summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/acpi_pad.c36
-rw-r--r--drivers/acpi/acpica/acconfig.h4
-rw-r--r--drivers/acpi/acpica/acevents.h4
-rw-r--r--drivers/acpi/acpica/acglobal.h8
-rw-r--r--drivers/acpi/acpica/achware.h6
-rw-r--r--drivers/acpi/acpica/evgpe.c115
-rw-r--r--drivers/acpi/acpica/evgpeblk.c14
-rw-r--r--drivers/acpi/acpica/evxface.c7
-rw-r--r--drivers/acpi/acpica/evxfevnt.c59
-rw-r--r--drivers/acpi/acpica/exsystem.c8
-rw-r--r--drivers/acpi/acpica/hwgpe.c94
-rw-r--r--drivers/acpi/acpica/hwvalid.c12
-rw-r--r--drivers/acpi/acpica/nsinit.c9
-rw-r--r--drivers/acpi/apei/apei-base.c1
-rw-r--r--drivers/acpi/atomicio.c1
-rw-r--r--drivers/acpi/blacklist.c8
-rw-r--r--drivers/acpi/button.c4
-rw-r--r--drivers/acpi/fan.c3
-rw-r--r--drivers/acpi/processor_driver.c5
-rw-r--r--drivers/acpi/sleep.c34
-rw-r--r--drivers/acpi/system.c6
-rw-r--r--drivers/acpi/wakeup.c20
-rw-r--r--drivers/block/cciss_scsi.c1
-rw-r--r--drivers/block/cpqarray.c6
-rw-r--r--drivers/block/drbd/drbd_main.c2
-rw-r--r--drivers/block/drbd/drbd_nl.c6
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c23
-rw-r--r--drivers/char/sysrq.c8
-rw-r--r--drivers/char/tpm/tpm.h1
-rw-r--r--drivers/clocksource/sh_cmt.c2
-rw-r--r--drivers/gpio/Kconfig2
-rw-r--r--drivers/gpio/Makefile6
-rw-r--r--drivers/hwmon/i5k_amb.c6
-rw-r--r--drivers/hwmon/k10temp.c14
-rw-r--r--drivers/hwmon/k8temp.c2
-rw-r--r--drivers/input/keyboard/Kconfig2
-rw-r--r--drivers/input/misc/pcf8574_keypad.c2
-rw-r--r--drivers/input/serio/Kconfig2
-rw-r--r--drivers/input/tablet/wacom_wac.c9
-rw-r--r--drivers/input/touchscreen/ad7877.c7
-rw-r--r--drivers/isdn/gigaset/asyncdata.c44
-rw-r--r--drivers/isdn/gigaset/capi.c405
-rw-r--r--drivers/isdn/gigaset/common.c36
-rw-r--r--drivers/isdn/gigaset/ev-layer.c4
-rw-r--r--drivers/isdn/gigaset/gigaset.h38
-rw-r--r--drivers/isdn/gigaset/i4l.c21
-rw-r--r--drivers/isdn/gigaset/isocdata.c72
-rw-r--r--drivers/isdn/hysdn/hysdn_net.c3
-rw-r--r--drivers/md/md.c38
-rw-r--r--drivers/md/md.h3
-rw-r--r--drivers/md/raid0.c21
-rw-r--r--drivers/md/raid0.h3
-rw-r--r--drivers/md/raid10.c46
-rw-r--r--drivers/md/raid10.h5
-rw-r--r--drivers/md/raid5.c150
-rw-r--r--drivers/net/Kconfig2
-rw-r--r--drivers/net/bnx2.c11
-rw-r--r--drivers/net/cnic.c55
-rw-r--r--drivers/net/cpmac.c3
-rw-r--r--drivers/net/e1000/e1000_main.c17
-rw-r--r--drivers/net/ehea/ehea.h2
-rw-r--r--drivers/net/ehea/ehea_main.c9
-rw-r--r--drivers/net/enic/vnic_dev.c2
-rw-r--r--drivers/net/gianfar.c25
-rw-r--r--drivers/net/ixgbe/ixgbe_ethtool.c37
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c4
-rw-r--r--drivers/net/ixgbe/ixgbe_phy.c2
-rw-r--r--drivers/net/lib82596.c2
-rw-r--r--drivers/net/mipsnet.c2
-rw-r--r--drivers/net/netxen/netxen_nic_ctx.c3
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c4
-rw-r--r--drivers/net/netxen/netxen_nic_init.c13
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c1
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c18
-rw-r--r--drivers/net/phy/lxt.c1
-rw-r--r--drivers/net/sky2.c19
-rw-r--r--drivers/net/tulip/de2104x.c5
-rw-r--r--drivers/net/ucc_geth.c2
-rw-r--r--drivers/net/usb/hso.c1
-rw-r--r--drivers/net/vxge/vxge-main.c29
-rw-r--r--drivers/net/wireless/ath/ath5k/attach.c1
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c15
-rw-r--r--drivers/net/wireless/hostap/hostap_hw.c13
-rw-r--r--drivers/net/wireless/hostap/hostap_wlan.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c9
-rw-r--r--drivers/net/wireless/libertas_tf/main.c2
-rw-r--r--drivers/net/wireless/p54/p54pci.c2
-rw-r--r--drivers/pci/intel-iommu.c14
-rw-r--r--drivers/pci/pci.c1
-rw-r--r--drivers/pci/pcie/pme/pcie_pme.c19
-rw-r--r--drivers/rtc/rtc-davinci.c1
-rw-r--r--drivers/rtc/rtc-ds1307.c4
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c143
-rw-r--r--drivers/serial/serial_cs.c1
-rw-r--r--drivers/staging/batman-adv/bat_sysfs.c24
-rw-r--r--drivers/staging/batman-adv/device.c2
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9111.c9
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidda.c3
-rw-r--r--drivers/staging/hv/channel_mgmt.c41
-rw-r--r--drivers/staging/hv/hv_utils.c28
-rw-r--r--drivers/staging/hv/vmbus.h2
-rw-r--r--drivers/staging/hv/vmbus_drv.c3
-rw-r--r--drivers/staging/mrst-touchscreen/intel-mid-touch.c2
-rw-r--r--drivers/staging/rt2860/usb_main_dev.c1
-rw-r--r--drivers/staging/rtl8187se/r8180_core.c2
-rw-r--r--drivers/staging/rtl8192su/r8192U_core.c43
-rw-r--r--drivers/staging/rtl8192u/r8192U_core.c2
-rw-r--r--drivers/staging/tm6000/tm6000-alsa.c1
-rw-r--r--drivers/staging/tm6000/tm6000-cards.c1
-rw-r--r--drivers/staging/tm6000/tm6000-core.c1
-rw-r--r--drivers/staging/tm6000/tm6000-dvb.c1
-rw-r--r--drivers/staging/usbip/usbip_common.c46
-rw-r--r--drivers/staging/wlags49_h2/wl_enc.c1
-rw-r--r--drivers/staging/wlags49_h2/wl_sysfs.h4
-rw-r--r--drivers/usb/core/driver.c13
-rw-r--r--drivers/usb/core/message.c7
-rw-r--r--drivers/usb/gadget/f_eem.c3
-rw-r--r--drivers/usb/gadget/f_mass_storage.c194
-rw-r--r--drivers/usb/gadget/g_ffs.c11
-rw-r--r--drivers/usb/gadget/printer.c32
-rw-r--r--drivers/usb/gadget/s3c2410_udc.c6
-rw-r--r--drivers/usb/gadget/u_serial.c16
-rw-r--r--drivers/usb/host/ehci-mxc.c13
-rw-r--r--drivers/usb/host/isp1362-hcd.c15
-rw-r--r--drivers/usb/host/r8a66597-hcd.c2
-rw-r--r--drivers/usb/host/xhci-ring.c62
-rw-r--r--drivers/usb/musb/musb_core.c13
-rw-r--r--drivers/usb/musb/musb_core.h6
-rw-r--r--drivers/usb/musb/musbhsdma.c13
-rw-r--r--drivers/usb/otg/ulpi.c17
-rw-r--r--drivers/usb/serial/ftdi_sio.c1
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h7
-rw-r--r--drivers/usb/serial/qcserial.c3
-rw-r--r--drivers/video/geode/gxfb_core.c20
-rw-r--r--drivers/video/geode/lxfb_core.c18
-rw-r--r--drivers/video/nuc900fb.c2
-rw-r--r--drivers/video/omap/lcdc.c14
-rw-r--r--drivers/video/omap/rfbi.c5
-rw-r--r--drivers/virtio/virtio_pci.c3
-rw-r--r--drivers/virtio/virtio_ring.c2
-rw-r--r--drivers/watchdog/at32ap700x_wdt.c16
-rw-r--r--drivers/watchdog/imx2_wdt.c1
146 files changed, 1619 insertions, 1075 deletions
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index d269a8f3329c..446aced33aff 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -46,6 +46,8 @@ static unsigned long power_saving_mwait_eax;
static unsigned char tsc_detected_unstable;
static unsigned char tsc_marked_unstable;
+static unsigned char lapic_detected_unstable;
+static unsigned char lapic_marked_unstable;
static void power_saving_mwait_init(void)
{
@@ -75,9 +77,6 @@ static void power_saving_mwait_init(void)
power_saving_mwait_eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) |
(highest_subcstate - 1);
- for_each_online_cpu(i)
- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &i);
-
#if defined(CONFIG_GENERIC_TIME) && defined(CONFIG_X86)
switch (boot_cpu_data.x86_vendor) {
case X86_VENDOR_AMD:
@@ -86,13 +85,15 @@ static void power_saving_mwait_init(void)
* AMD Fam10h TSC will tick in all
* C/P/S0/S1 states when this bit is set.
*/
- if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
- return;
-
- /*FALL THROUGH*/
+ if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
+ tsc_detected_unstable = 1;
+ if (!boot_cpu_has(X86_FEATURE_ARAT))
+ lapic_detected_unstable = 1;
+ break;
default:
- /* TSC could halt in idle */
+ /* TSC & LAPIC could halt in idle */
tsc_detected_unstable = 1;
+ lapic_detected_unstable = 1;
}
#endif
}
@@ -180,10 +181,20 @@ static int power_saving_thread(void *data)
mark_tsc_unstable("TSC halts in idle");
tsc_marked_unstable = 1;
}
+ if (lapic_detected_unstable && !lapic_marked_unstable) {
+ int i;
+ /* LAPIC could halt in idle, so notify users */
+ for_each_online_cpu(i)
+ clockevents_notify(
+ CLOCK_EVT_NOTIFY_BROADCAST_ON,
+ &i);
+ lapic_marked_unstable = 1;
+ }
local_irq_disable();
cpu = smp_processor_id();
- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
- &cpu);
+ if (lapic_marked_unstable)
+ clockevents_notify(
+ CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
stop_critical_timings();
__monitor((void *)&current_thread_info()->flags, 0, 0);
@@ -192,8 +203,9 @@ static int power_saving_thread(void *data)
__mwait(power_saving_mwait_eax, 1);
start_critical_timings();
- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
- &cpu);
+ if (lapic_marked_unstable)
+ clockevents_notify(
+ CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
local_irq_enable();
if (jiffies > expire_time) {
diff --git a/drivers/acpi/acpica/acconfig.h b/drivers/acpi/acpica/acconfig.h
index 33181ad350d5..b17d8de9f6ff 100644
--- a/drivers/acpi/acpica/acconfig.h
+++ b/drivers/acpi/acpica/acconfig.h
@@ -119,6 +119,10 @@
#define ACPI_MAX_LOOP_ITERATIONS 0xFFFF
+/* Maximum sleep allowed via Sleep() operator */
+
+#define ACPI_MAX_SLEEP 20000 /* Two seconds */
+
/******************************************************************************
*
* ACPI Specification constants (Do not change unless the specification changes)
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h
index 64d1e5c2d4ae..c3f43daa8be3 100644
--- a/drivers/acpi/acpica/acevents.h
+++ b/drivers/acpi/acpica/acevents.h
@@ -80,10 +80,6 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list);
acpi_status
acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info);
-acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info);
-
-acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info);
-
struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
u32 gpe_number);
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 9070f1fe8f17..899d68afc3c5 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -125,6 +125,14 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_aml_debug_object, FALSE);
*/
u8 ACPI_INIT_GLOBAL(acpi_gbl_copy_dsdt_locally, FALSE);
+/*
+ * Optionally truncate I/O addresses to 16 bits. Provides compatibility
+ * with other ACPI implementations. NOTE: During ACPICA initialization,
+ * this value is set to TRUE if any Windows OSI strings have been
+ * requested by the BIOS.
+ */
+u8 ACPI_INIT_GLOBAL(acpi_gbl_truncate_io_addresses, FALSE);
+
/* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */
struct acpi_table_fadt acpi_gbl_FADT;
diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h
index 5900f135dc6d..32391588e163 100644
--- a/drivers/acpi/acpica/achware.h
+++ b/drivers/acpi/acpica/achware.h
@@ -90,7 +90,11 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width);
/*
* hwgpe - GPE support
*/
-acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info);
+u32 acpi_hw_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info,
+ struct acpi_gpe_register_info *gpe_register_info);
+
+acpi_status
+acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action);
acpi_status
acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info *gpe_event_info);
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index a221ad404167..7c2c336006a1 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -69,7 +69,7 @@ acpi_status
acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
{
struct acpi_gpe_register_info *gpe_register_info;
- u8 register_bit;
+ u32 register_bit;
ACPI_FUNCTION_TRACE(ev_update_gpe_enable_masks);
@@ -78,9 +78,8 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
return_ACPI_STATUS(AE_NOT_EXIST);
}
- register_bit = (u8)
- (1 <<
- (gpe_event_info->gpe_number - gpe_register_info->base_gpe_number));
+ register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
+ gpe_register_info);
/* Clear the wake/run bits up front */
@@ -100,106 +99,6 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
return_ACPI_STATUS(AE_OK);
}
-/*******************************************************************************
- *
- * FUNCTION: acpi_ev_enable_gpe
- *
- * PARAMETERS: gpe_event_info - GPE to enable
- *
- * RETURN: Status
- *
- * DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless
- * of type or number of references.
- *
- * Note: The GPE lock should be already acquired when this function is called.
- *
- ******************************************************************************/
-
-acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
-{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE(ev_enable_gpe);
-
-
- /*
- * We will only allow a GPE to be enabled if it has either an
- * associated method (_Lxx/_Exx) or a handler. Otherwise, the
- * GPE will be immediately disabled by acpi_ev_gpe_dispatch the
- * first time it fires.
- */
- if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) {
- return_ACPI_STATUS(AE_NO_HANDLER);
- }
-
- /* Ensure the HW enable masks are current */
-
- status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
-
- /* Clear the GPE (of stale events) */
-
- status = acpi_hw_clear_gpe(gpe_event_info);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
-
- /* Enable the requested GPE */
-
- status = acpi_hw_write_gpe_enable_reg(gpe_event_info);
- return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ev_disable_gpe
- *
- * PARAMETERS: gpe_event_info - GPE to disable
- *
- * RETURN: Status
- *
- * DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE,
- * regardless of the type or number of references.
- *
- * Note: The GPE lock should be already acquired when this function is called.
- *
- ******************************************************************************/
-
-acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
-{
- acpi_status status;
-
- ACPI_FUNCTION_TRACE(ev_disable_gpe);
-
-
- /*
- * Note: Always disable the GPE, even if we think that that it is already
- * disabled. It is possible that the AML or some other code has enabled
- * the GPE behind our back.
- */
-
- /* Ensure the HW enable masks are current */
-
- status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
-
- /*
- * Always H/W disable this GPE, even if we don't know the GPE type.
- * Simply clear the enable bit for this particular GPE, but do not
- * write out the current GPE enable mask since this may inadvertently
- * enable GPEs too early. An example is a rogue GPE that has arrived
- * during ACPICA initialization - possibly because AML or other code
- * has enabled the GPE.
- */
- status = acpi_hw_low_disable_gpe(gpe_event_info);
- return_ACPI_STATUS(status);
-}
-
/*******************************************************************************
*
@@ -451,10 +350,6 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
return_VOID;
}
- /* Update the GPE register masks for return to enabled state */
-
- (void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
-
/*
* Take a snapshot of the GPE info for this level - we copy the info to
* prevent a race condition with remove_handler/remove_block.
@@ -607,7 +502,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
* Disable the GPE, so it doesn't keep firing before the method has a
* chance to run (it runs asynchronously with interrupts enabled).
*/
- status = acpi_ev_disable_gpe(gpe_event_info);
+ status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Unable to disable GPE[0x%2X]",
@@ -644,7 +539,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
* Disable the GPE. The GPE will remain disabled a handler
* is installed or ACPICA is restarted.
*/
- status = acpi_ev_disable_gpe(gpe_event_info);
+ status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Unable to disable GPE[0x%2X]",
diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c
index 7c28f2d9fd35..341a38ce8aa6 100644
--- a/drivers/acpi/acpica/evgpeblk.c
+++ b/drivers/acpi/acpica/evgpeblk.c
@@ -500,6 +500,19 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;
gpe_event_info = &gpe_block->event_info[gpe_index];
+ gpe_number = gpe_index + gpe_block->block_base_number;
+
+ /*
+ * If the GPE has already been enabled for runtime
+ * signaling, make sure it remains enabled, but do not
+ * increment its reference counter.
+ */
+ if (gpe_event_info->runtime_count) {
+ acpi_set_gpe(gpe_device, gpe_number,
+ ACPI_GPE_ENABLE);
+ gpe_enabled_count++;
+ continue;
+ }
if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) {
wake_gpe_count++;
@@ -516,7 +529,6 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
/* Enable this GPE */
- gpe_number = gpe_index + gpe_block->block_base_number;
status = acpi_enable_gpe(gpe_device, gpe_number,
ACPI_GPE_TYPE_RUNTIME);
if (ACPI_FAILURE(status)) {
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c
index cc825023012a..4a531cdf7942 100644
--- a/drivers/acpi/acpica/evxface.c
+++ b/drivers/acpi/acpica/evxface.c
@@ -719,13 +719,6 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
handler->context = context;
handler->method_node = gpe_event_info->dispatch.method_node;
- /* Disable the GPE before installing the handler */
-
- status = acpi_ev_disable_gpe(gpe_event_info);
- if (ACPI_FAILURE (status)) {
- goto unlock_and_exit;
- }
-
/* Install the handler */
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index d5a5efc043bf..d97b8dce1668 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -210,6 +210,44 @@ ACPI_EXPORT_SYMBOL(acpi_enable_event)
/*******************************************************************************
*
+ * FUNCTION: acpi_clear_and_enable_gpe
+ *
+ * PARAMETERS: gpe_event_info - GPE to enable
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Clear the given GPE from stale events and enable it.
+ *
+ ******************************************************************************/
+static acpi_status
+acpi_clear_and_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
+{
+ acpi_status status;
+
+ /*
+ * We will only allow a GPE to be enabled if it has either an
+ * associated method (_Lxx/_Exx) or a handler. Otherwise, the
+ * GPE will be immediately disabled by acpi_ev_gpe_dispatch the
+ * first time it fires.
+ */
+ if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) {
+ return_ACPI_STATUS(AE_NO_HANDLER);
+ }
+
+ /* Clear the GPE (of stale events) */
+ status = acpi_hw_clear_gpe(gpe_event_info);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ /* Enable the requested GPE */
+ status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);
+
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_set_gpe
*
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
@@ -249,11 +287,11 @@ acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
switch (action) {
case ACPI_GPE_ENABLE:
- status = acpi_ev_enable_gpe(gpe_event_info);
+ status = acpi_clear_and_enable_gpe(gpe_event_info);
break;
case ACPI_GPE_DISABLE:
- status = acpi_ev_disable_gpe(gpe_event_info);
+ status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
break;
default:
@@ -316,7 +354,11 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
gpe_event_info->runtime_count++;
if (gpe_event_info->runtime_count == 1) {
- status = acpi_ev_enable_gpe(gpe_event_info);
+ status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
+ if (ACPI_SUCCESS(status)) {
+ status = acpi_clear_and_enable_gpe(gpe_event_info);
+ }
+
if (ACPI_FAILURE(status)) {
gpe_event_info->runtime_count--;
goto unlock_and_exit;
@@ -343,7 +385,7 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
*/
gpe_event_info->wakeup_count++;
if (gpe_event_info->wakeup_count == 1) {
- (void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
+ status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
}
}
@@ -403,7 +445,12 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type
gpe_event_info->runtime_count--;
if (!gpe_event_info->runtime_count) {
- status = acpi_ev_disable_gpe(gpe_event_info);
+ status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
+ if (ACPI_SUCCESS(status)) {
+ status = acpi_hw_low_set_gpe(gpe_event_info,
+ ACPI_GPE_DISABLE);
+ }
+
if (ACPI_FAILURE(status)) {
gpe_event_info->runtime_count++;
goto unlock_and_exit;
@@ -424,7 +471,7 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type
gpe_event_info->wakeup_count--;
if (!gpe_event_info->wakeup_count) {
- (void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
+ status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
}
}
diff --git a/drivers/acpi/acpica/exsystem.c b/drivers/acpi/acpica/exsystem.c
index 6d32e09327f1..675aaa91a770 100644
--- a/drivers/acpi/acpica/exsystem.c
+++ b/drivers/acpi/acpica/exsystem.c
@@ -201,6 +201,14 @@ acpi_status acpi_ex_system_do_sleep(u64 how_long)
acpi_ex_relinquish_interpreter();
+ /*
+ * For compatibility with other ACPI implementations and to prevent
+ * accidental deep sleeps, limit the sleep time to something reasonable.
+ */
+ if (how_long > ACPI_MAX_SLEEP) {
+ how_long = ACPI_MAX_SLEEP;
+ }
+
acpi_os_sleep(how_long);
/* And now we must get the interpreter again */
diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c
index bd72319a38f0..3450309c2786 100644
--- a/drivers/acpi/acpica/hwgpe.c
+++ b/drivers/acpi/acpica/hwgpe.c
@@ -57,21 +57,47 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
/******************************************************************************
*
- * FUNCTION: acpi_hw_low_disable_gpe
+ * FUNCTION: acpi_hw_gpe_register_bit
+ *
+ * PARAMETERS: gpe_event_info - Info block for the GPE
+ * gpe_register_info - Info block for the GPE register
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Compute GPE enable mask with one bit corresponding to the given
+ * GPE set.
+ *
+ ******************************************************************************/
+
+u32 acpi_hw_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info,
+ struct acpi_gpe_register_info *gpe_register_info)
+{
+ return (u32)1 << (gpe_event_info->gpe_number -
+ gpe_register_info->base_gpe_number);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION: acpi_hw_low_set_gpe
*
* PARAMETERS: gpe_event_info - Info block for the GPE to be disabled
+ * action - Enable or disable
*
* RETURN: Status
*
- * DESCRIPTION: Disable a single GPE in the enable register.
+ * DESCRIPTION: Enable or disable a single GPE in its enable register.
*
******************************************************************************/
-acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
+acpi_status
+acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action)
{
struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
u32 enable_mask;
+ u32 register_bit;
+
+ ACPI_FUNCTION_ENTRY();
/* Get the info block for the entire GPE register */
@@ -87,11 +113,27 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
return (status);
}
- /* Clear just the bit that corresponds to this GPE */
+ /* Set ot clear just the bit that corresponds to this GPE */
- ACPI_CLEAR_BIT(enable_mask, ((u32)1 <<
- (gpe_event_info->gpe_number -
- gpe_register_info->base_gpe_number)));
+ register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
+ gpe_register_info);
+ switch (action) {
+ case ACPI_GPE_COND_ENABLE:
+ if (!(register_bit & gpe_register_info->enable_for_run))
+ return (AE_BAD_PARAMETER);
+
+ case ACPI_GPE_ENABLE:
+ ACPI_SET_BIT(enable_mask, register_bit);
+ break;
+
+ case ACPI_GPE_DISABLE:
+ ACPI_CLEAR_BIT(enable_mask, register_bit);
+ break;
+
+ default:
+ ACPI_ERROR((AE_INFO, "Invalid action\n"));
+ return (AE_BAD_PARAMETER);
+ }
/* Write the updated enable mask */
@@ -116,23 +158,11 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
acpi_status
acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info)
{
- struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
ACPI_FUNCTION_ENTRY();
- /* Get the info block for the entire GPE register */
-
- gpe_register_info = gpe_event_info->register_info;
- if (!gpe_register_info) {
- return (AE_NOT_EXIST);
- }
-
- /* Write the entire GPE (runtime) enable register */
-
- status = acpi_hw_write(gpe_register_info->enable_for_run,
- &gpe_register_info->enable_address);
-
+ status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_COND_ENABLE);
return (status);
}
@@ -150,21 +180,28 @@ acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info)
acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
{
+ struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
- u8 register_bit;
+ u32 register_bit;
ACPI_FUNCTION_ENTRY();
- register_bit = (u8)(1 <<
- (gpe_event_info->gpe_number -
- gpe_event_info->register_info->base_gpe_number));
+ /* Get the info block for the entire GPE register */
+
+ gpe_register_info = gpe_event_info->register_info;
+ if (!gpe_register_info) {
+ return (AE_NOT_EXIST);
+ }
+
+ register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
+ gpe_register_info);
/*
* Write a one to the appropriate bit in the status register to
* clear this GPE.
*/
status = acpi_hw_write(register_bit,
- &gpe_event_info->register_info->status_address);
+ &gpe_register_info->status_address);
return (status);
}
@@ -187,7 +224,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
acpi_event_status * event_status)
{
u32 in_byte;
- u8 register_bit;
+ u32 register_bit;
struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
acpi_event_status local_event_status = 0;
@@ -204,9 +241,8 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
/* Get the register bitmask for this GPE */
- register_bit = (u8)(1 <<
- (gpe_event_info->gpe_number -
- gpe_event_info->register_info->base_gpe_number));
+ register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
+ gpe_register_info);
/* GPE currently enabled? (enabled for runtime?) */
diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c
index c10d587c1641..e1d9c777b213 100644
--- a/drivers/acpi/acpica/hwvalid.c
+++ b/drivers/acpi/acpica/hwvalid.c
@@ -222,6 +222,12 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width)
u32 one_byte;
u32 i;
+ /* Truncate address to 16 bits if requested */
+
+ if (acpi_gbl_truncate_io_addresses) {
+ address &= ACPI_UINT16_MAX;
+ }
+
/* Validate the entire request and perform the I/O */
status = acpi_hw_validate_io_request(address, width);
@@ -279,6 +285,12 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width)
acpi_status status;
u32 i;
+ /* Truncate address to 16 bits if requested */
+
+ if (acpi_gbl_truncate_io_addresses) {
+ address &= ACPI_UINT16_MAX;
+ }
+
/* Validate the entire request and perform the I/O */
status = acpi_hw_validate_io_request(address, width);
diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c
index 9bd6f050f299..4e5272c313e0 100644
--- a/drivers/acpi/acpica/nsinit.c
+++ b/drivers/acpi/acpica/nsinit.c
@@ -193,6 +193,15 @@ acpi_status acpi_ns_initialize_devices(void)
acpi_ns_init_one_device, NULL, &info,
NULL);
+ /*
+ * Any _OSI requests should be completed by now. If the BIOS has
+ * requested any Windows OSI strings, we will always truncate
+ * I/O addresses to 16 bits -- for Windows compatibility.
+ */
+ if (acpi_gbl_osi_data >= ACPI_OSI_WIN_2000) {
+ acpi_gbl_truncate_io_addresses = TRUE;
+ }
+
ACPI_FREE(info.evaluate_info);
if (ACPI_FAILURE(status)) {
goto error_exit;
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c
index db3946e9c66b..216e1e948ff6 100644
--- a/drivers/acpi/apei/apei-base.c
+++ b/drivers/acpi/apei/apei-base.c
@@ -34,6 +34,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/acpi.h>
+#include <linux/slab.h>
#include <linux/io.h>
#include <linux/kref.h>
#include <linux/rculist.h>
diff --git a/drivers/acpi/atomicio.c b/drivers/acpi/atomicio.c
index 814b19249616..8f8bd736d4ff 100644
--- a/drivers/acpi/atomicio.c
+++ b/drivers/acpi/atomicio.c
@@ -31,6 +31,7 @@
#include <linux/kref.h>
#include <linux/rculist.h>
#include <linux/interrupt.h>
+#include <linux/slab.h>
#include <acpi/atomicio.h>
#define ACPI_PFX "ACPI: "
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index 2815df66f6f7..01381be05e96 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -218,6 +218,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
},
},
{
+ .callback = dmi_disable_osi_vista,
+ .ident = "VGN-NS50B_L",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS50B_L"),
+ },
+ },
+ {
.callback = dmi_disable_osi_win7,
.ident = "ASUS K50IJ",
.matches = {
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index fd51c4ab4829..7d857dabdde4 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -425,7 +425,7 @@ static int acpi_button_add(struct acpi_device *device)
/* Button's GPE is run-wake GPE */
acpi_enable_gpe(device->wakeup.gpe_device,
device->wakeup.gpe_number,
- ACPI_GPE_TYPE_WAKE_RUN);
+ ACPI_GPE_TYPE_RUNTIME);
device->wakeup.run_wake_count++;
device->wakeup.state.enabled = 1;
}
@@ -449,7 +449,7 @@ static int acpi_button_remove(struct acpi_device *device, int type)
if (device->wakeup.flags.valid) {
acpi_disable_gpe(device->wakeup.gpe_device,
device->wakeup.gpe_number,
- ACPI_GPE_TYPE_WAKE_RUN);
+ ACPI_GPE_TYPE_RUNTIME);
device->wakeup.run_wake_count--;
device->wakeup.state.enabled = 0;
}
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index acf2ab249842..8a3b840c0bb2 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -347,7 +347,6 @@ static int __init acpi_fan_init(void)
{
int result = 0;
-
#ifdef CONFIG_ACPI_PROCFS
acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir);
if (!acpi_fan_dir)
@@ -356,7 +355,9 @@ static int __init acpi_fan_init(void)
result = acpi_bus_register_driver(&acpi_fan_driver);
if (result < 0) {
+#ifdef CONFIG_ACPI_PROCFS
remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir);
+#endif
return -ENODEV;
}
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index b1034a9ada4e..38ea0cc6dc49 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -581,6 +581,11 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
return 0;
}
+#ifdef CONFIG_SMP
+ if (pr->id >= setup_max_cpus && pr->id != 0)
+ return 0;
+#endif
+
BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
/*
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 3fb4bdea7e06..5b7c52e4a00f 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -114,6 +114,8 @@ static int __acpi_pm_prepare(void)
{
int error = acpi_sleep_prepare(acpi_target_sleep_state);
+ suspend_nvs_save();
+
if (error)
acpi_target_sleep_state = ACPI_STATE_S0;
return error;
@@ -143,6 +145,9 @@ static void acpi_pm_finish(void)
{
u32 acpi_state = acpi_target_sleep_state;
+ suspend_nvs_free();
+ acpi_ec_unblock_transactions();
+
if (acpi_state == ACPI_STATE_S0)
return;
@@ -192,6 +197,11 @@ static int acpi_suspend_begin(suspend_state_t pm_state)
u32 acpi_state = acpi_suspend_states[pm_state];
int error = 0;
+ error = suspend_nvs_alloc();
+
+ if (error)
+ return error;
+
if (sleep_states[acpi_state]) {
acpi_target_sleep_state = acpi_state;
acpi_sleep_tts_switch(acpi_target_sleep_state);
@@ -269,12 +279,13 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
if (acpi_state == ACPI_STATE_S3)
acpi_restore_state_mem();
+ suspend_nvs_restore();
+
return ACPI_SUCCESS(status) ? 0 : -EFAULT;
}
static void acpi_suspend_finish(void)
{
- acpi_ec_unblock_transactions();
acpi_pm_finish();
}
@@ -404,7 +415,7 @@ static int acpi_hibernation_begin(void)
{
int error;
- error = s4_no_nvs ? 0 : hibernate_nvs_alloc();
+ error = s4_no_nvs ? 0 : suspend_nvs_alloc();
if (!error) {
acpi_target_sleep_state = ACPI_STATE_S4;
acpi_sleep_tts_switch(acpi_target_sleep_state);
@@ -418,7 +429,7 @@ static int acpi_hibernation_pre_snapshot(void)
int error = acpi_pm_prepare();
if (!error)
- hibernate_nvs_save();
+ suspend_nvs_save();
return error;
}
@@ -441,13 +452,6 @@ static int acpi_hibernation_enter(void)
return ACPI_SUCCESS(status) ? 0 : -EFAULT;
}
-static void acpi_hibernation_finish(void)
-{
- hibernate_nvs_free();
- acpi_ec_unblock_transactions();
- acpi_pm_finish();
-}
-
static void acpi_hibernation_leave(void)
{
/*
@@ -464,7 +468,7 @@ static void acpi_hibernation_leave(void)
panic("ACPI S4 hardware signature mismatch");
}
/* Restore the NVS memory area */
- hibernate_nvs_restore();
+ suspend_nvs_restore();
/* Allow EC transactions to happen. */
acpi_ec_unblock_transactions_early();
}
@@ -479,7 +483,7 @@ static struct platform_hibernation_ops acpi_hibernation_ops = {
.begin = acpi_hibernation_begin,
.end = acpi_pm_end,
.pre_snapshot = acpi_hibernation_pre_snapshot,
- .finish = acpi_hibernation_finish,
+ .finish = acpi_pm_finish,
.prepare = acpi_pm_prepare,
.enter = acpi_hibernation_enter,
.leave = acpi_hibernation_leave,
@@ -507,7 +511,7 @@ static int acpi_hibernation_begin_old(void)
if (!error) {
if (!s4_no_nvs)
- error = hibernate_nvs_alloc();
+ error = suspend_nvs_alloc();
if (!error)
acpi_target_sleep_state = ACPI_STATE_S4;
}
@@ -517,7 +521,7 @@ static int acpi_hibernation_begin_old(void)
static int acpi_hibernation_pre_snapshot_old(void)
{
acpi_pm_freeze();
- hibernate_nvs_save();
+ suspend_nvs_save();
return 0;
}
@@ -529,8 +533,8 @@ static struct platform_hibernation_ops acpi_hibernation_ops_old = {
.begin = acpi_hibernation_begin_old,
.end = acpi_pm_end,
.pre_snapshot = acpi_hibernation_pre_snapshot_old,
- .finish = acpi_hibernation_finish,
.prepare = acpi_pm_freeze,
+ .finish = acpi_pm_finish,
.enter = acpi_hibernation_enter,
.leave = acpi_hibernation_leave,
.pre_restore = acpi_pm_freeze,
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index c79e789ed03a..f8db50a0941c 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -388,10 +388,12 @@ static ssize_t counter_set(struct kobject *kobj,
if (index < num_gpes) {
if (!strcmp(buf, "disable\n") &&
(status & ACPI_EVENT_FLAG_ENABLED))
- result = acpi_set_gpe(handle, index, ACPI_GPE_DISABLE);
+ result = acpi_disable_gpe(handle, index,
+ ACPI_GPE_TYPE_RUNTIME);
else if (!strcmp(buf, "enable\n") &&
!(status & ACPI_EVENT_FLAG_ENABLED))
- result = acpi_set_gpe(handle, index, ACPI_GPE_ENABLE);
+ result = acpi_enable_gpe(handle, index,
+ ACPI_GPE_TYPE_RUNTIME);
else if (!strcmp(buf, "clear\n") &&
(status & ACPI_EVENT_FLAG_SET))
result = acpi_clear_gpe(handle, index);
diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c
index 4b9d339a6e28..388747a7ef4f 100644
--- a/drivers/acpi/wakeup.c
+++ b/drivers/acpi/wakeup.c
@@ -64,16 +64,13 @@ void acpi_enable_wakeup_device(u8 sleep_state)
struct acpi_device *dev =
container_of(node, struct acpi_device, wakeup_list);
- if (!dev->wakeup.flags.valid)
- continue;
-
- if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count)
+ if (!dev->wakeup.flags.valid || !dev->wakeup.state.enabled
|| sleep_state > (u32) dev->wakeup.sleep_state)
continue;
/* The wake-up power should have been enabled already. */
- acpi_set_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
- ACPI_GPE_ENABLE);
+ acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
+ ACPI_GPE_TYPE_WAKE);
}
}
@@ -96,6 +93,8 @@ void acpi_disable_wakeup_device(u8 sleep_state)
|| (sleep_state > (u32) dev->wakeup.sleep_state))
continue;
+ acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
+ ACPI_GPE_TYPE_WAKE);
acpi_disable_wakeup_device_power(dev);
}
}
@@ -109,13 +108,8 @@ int __init acpi_wakeup_device_init(void)
struct acpi_device *dev = container_of(node,
struct acpi_device,
wakeup_list);
- /* In case user doesn't load button driver */
- if (!dev->wakeup.flags.always_enabled ||
- dev->wakeup.state.enabled)
- continue;
- acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
- ACPI_GPE_TYPE_WAKE);
- dev->wakeup.state.enabled = 1;
+ if (dev->wakeup.flags.always_enabled)
+ dev->wakeup.state.enabled = 1;
}
mutex_unlock(&acpi_device_lock);
return 0;
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 3381505c8a6c..72dae92f3cab 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -861,6 +861,7 @@ cciss_scsi_detect(int ctlr)
sh->n_io_port = 0; // I don't think we use these two...
sh->this_id = SELF_SCSI_ID;
sh->sg_tablesize = hba[ctlr]->maxsgentries;
+ sh->max_cmd_len = MAX_COMMAND_SIZE;
((struct cciss_scsi_adapter_data_t *)
hba[ctlr]->scsi_ctlr)->scsi_host = sh;
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 91d11631cec9..abb4ec6690fc 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -386,7 +386,7 @@ static void __devexit cpqarray_remove_one_eisa (int i)
}
/* pdev is NULL for eisa */
-static int __init cpqarray_register_ctlr( int i, struct pci_dev *pdev)
+static int __devinit cpqarray_register_ctlr( int i, struct pci_dev *pdev)
{
struct request_queue *q;
int j;
@@ -503,7 +503,7 @@ Enomem4:
return -1;
}
-static int __init cpqarray_init_one( struct pci_dev *pdev,
+static int __devinit cpqarray_init_one( struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int i;
@@ -740,7 +740,7 @@ __setup("smart2=", cpqarray_setup);
/*
* Find an EISA controller's signature. Set up an hba if we find it.
*/
-static int __init cpqarray_eisa_detect(void)
+static int __devinit cpqarray_eisa_detect(void)
{
int i=0, j;
__u32 board_id;
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 6b077f93acc6..7258c95e895e 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -1236,8 +1236,6 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
/* Last part of the attaching process ... */
if (ns.conn >= C_CONNECTED &&
os.disk == D_ATTACHING && ns.disk == D_NEGOTIATING) {
- kfree(mdev->p_uuid); /* We expect to receive up-to-date UUIDs soon. */
- mdev->p_uuid = NULL; /* ...to not use the old ones in the mean time */
drbd_send_sizes(mdev, 0, 0); /* to start sync... */
drbd_send_uuids(mdev);
drbd_send_state(mdev);
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 632e3245d1bb..2151f18b21de 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1114,6 +1114,12 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
mdev->new_state_tmp.i = ns.i;
ns.i = os.i;
ns.disk = D_NEGOTIATING;
+
+ /* We expect to receive up-to-date UUIDs soon.
+ To avoid a race in receive_state, free p_uuid while
+ holding req_lock. I.e. atomic with the state change */
+ kfree(mdev->p_uuid);
+ mdev->p_uuid = NULL;
}
rv = _drbd_set_state(mdev, ns, CS_VERBOSE, NULL);
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 35603dd4e6c5..094bdc355b1f 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -302,6 +302,12 @@ struct smi_info {
static int force_kipmid[SI_MAX_PARMS];
static int num_force_kipmid;
+#ifdef CONFIG_PCI
+static int pci_registered;
+#endif
+#ifdef CONFIG_PPC_OF
+static int of_registered;
+#endif
static unsigned int kipmid_max_busy_us[SI_MAX_PARMS];
static int num_max_busy_us;
@@ -1018,7 +1024,7 @@ static int ipmi_thread(void *data)
else if (smi_result == SI_SM_IDLE)
schedule_timeout_interruptible(100);
else
- schedule_timeout_interruptible(0);
+ schedule_timeout_interruptible(1);
}
return 0;
}
@@ -3314,6 +3320,8 @@ static __devinit int init_ipmi_si(void)
rv = pci_register_driver(&ipmi_pci_driver);
if (rv)
printk(KERN_ERR PFX "Unable to register PCI driver: %d\n", rv);
+ else
+ pci_registered = 1;
#endif
#ifdef CONFIG_ACPI
@@ -3330,6 +3338,7 @@ static __devinit int init_ipmi_si(void)
#ifdef CONFIG_PPC_OF
of_register_platform_driver(&ipmi_of_platform_driver);
+ of_registered = 1;
#endif
/* We prefer devices with interrupts, but in the case of a machine
@@ -3383,11 +3392,13 @@ static __devinit int init_ipmi_si(void)
if (unload_when_empty && list_empty(&smi_infos)) {
mutex_unlock(&smi_infos_lock);
#ifdef CONFIG_PCI
- pci_unregister_driver(&ipmi_pci_driver);
+ if (pci_registered)
+ pci_unregister_driver(&ipmi_pci_driver);
#endif
#ifdef CONFIG_PPC_OF
- of_unregister_platform_driver(&ipmi_of_platform_driver);
+ if (of_registered)
+ of_unregister_platform_driver(&ipmi_of_platform_driver);
#endif
driver_unregister(&ipmi_driver.driver);
printk(KERN_WARNING PFX
@@ -3478,14 +3489,16 @@ static __exit void cleanup_ipmi_si(void)
return;
#ifdef CONFIG_PCI
- pci_unregister_driver(&ipmi_pci_driver);
+ if (pci_registered)
+ pci_unregister_driver(&ipmi_pci_driver);
#endif
#ifdef CONFIG_ACPI
pnp_unregister_driver(&ipmi_pnp_driver);
#endif
#ifdef CONFIG_PPC_OF
- of_unregister_platform_driver(&ipmi_of_platform_driver);
+ if (of_registered)
+ of_unregister_platform_driver(&ipmi_of_platform_driver);
#endif
mutex_lock(&smi_infos_lock);
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 5d15630a5830..5d64e3acb000 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -580,8 +580,12 @@ static bool sysrq_filter(struct input_handle *handle, unsigned int type,
case KEY_RIGHTALT:
if (value)
sysrq_alt = code;
- else if (sysrq_down && code == sysrq_alt_use)
- sysrq_down = false;
+ else {
+ if (sysrq_down && code == sysrq_alt_use)
+ sysrq_down = false;
+
+ sysrq_alt = 0;
+ }
break;
case KEY_SYSRQ:
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 8e00b4ddd083..792868d24f2a 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -224,6 +224,7 @@ struct tpm_readpubek_params_out {
u8 algorithm[4];
u8 encscheme[2];
u8 sigscheme[2];
+ __be32 paramsize;
u8 parameters[12]; /*assuming RSA*/
__be32 keysize;
u8 modulus[256];
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index f3d3898898ed..717305d30444 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -449,7 +449,7 @@ static int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
clk_disable(p->clk);
/* TODO: calculate good shift from rate and counter bit width */
- cs->shift = 10;
+ cs->shift = 0;
cs->mult = clocksource_hz2mult(p->rate, cs->shift);
dev_info(&p->pdev->dev, "used as clock source\n");
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 724038dab4ca..7face915b963 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1,5 +1,5 @@
#
-# GPIO infrastructure and expanders
+# platform-neutral GPIO infrastructure and expanders
#
config ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 51c3cdd41b5a..e53dcff49b4f 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -1,4 +1,8 @@
-# gpio support: dedicated expander chips, etc
+# generic gpio support: dedicated expander chips, etc
+#
+# NOTE: platform-specific GPIO drivers don't belong in the
+# drivers/gpio directory; put them with other platform setup
+# code, IRQ controllers, board init, etc.
ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c
index e880e2c3871d..937983407e2a 100644
--- a/drivers/hwmon/i5k_amb.c
+++ b/drivers/hwmon/i5k_amb.c
@@ -289,6 +289,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
iattr->s_attr.dev_attr.show = show_label;
iattr->s_attr.index = k;
+ sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
res = device_create_file(&pdev->dev,
&iattr->s_attr.dev_attr);
if (res)
@@ -303,6 +304,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
iattr->s_attr.dev_attr.show = show_amb_temp;
iattr->s_attr.index = k;
+ sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
res = device_create_file(&pdev->dev,
&iattr->s_attr.dev_attr);
if (res)
@@ -318,6 +320,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
iattr->s_attr.dev_attr.show = show_amb_min;
iattr->s_attr.dev_attr.store = store_amb_min;
iattr->s_attr.index = k;
+ sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
res = device_create_file(&pdev->dev,
&iattr->s_attr.dev_attr);
if (res)
@@ -333,6 +336,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
iattr->s_attr.dev_attr.show = show_amb_mid;
iattr->s_attr.dev_attr.store = store_amb_mid;
iattr->s_attr.index = k;
+ sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
res = device_create_file(&pdev->dev,
&iattr->s_attr.dev_attr);
if (res)
@@ -348,6 +352,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
iattr->s_attr.dev_attr.show = show_amb_max;
iattr->s_attr.dev_attr.store = store_amb_max;
iattr->s_attr.index = k;
+ sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
res = device_create_file(&pdev->dev,
&iattr->s_attr.dev_attr);
if (res)
@@ -362,6 +367,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
iattr->s_attr.dev_attr.show = show_amb_alarm;
iattr->s_attr.index = k;
+ sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
res = device_create_file(&pdev->dev,
&iattr->s_attr.dev_attr);
if (res)
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
index 099a2138cdf6..da5a2404cd3e 100644
--- a/drivers/hwmon/k10temp.c
+++ b/drivers/hwmon/k10temp.c
@@ -112,11 +112,21 @@ static bool __devinit has_erratum_319(struct pci_dev *pdev)
if (pkg_type != CPUID_PKGTYPE_AM2R2_AM3)
return false;
- /* Differentiate between AM2+ (bad) and AM3 (good) */
+ /* DDR3 memory implies socket AM3, which is good */
pci_bus_read_config_dword(pdev->bus,
PCI_DEVFN(PCI_SLOT(pdev->devfn), 2),
REG_DCT0_CONFIG_HIGH, &reg_dram_cfg);
- return !(reg_dram_cfg & DDR3_MODE);
+ if (reg_dram_cfg & DDR3_MODE)
+ return false;
+
+ /*
+ * Unfortunately it is possible to run a socket AM3 CPU with DDR2
+ * memory. We blacklist all the cores which do exist in socket AM2+
+ * format. It still isn't perfect, as RB-C2 cores exist in both AM2+
+ * and AM3 formats, but that's the best we can do.
+ */
+ return boot_cpu_data.x86_model < 4 ||
+ (boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_mask <= 2);
}
static int __devinit k10temp_probe(struct pci_dev *pdev,
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
index 0ceb6d6200a3..f26acdb11681 100644
--- a/drivers/hwmon/k8temp.c
+++ b/drivers/hwmon/k8temp.c
@@ -120,7 +120,7 @@ static ssize_t show_temp(struct device *dev,
int temp;
struct k8temp_data *data = k8temp_update_device(dev);
- if (data->swap_core_select)
+ if (data->swap_core_select && (data->sensorsp & SEL_CORE))
core = core ? 0 : 1;
temp = TEMP_FROM_REG(data->temp[core][place]) + data->temp_offset;
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index d8fa5d724c57..0f9a4785d798 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -69,7 +69,7 @@ config KEYBOARD_ATARI
module will be called atakbd.
config KEYBOARD_ATKBD
- tristate "AT keyboard" if EMBEDDED || !X86
+ tristate "AT keyboard" if EMBEDDED || !X86 || X86_MRST
default y
select SERIO
select SERIO_LIBPS2
diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c
index 0ac47d2898ec..4b42ffc0532a 100644
--- a/drivers/input/misc/pcf8574_keypad.c
+++ b/drivers/input/misc/pcf8574_keypad.c
@@ -69,7 +69,7 @@ static irqreturn_t pcf8574_kp_irq_handler(int irq, void *dev_id)
unsigned char nextstate = read_state(lp);
if (lp->laststate != nextstate) {
- int key_down = nextstate <= ARRAY_SIZE(lp->btncode);
+ int key_down = nextstate < ARRAY_SIZE(lp->btncode);
unsigned short keycode = key_down ?
lp->btncode[nextstate] : lp->btncode[lp->laststate];
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index 3bfe8fafc6ad..256b9e9394dc 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -22,7 +22,7 @@ config SERIO_I8042
tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86
default y
depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \
- (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN
+ (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN && !X86_MRST
help
i8042 is the chip over which the standard AT keyboard and PS/2
mouse are connected to the computer. If you use these devices,
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index d564af58175c..415f6306105d 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -284,12 +284,13 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
(data[4] << 20) + (data[5] << 12) +
(data[6] << 4) + (data[7] >> 4);
- wacom->id[idx] = (data[2] << 4) | (data[3] >> 4);
+ wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) |
+ ((data[7] & 0x0f) << 20) | ((data[8] & 0xf0) << 12);
- switch (wacom->id[idx]) {
+ switch (wacom->id[idx] & 0xfffff) {
case 0x812: /* Inking pen */
case 0x801: /* Intuos3 Inking pen */
- case 0x20802: /* Intuos4 Classic Pen */
+ case 0x20802: /* Intuos4 Inking Pen */
case 0x012:
wacom->tool[idx] = BTN_TOOL_PENCIL;
break;
@@ -513,7 +514,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
input_report_abs(input, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
input_report_abs(input, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
- if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) |
+ if ((data[5] & 0x1f) | data[6] | (data[1] & 0x1f) |
data[2] | (data[3] & 0x1f) | data[4] | data[8] |
(data[7] & 0x01)) {
input_report_key(input, wacom->tool[1], 1);
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c
index 0d2d7e54b465..5f0221cffef9 100644
--- a/drivers/input/touchscreen/ad7877.c
+++ b/drivers/input/touchscreen/ad7877.c
@@ -679,6 +679,13 @@ static int __devinit ad7877_probe(struct spi_device *spi)
return -EINVAL;
}
+ spi->bits_per_word = 16;
+ err = spi_setup(spi);
+ if (err) {
+ dev_dbg(&spi->dev, "spi master doesn't support 16 bits/word\n");
+ return err;
+ }
+
ts = kzalloc(sizeof(struct ad7877), GFP_KERNEL);
input_dev = input_allocate_device();
if (!ts || !input_dev) {
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c
index c5016bd2d94f..c3b1dc3a13a0 100644
--- a/drivers/isdn/gigaset/asyncdata.c
+++ b/drivers/isdn/gigaset/asyncdata.c
@@ -126,26 +126,6 @@ static unsigned lock_loop(unsigned numbytes, struct inbuf_t *inbuf)
return numbytes;
}
-/* set up next receive skb for data mode
- */
-static void new_rcv_skb(struct bc_state *bcs)
-{
- struct cardstate *cs = bcs->cs;
- unsigned short hw_hdr_len = cs->hw_hdr_len;
-
- if (bcs->ignore) {
- bcs->skb = NULL;
- return;
- }
-
- bcs->skb = dev_alloc_skb(SBUFSIZE + hw_hdr_len);
- if (bcs->skb == NULL) {
- dev_warn(cs->dev, "could not allocate new skb\n");
- return;
- }
- skb_reserve(bcs->skb, hw_hdr_len);
-}
-
/* process a block of received bytes in HDLC data mode
* (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 == L2_HDLC)
* Collect HDLC frames, undoing byte stuffing and watching for DLE escapes.
@@ -159,8 +139,8 @@ static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf)
struct cardstate *cs = inbuf->cs;
struct bc_state *bcs = cs->bcs;
int inputstate = bcs->inputstate;
- __u16 fcs = bcs->fcs;
- struct sk_buff *skb = bcs->skb;
+ __u16 fcs = bcs->rx_fcs;
+ struct sk_buff *skb = bcs->rx_skb;
unsigned char *src = inbuf->data + inbuf->head;
unsigned procbytes = 0;
unsigned char c;
@@ -245,8 +225,7 @@ byte_stuff:
/* prepare reception of next frame */
inputstate &= ~INS_have_data;
- new_rcv_skb(bcs);
- skb = bcs->skb;
+ skb = gigaset_new_rx_skb(bcs);
} else {
/* empty frame (7E 7E) */
#ifdef CONFIG_GIGASET_DEBUG
@@ -255,8 +234,7 @@ byte_stuff:
if (!skb) {
/* skipped (?) */
gigaset_isdn_rcv_err(bcs);
- new_rcv_skb(bcs);
- skb = bcs->skb;
+ skb = gigaset_new_rx_skb(bcs);
}
}
@@ -279,11 +257,11 @@ byte_stuff:
#endif
inputstate |= INS_have_data;
if (skb) {
- if (skb->len == SBUFSIZE) {
+ if (skb->len >= bcs->rx_bufsize) {
dev_warn(cs->dev, "received packet too long\n");
dev_kfree_skb_any(skb);
/* skip remainder of packet */
- bcs->skb = skb = NULL;
+ bcs->rx_skb = skb = NULL;
} else {
*__skb_put(skb, 1) = c;
fcs = crc_ccitt_byte(fcs, c);
@@ -292,7 +270,7 @@ byte_stuff:
}
bcs->inputstate = inputstate;
- bcs->fcs = fcs;
+ bcs->rx_fcs = fcs;
return procbytes;
}
@@ -308,18 +286,18 @@ static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf)
struct cardstate *cs = inbuf->cs;
struct bc_state *bcs = cs->bcs;
int inputstate = bcs->inputstate;
- struct sk_buff *skb = bcs->skb;
+ struct sk_buff *skb = bcs->rx_skb;
unsigned char *src = inbuf->data + inbuf->head;
unsigned procbytes = 0;
unsigned char c;
if (!skb) {
/* skip this block */
- new_rcv_skb(bcs);
+ gigaset_new_rx_skb(bcs);
return numbytes;
}
- while (procbytes < numbytes && skb->len < SBUFSIZE) {
+ while (procbytes < numbytes && skb->len < bcs->rx_bufsize) {
c = *src++;
procbytes++;
@@ -343,7 +321,7 @@ static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf)
if (inputstate & INS_have_data) {
gigaset_skb_rcvd(bcs, skb);
inputstate &= ~INS_have_data;
- new_rcv_skb(bcs);
+ gigaset_new_rx_skb(bcs);
}
bcs->inputstate = inputstate;
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c
index 8f78f15c8ef7..6fbe8999c419 100644
--- a/drivers/isdn/gigaset/capi.c
+++ b/drivers/isdn/gigaset/capi.c
@@ -70,7 +70,7 @@
#define MAX_NUMBER_DIGITS 20
#define MAX_FMT_IE_LEN 20
-/* values for gigaset_capi_appl.connected */
+/* values for bcs->apconnstate */
#define APCONN_NONE 0 /* inactive/listening */
#define APCONN_SETUP 1 /* connecting */
#define APCONN_ACTIVE 2 /* B channel up */
@@ -80,10 +80,10 @@ struct gigaset_capi_appl {
struct list_head ctrlist;
struct gigaset_capi_appl *bcnext;
u16 id;
+ struct capi_register_params rp;
u16 nextMessageNumber;
u32 listenInfoMask;
u32 listenCIPmask;
- int connected;
};
/* CAPI specific controller data structure */
@@ -319,6 +319,39 @@ static const char *format_ie(const char *ie)
return result;
}
+/*
+ * emit DATA_B3_CONF message
+ */
+static void send_data_b3_conf(struct cardstate *cs, struct capi_ctr *ctr,
+ u16 appl, u16 msgid, int channel,
+ u16 handle, u16 info)
+{
+ struct sk_buff *cskb;
+ u8 *msg;
+
+ cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC);
+ if (!cskb) {
+ dev_err(cs->dev, "%s: out of memory\n", __func__);
+ return;
+ }
+ /* frequent message, avoid _cmsg overhead */
+ msg = __skb_put(cskb, CAPI_DATA_B3_CONF_LEN);
+ CAPIMSG_SETLEN(msg, CAPI_DATA_B3_CONF_LEN);
+ CAPIMSG_SETAPPID(msg, appl);
+ CAPIMSG_SETCOMMAND(msg, CAPI_DATA_B3);
+ CAPIMSG_SETSUBCOMMAND(msg, CAPI_CONF);
+ CAPIMSG_SETMSGID(msg, msgid);
+ CAPIMSG_SETCONTROLLER(msg, ctr->cnr);
+ CAPIMSG_SETPLCI_PART(msg, channel);
+ CAPIMSG_SETNCCI_PART(msg, 1);
+ CAPIMSG_SETHANDLE_CONF(msg, handle);
+ CAPIMSG_SETINFO_CONF(msg, info);
+
+ /* emit message */
+ dump_rawmsg(DEBUG_MCMD, __func__, msg);
+ capi_ctr_handle_message(ctr, appl, cskb);
+}
+
/*
* driver interface functions
@@ -339,7 +372,6 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb)
struct gigaset_capi_ctr *iif = cs->iif;
struct gigaset_capi_appl *ap = bcs->ap;
unsigned char *req = skb_mac_header(dskb);
- struct sk_buff *cskb;
u16 flags;
/* update statistics */
@@ -351,39 +383,22 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb)
}
/* don't send further B3 messages if disconnected */
- if (ap->connected < APCONN_ACTIVE) {
+ if (bcs->apconnstate < APCONN_ACTIVE) {
gig_dbg(DEBUG_LLDATA, "disconnected, discarding ack");
return;
}
- /* ToDo: honor unset "delivery confirmation" bit */
+ /*
+ * send DATA_B3_CONF if "delivery confirmation" bit was set in request;
+ * otherwise it has already been sent by do_data_b3_req()
+ */
flags = CAPIMSG_FLAGS(req);
-
- /* build DATA_B3_CONF message */
- cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC);
- if (!cskb) {
- dev_err(cs->dev, "%s: out of memory\n", __func__);
- return;
- }
- /* frequent message, avoid _cmsg overhead */
- CAPIMSG_SETLEN(cskb->data, CAPI_DATA_B3_CONF_LEN);
- CAPIMSG_SETAPPID(cskb->data, ap->id);
- CAPIMSG_SETCOMMAND(cskb->data, CAPI_DATA_B3);
- CAPIMSG_SETSUBCOMMAND(cskb->data, CAPI_CONF);
- CAPIMSG_SETMSGID(cskb->data, CAPIMSG_MSGID(req));
- CAPIMSG_SETCONTROLLER(cskb->data, iif->ctr.cnr);
- CAPIMSG_SETPLCI_PART(cskb->data, bcs->channel + 1);
- CAPIMSG_SETNCCI_PART(cskb->data, 1);
- CAPIMSG_SETHANDLE_CONF(cskb->data, CAPIMSG_HANDLE_REQ(req));
- if (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION)
- CAPIMSG_SETINFO_CONF(cskb->data,
- CapiFlagsNotSupportedByProtocol);
- else
- CAPIMSG_SETINFO_CONF(cskb->data, CAPI_NOERROR);
-
- /* emit message */
- dump_rawmsg(DEBUG_LLDATA, "DATA_B3_CONF", cskb->data);
- capi_ctr_handle_message(&iif->ctr, ap->id, cskb);
+ if (flags & CAPI_FLAGS_DELIVERY_CONFIRMATION)
+ send_data_b3_conf(cs, &iif->ctr, ap->id, CAPIMSG_MSGID(req),
+ bcs->channel + 1, CAPIMSG_HANDLE_REQ(req),
+ (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION) ?
+ CapiFlagsNotSupportedByProtocol :
+ CAPI_NOERROR);
}
EXPORT_SYMBOL_GPL(gigaset_skb_sent);
@@ -412,7 +427,7 @@ void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb)
}
/* don't send further B3 messages if disconnected */
- if (ap->connected < APCONN_ACTIVE) {
+ if (bcs->apconnstate < APCONN_ACTIVE) {
gig_dbg(DEBUG_LLDATA, "disconnected, discarding data");
dev_kfree_skb_any(skb);
return;
@@ -484,6 +499,7 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
u32 actCIPmask;
struct sk_buff *skb;
unsigned int msgsize;
+ unsigned long flags;
int i;
/*
@@ -608,7 +624,14 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
format_ie(iif->hcmsg.CalledPartyNumber));
/* scan application list for matching listeners */
- bcs->ap = NULL;
+ spin_lock_irqsave(&bcs->aplock, flags);
+ if (bcs->ap != NULL || bcs->apconnstate != APCONN_NONE) {
+ dev_warn(cs->dev, "%s: channel not properly cleared (%p/%d)\n",
+ __func__, bcs->ap, bcs->apconnstate);
+ bcs->ap = NULL;
+ bcs->apconnstate = APCONN_NONE;
+ }
+ spin_unlock_irqrestore(&bcs->aplock, flags);
actCIPmask = 1 | (1 << iif->hcmsg.CIPValue);
list_for_each_entry(ap, &iif->appls, ctrlist)
if (actCIPmask & ap->listenCIPmask) {
@@ -626,10 +649,12 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
/* add to listeners on this B channel, update state */
+ spin_lock_irqsave(&bcs->aplock, flags);
ap->bcnext = bcs->ap;
bcs->ap = ap;
bcs->chstate |= CHS_NOTIFY_LL;
- ap->connected = APCONN_SETUP;
+ bcs->apconnstate = APCONN_SETUP;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
/* emit message */
capi_ctr_handle_message(&iif->ctr, ap->id, skb);
@@ -654,7 +679,7 @@ static void send_disconnect_ind(struct bc_state *bcs,
struct gigaset_capi_ctr *iif = cs->iif;
struct sk_buff *skb;
- if (ap->connected == APCONN_NONE)
+ if (bcs->apconnstate == APCONN_NONE)
return;
capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT, CAPI_IND,
@@ -668,7 +693,6 @@ static void send_disconnect_ind(struct bc_state *bcs,
}
capi_cmsg2message(&iif->hcmsg, __skb_put(skb, CAPI_DISCONNECT_IND_LEN));
dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
- ap->connected = APCONN_NONE;
capi_ctr_handle_message(&iif->ctr, ap->id, skb);
}
@@ -685,9 +709,9 @@ static void send_disconnect_b3_ind(struct bc_state *bcs,
struct sk_buff *skb;
/* nothing to do if no logical connection active */
- if (ap->connected < APCONN_ACTIVE)
+ if (bcs->apconnstate < APCONN_ACTIVE)
return;
- ap->connected = APCONN_SETUP;
+ bcs->apconnstate = APCONN_SETUP;
capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND,
ap->nextMessageNumber++,
@@ -714,14 +738,25 @@ void gigaset_isdn_connD(struct bc_state *bcs)
{
struct cardstate *cs = bcs->cs;
struct gigaset_capi_ctr *iif = cs->iif;
- struct gigaset_capi_appl *ap = bcs->ap;
+ struct gigaset_capi_appl *ap;
struct sk_buff *skb;
unsigned int msgsize;
+ unsigned long flags;
+ spin_lock_irqsave(&bcs->aplock, flags);
+ ap = bcs->ap;
if (!ap) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
dev_err(cs->dev, "%s: no application\n", __func__);
return;
}
+ if (bcs->apconnstate == APCONN_NONE) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
+ dev_warn(cs->dev, "%s: application %u not connected\n",
+ __func__, ap->id);
+ return;
+ }
+ spin_unlock_irqrestore(&bcs->aplock, flags);
while (ap->bcnext) {
/* this should never happen */
dev_warn(cs->dev, "%s: dropping extra application %u\n",
@@ -730,11 +765,6 @@ void gigaset_isdn_connD(struct bc_state *bcs)
CapiCallGivenToOtherApplication);
ap->bcnext = ap->bcnext->bcnext;
}
- if (ap->connected == APCONN_NONE) {
- dev_warn(cs->dev, "%s: application %u not connected\n",
- __func__, ap->id);
- return;
- }
/* prepare CONNECT_ACTIVE_IND message
* Note: LLC not supported by device
@@ -772,17 +802,24 @@ void gigaset_isdn_connD(struct bc_state *bcs)
void gigaset_isdn_hupD(struct bc_state *bcs)
{
struct gigaset_capi_appl *ap;
+ unsigned long flags;
/*
* ToDo: pass on reason code reported by device
* (requires ev-layer state machine extension to collect
* ZCAU device reply)
*/
- for (ap = bcs->ap; ap != NULL; ap = ap->bcnext) {
+ spin_lock_irqsave(&bcs->aplock, flags);
+ while (bcs->ap != NULL) {
+ ap = bcs->ap;
+ bcs->ap = ap->bcnext;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
send_disconnect_b3_ind(bcs, ap);
send_disconnect_ind(bcs, ap, 0);
+ spin_lock_irqsave(&bcs->aplock, flags);
}
- bcs->ap = NULL;
+ bcs->apconnstate = APCONN_NONE;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
}
/**
@@ -796,24 +833,21 @@ void gigaset_isdn_connB(struct bc_state *bcs)
{
struct cardstate *cs = bcs->cs;
struct gigaset_capi_ctr *iif = cs->iif;
- struct gigaset_capi_appl *ap = bcs->ap;
+ struct gigaset_capi_appl *ap;
struct sk_buff *skb;
+ unsigned long flags;
unsigned int msgsize;
u8 command;
+ spin_lock_irqsave(&bcs->aplock, flags);
+ ap = bcs->ap;
if (!ap) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
dev_err(cs->dev, "%s: no application\n", __func__);
return;
}
- while (ap->bcnext) {
- /* this should never happen */
- dev_warn(cs->dev, "%s: dropping extra application %u\n",
- __func__, ap->bcnext->id);
- send_disconnect_ind(bcs, ap->bcnext,
- CapiCallGivenToOtherApplication);
- ap->bcnext = ap->bcnext->bcnext;
- }
- if (!ap->connected) {
+ if (!bcs->apconnstate) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
dev_warn(cs->dev, "%s: application %u not connected\n",
__func__, ap->id);
return;
@@ -825,13 +859,26 @@ void gigaset_isdn_connB(struct bc_state *bcs)
* CONNECT_B3_ACTIVE_IND in reply to CONNECT_B3_RESP
* Parameters in both cases always: NCCI = 1, NCPI empty
*/
- if (ap->connected >= APCONN_ACTIVE) {
+ if (bcs->apconnstate >= APCONN_ACTIVE) {
command = CAPI_CONNECT_B3_ACTIVE;
msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN;
} else {
command = CAPI_CONNECT_B3;
msgsize = CAPI_CONNECT_B3_IND_BASELEN;
}
+ bcs->apconnstate = APCONN_ACTIVE;
+
+ spin_unlock_irqrestore(&bcs->aplock, flags);
+
+ while (ap->bcnext) {
+ /* this should never happen */
+ dev_warn(cs->dev, "%s: dropping extra application %u\n",
+ __func__, ap->bcnext->id);
+ send_disconnect_ind(bcs, ap->bcnext,
+ CapiCallGivenToOtherApplication);
+ ap->bcnext = ap->bcnext->bcnext;
+ }
+
capi_cmsg_header(&iif->hcmsg, ap->id, command, CAPI_IND,
ap->nextMessageNumber++,
iif->ctr.cnr | ((bcs->channel + 1) << 8) | (1 << 16));
@@ -842,7 +889,6 @@ void gigaset_isdn_connB(struct bc_state *bcs)
}
capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize));
dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
- ap->connected = APCONN_ACTIVE;
capi_ctr_handle_message(&iif->ctr, ap->id, skb);
}
@@ -945,8 +991,64 @@ static void gigaset_register_appl(struct capi_ctr *ctr, u16 appl,
return;
}
ap->id = appl;
+ ap->rp = *rp;
list_add(&ap->ctrlist, &iif->appls);
+ dev_info(cs->dev, "application %u registered\n", ap->id);
+}
+
+/*
+ * remove CAPI application from channel
+ * helper function to keep indentation levels down and stay in 80 columns
+ */
+
+static inline void remove_appl_from_channel(struct bc_state *bcs,
+ struct gigaset_capi_appl *ap)
+{
+ struct cardstate *cs = bcs->cs;
+ struct gigaset_capi_appl *bcap;
+ unsigned long flags;
+ int prevconnstate;
+
+ spin_lock_irqsave(&bcs->aplock, flags);
+ bcap = bcs->ap;
+ if (bcap == NULL) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
+ return;
+ }
+
+ /* check first application on channel */
+ if (bcap == ap) {
+ bcs->ap = ap->bcnext;
+ if (bcs->ap != NULL) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
+ return;
+ }
+
+ /* none left, clear channel state */
+ prevconnstate = bcs->apconnstate;
+ bcs->apconnstate = APCONN_NONE;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
+
+ if (prevconnstate == APCONN_ACTIVE) {
+ dev_notice(cs->dev, "%s: hanging up channel %u\n",
+ __func__, bcs->channel);
+ gigaset_add_event(cs, &bcs->at_state,
+ EV_HUP, NULL, 0, NULL);
+ gigaset_schedule_event(cs);
+ }
+ return;
+ }
+
+ /* check remaining list */
+ do {
+ if (bcap->bcnext == ap) {
+ bcap->bcnext = bcap->bcnext->bcnext;
+ return;
+ }
+ bcap = bcap->bcnext;
+ } while (bcap != NULL);
+ spin_unlock_irqrestore(&bcs->aplock, flags);
}
/*
@@ -958,19 +1060,19 @@ static void gigaset_release_appl(struct capi_ctr *ctr, u16 appl)
= container_of(ctr, struct gigaset_capi_ctr, ctr);
struct cardstate *cs = iif->ctr.driverdata;
struct gigaset_capi_appl *ap, *tmp;
+ unsigned ch;
list_for_each_entry_safe(ap, tmp, &iif->appls, ctrlist)
if (ap->id == appl) {
- if (ap->connected != APCONN_NONE) {
- dev_err(cs->dev,
- "%s: application %u still connected\n",
- __func__, ap->id);
- /* ToDo: clear active connection */
- }
+ /* remove from any channels */
+ for (ch = 0; ch < cs->channels; ch++)
+ remove_appl_from_channel(&cs->bcs[ch], ap);
+
+ /* remove from registration list */
list_del(&ap->ctrlist);
kfree(ap);
+ dev_info(cs->dev, "application %u released\n", appl);
}
-
}
/*
@@ -1149,7 +1251,8 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
char **commands;
char *s;
u8 *pp;
- int i, l;
+ unsigned long flags;
+ int i, l, lbc, lhlc;
u16 info;
/* decode message */
@@ -1164,8 +1267,18 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
send_conf(iif, ap, skb, CapiNoPlciAvailable);
return;
}
+ spin_lock_irqsave(&bcs->aplock, flags);
+ if (bcs->ap != NULL || bcs->apconnstate != APCONN_NONE)
+ dev_warn(cs->dev, "%s: channel not properly cleared (%p/%d)\n",
+ __func__, bcs->ap, bcs->apconnstate);
ap->bcnext = NULL;
bcs->ap = ap;
+ bcs->apconnstate = APCONN_SETUP;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
+
+ bcs->rx_bufsize = ap->rp.datablklen;
+ dev_kfree_skb(bcs->rx_skb);
+ gigaset_new_rx_skb(bcs);
cmsg->adr.adrPLCI |= (bcs->channel + 1) << 8;
/* build command table */
@@ -1273,42 +1386,59 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
goto error;
}
- /* check/encode parameter: BC */
- if (cmsg->BC && cmsg->BC[0]) {
- /* explicit BC overrides CIP */
- l = 2*cmsg->BC[0] + 7;
+ /*
+ * check/encode parameters: BC & HLC
+ * must be encoded together as device doesn't accept HLC separately
+ * explicit parameters override values derived from CIP
+ */
+
+ /* determine lengths */
+ if (cmsg->BC && cmsg->BC[0]) /* BC specified explicitly */
+ lbc = 2*cmsg->BC[0];
+ else if (cip2bchlc[cmsg->CIPValue].bc) /* BC derived from CIP */
+ lbc = strlen(cip2bchlc[cmsg->CIPValue].bc);
+ else /* no BC */
+ lbc = 0;
+ if (cmsg->HLC && cmsg->HLC[0]) /* HLC specified explicitly */
+ lhlc = 2*cmsg->HLC[0];
+ else if (cip2bchlc[cmsg->CIPValue].hlc) /* HLC derived from CIP */
+ lhlc = strlen(cip2bchlc[cmsg->CIPValue].hlc);
+ else /* no HLC */
+ lhlc = 0;
+
+ if (lbc) {
+ /* have BC: allocate and assemble command string */
+ l = lbc + 7; /* "^SBC=" + value + "\r" + null byte */
+ if (lhlc)
+ l += lhlc + 7; /* ";^SHLC=" + value */
commands[AT_BC] = kmalloc(l, GFP_KERNEL);
if (!commands[AT_BC])
goto oom;
strcpy(commands[AT_BC], "^SBC=");
- decode_ie(cmsg->BC, commands[AT_BC]+5);
+ if (cmsg->BC && cmsg->BC[0]) /* BC specified explicitly */
+ decode_ie(cmsg->BC, commands[AT_BC] + 5);
+ else /* BC derived from CIP */
+ strcpy(commands[AT_BC] + 5,
+ cip2bchlc[cmsg->CIPValue].bc);
+ if (lhlc) {
+ strcpy(commands[AT_BC] + lbc + 5, ";^SHLC=");
+ if (cmsg->HLC && cmsg->HLC[0])
+ /* HLC specified explicitly */
+ decode_ie(cmsg->HLC,
+ commands[AT_BC] + lbc + 12);
+ else /* HLC derived from CIP */
+ strcpy(commands[AT_BC] + lbc + 12,
+ cip2bchlc[cmsg->CIPValue].hlc);
+ }
strcpy(commands[AT_BC] + l - 2, "\r");
- } else if (cip2bchlc[cmsg->CIPValue].bc) {
- l = strlen(cip2bchlc[cmsg->CIPValue].bc) + 7;
- commands[AT_BC] = kmalloc(l, GFP_KERNEL);
- if (!commands[AT_BC])
- goto oom;
- snprintf(commands[AT_BC], l, "^SBC=%s\r",
- cip2bchlc[cmsg->CIPValue].bc);
- }
-
- /* check/encode parameter: HLC */
- if (cmsg->HLC && cmsg->HLC[0]) {
- /* explicit HLC overrides CIP */
- l = 2*cmsg->HLC[0] + 7;
- commands[AT_HLC] = kmalloc(l, GFP_KERNEL);
- if (!commands[AT_HLC])
- goto oom;
- strcpy(commands[AT_HLC], "^SHLC=");
- decode_ie(cmsg->HLC, commands[AT_HLC]+5);
- strcpy(commands[AT_HLC] + l - 2, "\r");
- } else if (cip2bchlc[cmsg->CIPValue].hlc) {
- l = strlen(cip2bchlc[cmsg->CIPValue].hlc) + 7;
- commands[AT_HLC] = kmalloc(l, GFP_KERNEL);
- if (!commands[AT_HLC])
- goto oom;
- snprintf(commands[AT_HLC], l, "^SHLC=%s\r",
- cip2bchlc[cmsg->CIPValue].hlc);
+ } else {
+ /* no BC */
+ if (lhlc) {
+ dev_notice(cs->dev, "%s: cannot set HLC without BC\n",
+ "CONNECT_REQ");
+ info = CapiIllMessageParmCoding; /* ? */
+ goto error;
+ }
}
/* check/encode parameter: B Protocol */
@@ -1322,13 +1452,13 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
bcs->proto2 = L2_HDLC;
break;
case 1:
- bcs->proto2 = L2_BITSYNC;
+ bcs->proto2 = L2_VOICE;
break;
default:
dev_warn(cs->dev,
"B1 Protocol %u unsupported, using Transparent\n",
cmsg->B1protocol);
- bcs->proto2 = L2_BITSYNC;
+ bcs->proto2 = L2_VOICE;
}
if (cmsg->B2protocol != 1)
dev_warn(cs->dev,
@@ -1382,7 +1512,6 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
goto error;
}
gigaset_schedule_event(cs);
- ap->connected = APCONN_SETUP;
send_conf(iif, ap, skb, CapiSuccess);
return;
@@ -1410,6 +1539,7 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
_cmsg *cmsg = &iif->acmsg;
struct bc_state *bcs;
struct gigaset_capi_appl *oap;
+ unsigned long flags;
int channel;
/* decode message */
@@ -1429,12 +1559,24 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
switch (cmsg->Reject) {
case 0: /* Accept */
/* drop all competing applications, keep only this one */
- for (oap = bcs->ap; oap != NULL; oap = oap->bcnext)
- if (oap != ap)
+ spin_lock_irqsave(&bcs->aplock, flags);
+ while (bcs->ap != NULL) {
+ oap = bcs->ap;
+ bcs->ap = oap->bcnext;
+ if (oap != ap) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
send_disconnect_ind(bcs, oap,
CapiCallGivenToOtherApplication);
+ spin_lock_irqsave(&bcs->aplock, flags);
+ }
+ }
ap->bcnext = NULL;
bcs->ap = ap;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
+
+ bcs->rx_bufsize = ap->rp.datablklen;
+ dev_kfree_skb(bcs->rx_skb);
+ gigaset_new_rx_skb(bcs);
bcs->chstate |= CHS_NOTIFY_LL;
/* check/encode B channel protocol */
@@ -1448,13 +1590,13 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
bcs->proto2 = L2_HDLC;
break;
case 1:
- bcs->proto2 = L2_BITSYNC;
+ bcs->proto2 = L2_VOICE;
break;
default:
dev_warn(cs->dev,
"B1 Protocol %u unsupported, using Transparent\n",
cmsg->B1protocol);
- bcs->proto2 = L2_BITSYNC;
+ bcs->proto2 = L2_VOICE;
}
if (cmsg->B2protocol != 1)
dev_warn(cs->dev,
@@ -1502,31 +1644,45 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
send_disconnect_ind(bcs, ap, 0);
/* remove it from the list of listening apps */
+ spin_lock_irqsave(&bcs->aplock, flags);
if (bcs->ap == ap) {
bcs->ap = ap->bcnext;
- if (bcs->ap == NULL)
+ if (bcs->ap == NULL) {
/* last one: stop ev-layer hupD notifications */
+ bcs->apconnstate = APCONN_NONE;
bcs->chstate &= ~CHS_NOTIFY_LL;
+ }
+ spin_unlock_irqrestore(&bcs->aplock, flags);
return;
}
for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) {
if (oap->bcnext == ap) {
oap->bcnext = oap->bcnext->bcnext;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
return;
}
}
+ spin_unlock_irqrestore(&bcs->aplock, flags);
dev_err(cs->dev, "%s: application %u not found\n",
__func__, ap->id);
return;
default: /* Reject */
/* drop all competing applications, keep only this one */
- for (oap = bcs->ap; oap != NULL; oap = oap->bcnext)
- if (oap != ap)
+ spin_lock_irqsave(&bcs->aplock, flags);
+ while (bcs->ap != NULL) {
+ oap = bcs->ap;
+ bcs->ap = oap->bcnext;
+ if (oap != ap) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
send_disconnect_ind(bcs, oap,
CapiCallGivenToOtherApplication);
+ spin_lock_irqsave(&bcs->aplock, flags);
+ }
+ }
ap->bcnext = NULL;
bcs->ap = ap;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
/* reject call - will trigger DISCONNECT_IND for this app */
dev_info(cs->dev, "%s: Reject=%x\n",
@@ -1549,6 +1705,7 @@ static void do_connect_b3_req(struct gigaset_capi_ctr *iif,
{
struct cardstate *cs = iif->ctr.driverdata;
_cmsg *cmsg = &iif->acmsg;
+ struct bc_state *bcs;
int channel;
/* decode message */
@@ -1563,9 +1720,10 @@ static void do_connect_b3_req(struct gigaset_capi_ctr *iif,
send_conf(iif, ap, skb, CapiIllContrPlciNcci);
return;
}
+ bcs = &cs->bcs[channel-1];
/* mark logical connection active */
- ap->connected = APCONN_ACTIVE;
+ bcs->apconnstate = APCONN_ACTIVE;
/* build NCCI: always 1 (one B3 connection only) */
cmsg->adr.adrNCCI |= 1 << 16;
@@ -1611,7 +1769,7 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif,
if (cmsg->Reject) {
/* Reject: clear B3 connect received flag */
- ap->connected = APCONN_SETUP;
+ bcs->apconnstate = APCONN_SETUP;
/* trigger hangup, causing eventual DISCONNECT_IND */
if (!gigaset_add_event(cs, &bcs->at_state,
@@ -1683,11 +1841,11 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif,
}
/* skip if DISCONNECT_IND already sent */
- if (!ap->connected)
+ if (!bcs->apconnstate)
return;
/* check for active logical connection */
- if (ap->connected >= APCONN_ACTIVE) {
+ if (bcs->apconnstate >= APCONN_ACTIVE) {
/*
* emit DISCONNECT_B3_IND with cause 0x3301
* use separate cmsg structure, as the content of iif->acmsg
@@ -1736,6 +1894,7 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif,
{
struct cardstate *cs = iif->ctr.driverdata;
_cmsg *cmsg = &iif->acmsg;
+ struct bc_state *bcs;
int channel;
/* decode message */
@@ -1751,17 +1910,17 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif,
send_conf(iif, ap, skb, CapiIllContrPlciNcci);
return;
}
+ bcs = &cs->bcs[channel-1];
/* reject if logical connection not active */
- if (ap->connected < APCONN_ACTIVE) {
+ if (bcs->apconnstate < APCONN_ACTIVE) {
send_conf(iif, ap, skb,
CapiMessageNotSupportedInCurrentState);
return;
}
/* trigger hangup, causing eventual DISCONNECT_B3_IND */
- if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state,
- EV_HUP, NULL, 0, NULL)) {
+ if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) {
send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR);
return;
}
@@ -1782,11 +1941,14 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,
struct sk_buff *skb)
{
struct cardstate *cs = iif->ctr.driverdata;
+ struct bc_state *bcs;
int channel = CAPIMSG_PLCI_PART(skb->data);
u16 ncci = CAPIMSG_NCCI_PART(skb->data);
u16 msglen = CAPIMSG_LEN(skb->data);
u16 datalen = CAPIMSG_DATALEN(skb->data);
u16 flags = CAPIMSG_FLAGS(skb->data);
+ u16 msgid = CAPIMSG_MSGID(skb->data);
+ u16 handle = CAPIMSG_HANDLE_REQ(skb->data);
/* frequent message, avoid _cmsg overhead */
dump_rawmsg(DEBUG_LLDATA, "DATA_B3_REQ", skb->data);
@@ -1802,6 +1964,7 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,
send_conf(iif, ap, skb, CapiIllContrPlciNcci);
return;
}
+ bcs = &cs->bcs[channel-1];
if (msglen != CAPI_DATA_B3_REQ_LEN && msglen != CAPI_DATA_B3_REQ_LEN64)
dev_notice(cs->dev, "%s: unexpected length %d\n",
"DATA_B3_REQ", msglen);
@@ -1821,7 +1984,7 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,
}
/* reject if logical connection not active */
- if (ap->connected < APCONN_ACTIVE) {
+ if (bcs->apconnstate < APCONN_ACTIVE) {
send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState);
return;
}
@@ -1832,17 +1995,19 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,
skb_pull(skb, msglen);
/* pass to device-specific module */
- if (cs->ops->send_skb(&cs->bcs[channel-1], skb) < 0) {
+ if (cs->ops->send_skb(bcs, skb) < 0) {
send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR);
return;
}
- /* DATA_B3_CONF reply will be sent by gigaset_skb_sent() */
-
/*
- * ToDo: honor unset "delivery confirmation" bit
- * (send DATA_B3_CONF immediately?)
+ * DATA_B3_CONF will be sent by gigaset_skb_sent() only if "delivery
+ * confirmation" bit is set; otherwise we have to send it now
*/
+ if (!(flags & CAPI_FLAGS_DELIVERY_CONFIRMATION))
+ send_data_b3_conf(cs, &iif->ctr, ap->id, msgid, channel, handle,
+ flags ? CapiFlagsNotSupportedByProtocol
+ : CAPI_NOERROR);
}
/*
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index f6f45f221920..5d4befb81057 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -399,8 +399,8 @@ static void gigaset_freebcs(struct bc_state *bcs)
gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
clear_at_state(&bcs->at_state);
gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel);
- dev_kfree_skb(bcs->skb);
- bcs->skb = NULL;
+ dev_kfree_skb(bcs->rx_skb);
+ bcs->rx_skb = NULL;
for (i = 0; i < AT_NUM; ++i) {
kfree(bcs->commands[i]);
@@ -634,19 +634,10 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
bcs->emptycount = 0;
#endif
- gig_dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel);
- bcs->fcs = PPP_INITFCS;
+ bcs->rx_bufsize = 0;
+ bcs->rx_skb = NULL;
+ bcs->rx_fcs = PPP_INITFCS;
bcs->inputstate = 0;
- if (cs->ignoreframes) {
- bcs->skb = NULL;
- } else {
- bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
- if (bcs->skb != NULL)
- skb_reserve(bcs->skb, cs->hw_hdr_len);
- else
- pr_err("out of memory\n");
- }
-
bcs->channel = channel;
bcs->cs = cs;
@@ -658,16 +649,15 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
for (i = 0; i < AT_NUM; ++i)
bcs->commands[i] = NULL;
+ spin_lock_init(&bcs->aplock);
+ bcs->ap = NULL;
+ bcs->apconnstate = 0;
+
gig_dbg(DEBUG_INIT, " setting up bcs[%d]->hw", channel);
if (cs->ops->initbcshw(bcs))
return bcs;
gig_dbg(DEBUG_INIT, " failed");
-
- gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel);
- dev_kfree_skb(bcs->skb);
- bcs->skb = NULL;
-
return NULL;
}
@@ -839,14 +829,12 @@ void gigaset_bcs_reinit(struct bc_state *bcs)
bcs->emptycount = 0;
#endif
- bcs->fcs = PPP_INITFCS;
+ bcs->rx_fcs = PPP_INITFCS;
bcs->chstate = 0;
bcs->ignore = cs->ignoreframes;
- if (bcs->ignore) {
- dev_kfree_skb(bcs->skb);
- bcs->skb = NULL;
- }
+ dev_kfree_skb(bcs->rx_skb);
+ bcs->rx_skb = NULL;
cs->ops->reinitbcshw(bcs);
}
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c
index 206c380c5235..ceaef9a04a42 100644
--- a/drivers/isdn/gigaset/ev-layer.c
+++ b/drivers/isdn/gigaset/ev-layer.c
@@ -282,9 +282,7 @@ struct reply_t gigaset_tab_cid[] =
/* dial */
{EV_DIAL, -1, -1, -1, -1, -1, {ACT_DIAL} },
{RSP_INIT, 0, 0, SEQ_DIAL, 601, 5, {ACT_CMD+AT_BC} },
-{RSP_OK, 601, 601, -1, 602, 5, {ACT_CMD+AT_HLC} },
-{RSP_NULL, 602, 602, -1, 603, 5, {ACT_CMD+AT_PROTO} },
-{RSP_OK, 602, 602, -1, 603, 5, {ACT_CMD+AT_PROTO} },
+{RSP_OK, 601, 601, -1, 603, 5, {ACT_CMD+AT_PROTO} },
{RSP_OK, 603, 603, -1, 604, 5, {ACT_CMD+AT_TYPE} },
{RSP_OK, 604, 604, -1, 605, 5, {ACT_CMD+AT_MSN} },
{RSP_NULL, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} },
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index 05947f9c1849..8738b0821fc9 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -45,10 +45,6 @@
#define MAX_EVENTS 64 /* size of event queue */
#define RBUFSIZE 8192
-#define SBUFSIZE 4096 /* sk_buff payload size */
-
-#define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */
-#define MAX_BUF_SIZE (SBUFSIZE - 2) /* Max. size of a data packet from LL */
/* compile time options */
#define GIG_MAJOR 0
@@ -190,10 +186,9 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
#define AT_BC 3
#define AT_PROTO 4
#define AT_TYPE 5
-#define AT_HLC 6
-#define AT_CLIP 7
+#define AT_CLIP 6
/* total number */
-#define AT_NUM 8
+#define AT_NUM 7
/* variables in struct at_state_t */
#define VAR_ZSAU 0
@@ -380,8 +375,10 @@ struct bc_state {
struct at_state_t at_state;
- __u16 fcs;
- struct sk_buff *skb;
+ /* receive buffer */
+ unsigned rx_bufsize; /* max size accepted by application */
+ struct sk_buff *rx_skb;
+ __u16 rx_fcs;
int inputstate; /* see INS_XXXX */
int channel;
@@ -406,7 +403,9 @@ struct bc_state {
struct bas_bc_state *bas; /* usb hardware driver (base) */
} hw;
- void *ap; /* LL application structure */
+ void *ap; /* associated LL application */
+ int apconnstate; /* LL application connection state */
+ spinlock_t aplock;
};
struct cardstate {
@@ -801,8 +800,23 @@ static inline void gigaset_bchannel_up(struct bc_state *bcs)
gigaset_schedule_event(bcs->cs);
}
-/* handling routines for sk_buff */
-/* ============================= */
+/* set up next receive skb for data mode */
+static inline struct sk_buff *gigaset_new_rx_skb(struct bc_state *bcs)
+{
+ struct cardstate *cs = bcs->cs;
+ unsigned short hw_hdr_len = cs->hw_hdr_len;
+
+ if (bcs->ignore) {
+ bcs->rx_skb = NULL;
+ } else {
+ bcs->rx_skb = dev_alloc_skb(bcs->rx_bufsize + hw_hdr_len);
+ if (bcs->rx_skb == NULL)
+ dev_warn(cs->dev, "could not allocate skb\n");
+ else
+ skb_reserve(bcs->rx_skb, hw_hdr_len);
+ }
+ return bcs->rx_skb;
+}
/* append received bytes to inbuf */
int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c
index c22e5ace8276..f01c3c2e2e46 100644
--- a/drivers/isdn/gigaset/i4l.c
+++ b/drivers/isdn/gigaset/i4l.c
@@ -16,7 +16,10 @@
#include "gigaset.h"
#include <linux/isdnif.h>
+#define SBUFSIZE 4096 /* sk_buff payload size */
+#define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */
#define HW_HDR_LEN 2 /* Header size used to store ack info */
+#define MAX_BUF_SIZE (SBUFSIZE - HW_HDR_LEN) /* max data packet from LL */
/* == Handling of I4L IO =====================================================*/
@@ -231,6 +234,15 @@ static int command_from_LL(isdn_ctrl *cntrl)
dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n");
return -EBUSY;
}
+ switch (bcs->proto2) {
+ case L2_HDLC:
+ bcs->rx_bufsize = SBUFSIZE;
+ break;
+ default: /* assume transparent */
+ bcs->rx_bufsize = TRANSBUFSIZE;
+ }
+ dev_kfree_skb(bcs->rx_skb);
+ gigaset_new_rx_skb(bcs);
commands = kzalloc(AT_NUM*(sizeof *commands), GFP_ATOMIC);
if (!commands) {
@@ -314,6 +326,15 @@ static int command_from_LL(isdn_ctrl *cntrl)
return -EINVAL;
}
bcs = cs->bcs + ch;
+ switch (bcs->proto2) {
+ case L2_HDLC:
+ bcs->rx_bufsize = SBUFSIZE;
+ break;
+ default: /* assume transparent */
+ bcs->rx_bufsize = TRANSBUFSIZE;
+ }
+ dev_kfree_skb(bcs->rx_skb);
+ gigaset_new_rx_skb(bcs);
if (!gigaset_add_event(cs, &bcs->at_state,
EV_ACCEPT, NULL, 0, NULL))
return -ENOMEM;
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c
index 16fd3bd48883..2dfd346fc889 100644
--- a/drivers/isdn/gigaset/isocdata.c
+++ b/drivers/isdn/gigaset/isocdata.c
@@ -500,19 +500,18 @@ int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len)
*/
static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs)
{
- bcs->fcs = crc_ccitt_byte(bcs->fcs, c);
- if (unlikely(bcs->skb == NULL)) {
+ bcs->rx_fcs = crc_ccitt_byte(bcs->rx_fcs, c);
+ if (bcs->rx_skb == NULL)
/* skipping */
return;
- }
- if (unlikely(bcs->skb->len == SBUFSIZE)) {
+ if (bcs->rx_skb->len >= bcs->rx_bufsize) {
dev_warn(bcs->cs->dev, "received oversized packet discarded\n");
bcs->hw.bas->giants++;
- dev_kfree_skb_any(bcs->skb);
- bcs->skb = NULL;
+ dev_kfree_skb_any(bcs->rx_skb);
+ bcs->rx_skb = NULL;
return;
}
- *__skb_put(bcs->skb, 1) = c;
+ *__skb_put(bcs->rx_skb, 1) = c;
}
/* hdlc_flush
@@ -521,18 +520,13 @@ static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs)
static inline void hdlc_flush(struct bc_state *bcs)
{
/* clear skb or allocate new if not skipping */
- if (likely(bcs->skb != NULL))
- skb_trim(bcs->skb, 0);
- else if (!bcs->ignore) {
- bcs->skb = dev_alloc_skb(SBUFSIZE + bcs->cs->hw_hdr_len);
- if (bcs->skb)
- skb_reserve(bcs->skb, bcs->cs->hw_hdr_len);
- else
- dev_err(bcs->cs->dev, "could not allocate skb\n");
- }
+ if (bcs->rx_skb != NULL)
+ skb_trim(bcs->rx_skb, 0);
+ else
+ gigaset_new_rx_skb(bcs);
/* reset packet state */
- bcs->fcs = PPP_INITFCS;
+ bcs->rx_fcs = PPP_INITFCS;
}
/* hdlc_done
@@ -549,7 +543,7 @@ static inline void hdlc_done(struct bc_state *bcs)
hdlc_flush(bcs);
return;
}
- procskb = bcs->skb;
+ procskb = bcs->rx_skb;
if (procskb == NULL) {
/* previous error */
gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__);
@@ -560,8 +554,8 @@ static inline void hdlc_done(struct bc_state *bcs)
bcs->hw.bas->runts++;
dev_kfree_skb_any(procskb);
gigaset_isdn_rcv_err(bcs);
- } else if (bcs->fcs != PPP_GOODFCS) {
- dev_notice(cs->dev, "frame check error (0x%04x)\n", bcs->fcs);
+ } else if (bcs->rx_fcs != PPP_GOODFCS) {
+ dev_notice(cs->dev, "frame check error\n");
bcs->hw.bas->fcserrs++;
dev_kfree_skb_any(procskb);
gigaset_isdn_rcv_err(bcs);
@@ -574,13 +568,8 @@ static inline void hdlc_done(struct bc_state *bcs)
bcs->hw.bas->goodbytes += len;
gigaset_skb_rcvd(bcs, procskb);
}
-
- bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
- if (bcs->skb)
- skb_reserve(bcs->skb, cs->hw_hdr_len);
- else
- dev_err(cs->dev, "could not allocate skb\n");
- bcs->fcs = PPP_INITFCS;
+ gigaset_new_rx_skb(bcs);
+ bcs->rx_fcs = PPP_INITFCS;
}
/* hdlc_frag
@@ -597,8 +586,8 @@ static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits)
dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits);
bcs->hw.bas->alignerrs++;
gigaset_isdn_rcv_err(bcs);
- __skb_trim(bcs->skb, 0);
- bcs->fcs = PPP_INITFCS;
+ __skb_trim(bcs->rx_skb, 0);
+ bcs->rx_fcs = PPP_INITFCS;
}
/* bit counts lookup table for HDLC bit unstuffing
@@ -847,7 +836,6 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
static inline void trans_receive(unsigned char *src, unsigned count,
struct bc_state *bcs)
{
- struct cardstate *cs = bcs->cs;
struct sk_buff *skb;
int dobytes;
unsigned char *dst;
@@ -857,17 +845,11 @@ static inline void trans_receive(unsigned char *src, unsigned count,
hdlc_flush(bcs);
return;
}
- skb = bcs->skb;
- if (unlikely(skb == NULL)) {
- bcs->skb = skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
- if (!skb) {
- dev_err(cs->dev, "could not allocate skb\n");
- return;
- }
- skb_reserve(skb, cs->hw_hdr_len);
- }
+ skb = bcs->rx_skb;
+ if (skb == NULL)
+ skb = gigaset_new_rx_skb(bcs);
bcs->hw.bas->goodbytes += skb->len;
- dobytes = TRANSBUFSIZE - skb->len;
+ dobytes = bcs->rx_bufsize - skb->len;
while (count > 0) {
dst = skb_put(skb, count < dobytes ? count : dobytes);
while (count > 0 && dobytes > 0) {
@@ -879,14 +861,10 @@ static inline void trans_receive(unsigned char *src, unsigned count,
dump_bytes(DEBUG_STREAM_DUMP,
"rcv data", skb->data, skb->len);
gigaset_skb_rcvd(bcs, skb);
- bcs->skb = skb =
- dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
- if (!skb) {
- dev_err(cs->dev, "could not allocate skb\n");
+ skb = gigaset_new_rx_skb(bcs);
+ if (skb == NULL)
return;
- }
- skb_reserve(skb, cs->hw_hdr_len);
- dobytes = TRANSBUFSIZE;
+ dobytes = bcs->rx_bufsize;
}
}
}
diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c
index 72eb92647c1b..feec8d89d719 100644
--- a/drivers/isdn/hysdn/hysdn_net.c
+++ b/drivers/isdn/hysdn/hysdn_net.c
@@ -187,12 +187,13 @@ void
hysdn_rx_netpkt(hysdn_card * card, unsigned char *buf, unsigned short len)
{
struct net_local *lp = card->netif;
- struct net_device *dev = lp->dev;
+ struct net_device *dev;
struct sk_buff *skb;
if (!lp)
return; /* non existing device */
+ dev = lp->dev;
dev->stats.rx_bytes += len;
skb = dev_alloc_skb(len);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 46b3a044eadf..cb20d0b0555a 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2087,6 +2087,7 @@ static void sync_sbs(mddev_t * mddev, int nospares)
/* First make sure individual recovery_offsets are correct */
list_for_each_entry(rdev, &mddev->disks, same_set) {
if (rdev->raid_disk >= 0 &&
+ mddev->delta_disks >= 0 &&
!test_bit(In_sync, &rdev->flags) &&
mddev->curr_resync_completed > rdev->recovery_offset)
rdev->recovery_offset = mddev->curr_resync_completed;
@@ -3001,6 +3002,9 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
return -EINVAL;
}
+ list_for_each_entry(rdev, &mddev->disks, same_set)
+ rdev->new_raid_disk = rdev->raid_disk;
+
/* ->takeover must set new_* and/or delta_disks
* if it succeeds, and may set them when it fails.
*/
@@ -3051,13 +3055,35 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
mddev->safemode = 0;
}
- module_put(mddev->pers->owner);
- /* Invalidate devices that are now superfluous */
- list_for_each_entry(rdev, &mddev->disks, same_set)
- if (rdev->raid_disk >= mddev->raid_disks) {
- rdev->raid_disk = -1;
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
+ char nm[20];
+ if (rdev->raid_disk < 0)
+ continue;
+ if (rdev->new_raid_disk > mddev->raid_disks)
+ rdev->new_raid_disk = -1;
+ if (rdev->new_raid_disk == rdev->raid_disk)
+ continue;
+ sprintf(nm, "rd%d", rdev->raid_disk);
+ sysfs_remove_link(&mddev->kobj, nm);
+ }
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
+ if (rdev->raid_disk < 0)
+ continue;
+ if (rdev->new_raid_disk == rdev->raid_disk)
+ continue;
+ rdev->raid_disk = rdev->new_raid_disk;
+ if (rdev->raid_disk < 0)
clear_bit(In_sync, &rdev->flags);
+ else {
+ char nm[20];
+ sprintf(nm, "rd%d", rdev->raid_disk);
+ if(sysfs_create_link(&mddev->kobj, &rdev->kobj, nm))
+ printk("md: cannot register %s for %s after level change\n",
+ nm, mdname(mddev));
}
+ }
+
+ module_put(mddev->pers->owner);
mddev->pers = pers;
mddev->private = priv;
strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
@@ -5895,6 +5921,7 @@ static int md_open(struct block_device *bdev, fmode_t mode)
atomic_inc(&mddev->openers);
mutex_unlock(&mddev->open_mutex);
+ check_disk_size_change(mddev->gendisk, bdev);
out:
return err;
}
@@ -6846,6 +6873,7 @@ void md_do_sync(mddev_t *mddev)
rcu_read_lock();
list_for_each_entry_rcu(rdev, &mddev->disks, same_set)
if (rdev->raid_disk >= 0 &&
+ mddev->delta_disks >= 0 &&
!test_bit(Faulty, &rdev->flags) &&
!test_bit(In_sync, &rdev->flags) &&
rdev->recovery_offset < mddev->curr_resync)
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 7ab5ea155452..10597bfec000 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -78,6 +78,9 @@ struct mdk_rdev_s
int desc_nr; /* descriptor index in the superblock */
int raid_disk; /* role of device in array */
+ int new_raid_disk; /* role that the device will have in
+ * the array after a level-change completes.
+ */
int saved_raid_disk; /* role that device used to have in the
* array and could again if we did a partial
* resync from the bitmap
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index e70f004c99e8..563abed5a2cb 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -173,9 +173,11 @@ static int create_strip_zones(mddev_t *mddev, raid0_conf_t **private_conf)
list_for_each_entry(rdev1, &mddev->disks, same_set) {
int j = rdev1->raid_disk;
- if (mddev->level == 10)
+ if (mddev->level == 10) {
/* taking over a raid10-n2 array */
j /= 2;
+ rdev1->new_raid_disk = j;
+ }
if (j < 0 || j >= mddev->raid_disks) {
printk(KERN_ERR "md/raid0:%s: bad disk number %d - "
@@ -361,12 +363,6 @@ static int raid0_run(mddev_t *mddev)
mddev->private = conf;
}
conf = mddev->private;
- if (conf->scale_raid_disks) {
- int i;
- for (i=0; i < conf->strip_zone[0].nb_dev; i++)
- conf->devlist[i]->raid_disk /= conf->scale_raid_disks;
- /* FIXME update sysfs rd links */
- }
/* calculate array device size */
md_set_array_sectors(mddev, raid0_size(mddev, 0, 0));
@@ -573,7 +569,7 @@ static void raid0_status(struct seq_file *seq, mddev_t *mddev)
return;
}
-static void *raid0_takeover_raid5(mddev_t *mddev)
+static void *raid0_takeover_raid45(mddev_t *mddev)
{
mdk_rdev_t *rdev;
raid0_conf_t *priv_conf;
@@ -596,6 +592,7 @@ static void *raid0_takeover_raid5(mddev_t *mddev)
/* Set new parameters */
mddev->new_level = 0;
+ mddev->new_layout = 0;
mddev->new_chunk_sectors = mddev->chunk_sectors;
mddev->raid_disks--;
mddev->delta_disks = -1;
@@ -635,6 +632,7 @@ static void *raid0_takeover_raid10(mddev_t *mddev)
/* Set new parameters */
mddev->new_level = 0;
+ mddev->new_layout = 0;
mddev->new_chunk_sectors = mddev->chunk_sectors;
mddev->delta_disks = - mddev->raid_disks / 2;
mddev->raid_disks += mddev->delta_disks;
@@ -643,19 +641,22 @@ static void *raid0_takeover_raid10(mddev_t *mddev)
mddev->recovery_cp = MaxSector;
create_strip_zones(mddev, &priv_conf);
- priv_conf->scale_raid_disks = 2;
return priv_conf;
}
static void *raid0_takeover(mddev_t *mddev)
{
/* raid0 can take over:
+ * raid4 - if all data disks are active.
* raid5 - providing it is Raid4 layout and one disk is faulty
* raid10 - assuming we have all necessary active disks
*/
+ if (mddev->level == 4)
+ return raid0_takeover_raid45(mddev);
+
if (mddev->level == 5) {
if (mddev->layout == ALGORITHM_PARITY_N)
- return raid0_takeover_raid5(mddev);
+ return raid0_takeover_raid45(mddev);
printk(KERN_ERR "md/raid0:%s: Raid can only takeover Raid5 with layout: %d\n",
mdname(mddev), ALGORITHM_PARITY_N);
diff --git a/drivers/md/raid0.h b/drivers/md/raid0.h
index d724e664ca4d..91f8e876ee64 100644
--- a/drivers/md/raid0.h
+++ b/drivers/md/raid0.h
@@ -13,9 +13,6 @@ struct raid0_private_data
struct strip_zone *strip_zone;
mdk_rdev_t **devlist; /* lists of rdevs, pointed to by strip_zone->dev */
int nr_strip_zones;
- int scale_raid_disks; /* divide rdev->raid_disks by this in run()
- * to handle conversion from raid10
- */
};
typedef struct raid0_private_data raid0_conf_t;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 03724992cdf2..42e64e4e5e25 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1482,14 +1482,14 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
int sectors = r10_bio->sectors;
mdk_rdev_t*rdev;
int max_read_errors = atomic_read(&mddev->max_corr_read_errors);
+ int d = r10_bio->devs[r10_bio->read_slot].devnum;
rcu_read_lock();
- {
- int d = r10_bio->devs[r10_bio->read_slot].devnum;
+ rdev = rcu_dereference(conf->mirrors[d].rdev);
+ if (rdev) { /* If rdev is not NULL */
char b[BDEVNAME_SIZE];
int cur_read_error_count = 0;
- rdev = rcu_dereference(conf->mirrors[d].rdev);
bdevname(rdev->bdev, b);
if (test_bit(Faulty, &rdev->flags)) {
@@ -1530,7 +1530,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
rcu_read_lock();
do {
- int d = r10_bio->devs[sl].devnum;
+ d = r10_bio->devs[sl].devnum;
rdev = rcu_dereference(conf->mirrors[d].rdev);
if (rdev &&
test_bit(In_sync, &rdev->flags)) {
@@ -1564,7 +1564,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
rcu_read_lock();
while (sl != r10_bio->read_slot) {
char b[BDEVNAME_SIZE];
- int d;
+
if (sl==0)
sl = conf->copies;
sl--;
@@ -1601,7 +1601,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
}
sl = start;
while (sl != r10_bio->read_slot) {
- int d;
+
if (sl==0)
sl = conf->copies;
sl--;
@@ -2161,22 +2161,22 @@ static conf_t *setup_conf(mddev_t *mddev)
sector_t stride, size;
int err = -EINVAL;
- if (mddev->chunk_sectors < (PAGE_SIZE >> 9) ||
- !is_power_of_2(mddev->chunk_sectors)) {
+ if (mddev->new_chunk_sectors < (PAGE_SIZE >> 9) ||
+ !is_power_of_2(mddev->new_chunk_sectors)) {
printk(KERN_ERR "md/raid10:%s: chunk size must be "
"at least PAGE_SIZE(%ld) and be a power of 2.\n",
mdname(mddev), PAGE_SIZE);
goto out;
}
- nc = mddev->layout & 255;
- fc = (mddev->layout >> 8) & 255;
- fo = mddev->layout & (1<<16);
+ nc = mddev->new_layout & 255;
+ fc = (mddev->new_layout >> 8) & 255;
+ fo = mddev->new_layout & (1<<16);
if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks ||
- (mddev->layout >> 17)) {
+ (mddev->new_layout >> 17)) {
printk(KERN_ERR "md/raid10:%s: unsupported raid10 layout: 0x%8x\n",
- mdname(mddev), mddev->layout);
+ mdname(mddev), mddev->new_layout);
goto out;
}
@@ -2241,7 +2241,6 @@ static conf_t *setup_conf(mddev_t *mddev)
if (!conf->thread)
goto out;
- conf->scale_disks = 0;
conf->mddev = mddev;
return conf;
@@ -2300,11 +2299,6 @@ static int run(mddev_t *mddev)
if (disk_idx >= conf->raid_disks
|| disk_idx < 0)
continue;
- if (conf->scale_disks) {
- disk_idx *= conf->scale_disks;
- rdev->raid_disk = disk_idx;
- /* MOVE 'rd%d' link !! */
- }
disk = conf->mirrors + disk_idx;
disk->rdev = rdev;
@@ -2435,26 +2429,22 @@ static void *raid10_takeover_raid0(mddev_t *mddev)
return ERR_PTR(-EINVAL);
}
- /* Update slot numbers to obtain
- * degraded raid10 with missing mirrors
- */
- list_for_each_entry(rdev, &mddev->disks, same_set) {
- rdev->raid_disk *= 2;
- }
-
/* Set new parameters */
mddev->new_level = 10;
/* new layout: far_copies = 1, near_copies = 2 */
mddev->new_layout = (1<<8) + 2;
mddev->new_chunk_sectors = mddev->chunk_sectors;
mddev->delta_disks = mddev->raid_disks;
- mddev->degraded = mddev->raid_disks;
mddev->raid_disks *= 2;
/* make sure it will be not marked as dirty */
mddev->recovery_cp = MaxSector;
conf = setup_conf(mddev);
- conf->scale_disks = 2;
+ if (!IS_ERR(conf))
+ list_for_each_entry(rdev, &mddev->disks, same_set)
+ if (rdev->raid_disk >= 0)
+ rdev->new_raid_disk = rdev->raid_disk * 2;
+
return conf;
}
diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h
index 3824a087e17c..2316ac2e8e21 100644
--- a/drivers/md/raid10.h
+++ b/drivers/md/raid10.h
@@ -38,11 +38,6 @@ struct r10_private_data_s {
int chunk_shift; /* shift from chunks to sectors */
sector_t chunk_mask;
- int scale_disks; /* When starting array, multiply
- * each ->raid_disk by this.
- * Need for raid0->raid10 migration
- */
-
struct list_head retry_list;
/* queue pending writes and submit them on unplug */
struct bio_list pending_bio_list;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index d2c0f94fa37d..96c690279fc6 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -277,12 +277,13 @@ out:
return sh;
}
-static void shrink_buffers(struct stripe_head *sh, int num)
+static void shrink_buffers(struct stripe_head *sh)
{
struct page *p;
int i;
+ int num = sh->raid_conf->pool_size;
- for (i=0; i<num ; i++) {
+ for (i = 0; i < num ; i++) {
p = sh->dev[i].page;
if (!p)
continue;
@@ -291,11 +292,12 @@ static void shrink_buffers(struct stripe_head *sh, int num)
}
}
-static int grow_buffers(struct stripe_head *sh, int num)
+static int grow_buffers(struct stripe_head *sh)
{
int i;
+ int num = sh->raid_conf->pool_size;
- for (i=0; i<num; i++) {
+ for (i = 0; i < num; i++) {
struct page *page;
if (!(page = alloc_page(GFP_KERNEL))) {
@@ -364,6 +366,73 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector,
return NULL;
}
+/*
+ * Need to check if array has failed when deciding whether to:
+ * - start an array
+ * - remove non-faulty devices
+ * - add a spare
+ * - allow a reshape
+ * This determination is simple when no reshape is happening.
+ * However if there is a reshape, we need to carefully check
+ * both the before and after sections.
+ * This is because some failed devices may only affect one
+ * of the two sections, and some non-in_sync devices may
+ * be insync in the section most affected by failed devices.
+ */
+static int has_failed(raid5_conf_t *conf)
+{
+ int degraded;
+ int i;
+ if (conf->mddev->reshape_position == MaxSector)
+ return conf->mddev->degraded > conf->max_degraded;
+
+ rcu_read_lock();
+ degraded = 0;
+ for (i = 0; i < conf->previous_raid_disks; i++) {
+ mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
+ if (!rdev || test_bit(Faulty, &rdev->flags))
+ degraded++;
+ else if (test_bit(In_sync, &rdev->flags))
+ ;
+ else
+ /* not in-sync or faulty.
+ * If the reshape increases the number of devices,
+ * this is being recovered by the reshape, so
+ * this 'previous' section is not in_sync.
+ * If the number of devices is being reduced however,
+ * the device can only be part of the array if
+ * we are reverting a reshape, so this section will
+ * be in-sync.
+ */
+ if (conf->raid_disks >= conf->previous_raid_disks)
+ degraded++;
+ }
+ rcu_read_unlock();
+ if (degraded > conf->max_degraded)
+ return 1;
+ rcu_read_lock();
+ degraded = 0;
+ for (i = 0; i < conf->raid_disks; i++) {
+ mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
+ if (!rdev || test_bit(Faulty, &rdev->flags))
+ degraded++;
+ else if (test_bit(In_sync, &rdev->flags))
+ ;
+ else
+ /* not in-sync or faulty.
+ * If reshape increases the number of devices, this
+ * section has already been recovered, else it
+ * almost certainly hasn't.
+ */
+ if (conf->raid_disks <= conf->previous_raid_disks)
+ degraded++;
+ }
+ rcu_read_unlock();
+ if (degraded > conf->max_degraded)
+ return 1;
+ return 0;
+}
+
static void unplug_slaves(mddev_t *mddev);
static void raid5_unplug_device(struct request_queue *q);
@@ -1240,19 +1309,18 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
static int grow_one_stripe(raid5_conf_t *conf)
{
struct stripe_head *sh;
- int disks = max(conf->raid_disks, conf->previous_raid_disks);
sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL);
if (!sh)
return 0;
- memset(sh, 0, sizeof(*sh) + (disks-1)*sizeof(struct r5dev));
+ memset(sh, 0, sizeof(*sh) + (conf->pool_size-1)*sizeof(struct r5dev));
sh->raid_conf = conf;
spin_lock_init(&sh->lock);
#ifdef CONFIG_MULTICORE_RAID456
init_waitqueue_head(&sh->ops.wait_for_ops);
#endif
- if (grow_buffers(sh, disks)) {
- shrink_buffers(sh, disks);
+ if (grow_buffers(sh)) {
+ shrink_buffers(sh);
kmem_cache_free(conf->slab_cache, sh);
return 0;
}
@@ -1468,7 +1536,7 @@ static int drop_one_stripe(raid5_conf_t *conf)
if (!sh)
return 0;
BUG_ON(atomic_read(&sh->count));
- shrink_buffers(sh, conf->pool_size);
+ shrink_buffers(sh);
kmem_cache_free(conf->slab_cache, sh);
atomic_dec(&conf->active_stripes);
return 1;
@@ -2963,7 +3031,6 @@ static void handle_stripe5(struct stripe_head *sh)
mdk_rdev_t *rdev;
dev = &sh->dev[i];
- clear_bit(R5_Insync, &dev->flags);
pr_debug("check %d: state 0x%lx toread %p read %p write %p "
"written %p\n", i, dev->flags, dev->toread, dev->read,
@@ -3000,17 +3067,27 @@ static void handle_stripe5(struct stripe_head *sh)
blocked_rdev = rdev;
atomic_inc(&rdev->nr_pending);
}
- if (!rdev || !test_bit(In_sync, &rdev->flags)) {
+ clear_bit(R5_Insync, &dev->flags);
+ if (!rdev)
+ /* Not in-sync */;
+ else if (test_bit(In_sync, &rdev->flags))
+ set_bit(R5_Insync, &dev->flags);
+ else {
+ /* could be in-sync depending on recovery/reshape status */
+ if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset)
+ set_bit(R5_Insync, &dev->flags);
+ }
+ if (!test_bit(R5_Insync, &dev->flags)) {
/* The ReadError flag will just be confusing now */
clear_bit(R5_ReadError, &dev->flags);
clear_bit(R5_ReWrite, &dev->flags);
}
- if (!rdev || !test_bit(In_sync, &rdev->flags)
- || test_bit(R5_ReadError, &dev->flags)) {
+ if (test_bit(R5_ReadError, &dev->flags))
+ clear_bit(R5_Insync, &dev->flags);
+ if (!test_bit(R5_Insync, &dev->flags)) {
s.failed++;
s.failed_num = i;
- } else
- set_bit(R5_Insync, &dev->flags);
+ }
}
rcu_read_unlock();
@@ -3244,7 +3321,6 @@ static void handle_stripe6(struct stripe_head *sh)
for (i=disks; i--; ) {
mdk_rdev_t *rdev;
dev = &sh->dev[i];
- clear_bit(R5_Insync, &dev->flags);
pr_debug("check %d: state 0x%lx read %p write %p written %p\n",
i, dev->flags, dev->toread, dev->towrite, dev->written);
@@ -3282,18 +3358,28 @@ static void handle_stripe6(struct stripe_head *sh)
blocked_rdev = rdev;
atomic_inc(&rdev->nr_pending);
}
- if (!rdev || !test_bit(In_sync, &rdev->flags)) {
+ clear_bit(R5_Insync, &dev->flags);
+ if (!rdev)
+ /* Not in-sync */;
+ else if (test_bit(In_sync, &rdev->flags))
+ set_bit(R5_Insync, &dev->flags);
+ else {
+ /* in sync if before recovery_offset */
+ if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset)
+ set_bit(R5_Insync, &dev->flags);
+ }
+ if (!test_bit(R5_Insync, &dev->flags)) {
/* The ReadError flag will just be confusing now */
clear_bit(R5_ReadError, &dev->flags);
clear_bit(R5_ReWrite, &dev->flags);
}
- if (!rdev || !test_bit(In_sync, &rdev->flags)
- || test_bit(R5_ReadError, &dev->flags)) {
+ if (test_bit(R5_ReadError, &dev->flags))
+ clear_bit(R5_Insync, &dev->flags);
+ if (!test_bit(R5_Insync, &dev->flags)) {
if (s.failed < 2)
r6s.failed_num[s.failed] = i;
s.failed++;
- } else
- set_bit(R5_Insync, &dev->flags);
+ }
}
rcu_read_unlock();
@@ -4971,8 +5057,10 @@ static int run(mddev_t *mddev)
list_for_each_entry(rdev, &mddev->disks, same_set) {
if (rdev->raid_disk < 0)
continue;
- if (test_bit(In_sync, &rdev->flags))
+ if (test_bit(In_sync, &rdev->flags)) {
working_disks++;
+ continue;
+ }
/* This disc is not fully in-sync. However if it
* just stored parity (beyond the recovery_offset),
* when we don't need to be concerned about the
@@ -5005,7 +5093,7 @@ static int run(mddev_t *mddev)
mddev->degraded = (max(conf->raid_disks, conf->previous_raid_disks)
- working_disks);
- if (mddev->degraded > conf->max_degraded) {
+ if (has_failed(conf)) {
printk(KERN_ERR "md/raid:%s: not enough operational devices"
" (%d/%d failed)\n",
mdname(mddev), mddev->degraded, conf->raid_disks);
@@ -5207,6 +5295,7 @@ static int raid5_spare_active(mddev_t *mddev)
for (i = 0; i < conf->raid_disks; i++) {
tmp = conf->disks + i;
if (tmp->rdev
+ && tmp->rdev->recovery_offset == MaxSector
&& !test_bit(Faulty, &tmp->rdev->flags)
&& !test_and_set_bit(In_sync, &tmp->rdev->flags)) {
unsigned long flags;
@@ -5242,7 +5331,7 @@ static int raid5_remove_disk(mddev_t *mddev, int number)
* isn't possible.
*/
if (!test_bit(Faulty, &rdev->flags) &&
- mddev->degraded <= conf->max_degraded &&
+ !has_failed(conf) &&
number < conf->raid_disks) {
err = -EBUSY;
goto abort;
@@ -5270,7 +5359,7 @@ static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
int first = 0;
int last = conf->raid_disks - 1;
- if (mddev->degraded > conf->max_degraded)
+ if (has_failed(conf))
/* no point adding a device */
return -EINVAL;
@@ -5362,7 +5451,7 @@ static int check_reshape(mddev_t *mddev)
if (mddev->bitmap)
/* Cannot grow a bitmap yet */
return -EBUSY;
- if (mddev->degraded > conf->max_degraded)
+ if (has_failed(conf))
return -EINVAL;
if (mddev->delta_disks < 0) {
/* We might be able to shrink, but the devices must
@@ -5437,8 +5526,13 @@ static int raid5_start_reshape(mddev_t *mddev)
/* Add some new drives, as many as will fit.
* We know there are enough to make the newly sized array work.
+ * Don't add devices if we are reducing the number of
+ * devices in the array. This is because it is not possible
+ * to correctly record the "partially reconstructed" state of
+ * such devices during the reshape and confusion could result.
*/
- list_for_each_entry(rdev, &mddev->disks, same_set)
+ if (mddev->delta_disks >= 0)
+ list_for_each_entry(rdev, &mddev->disks, same_set)
if (rdev->raid_disk < 0 &&
!test_bit(Faulty, &rdev->flags)) {
if (raid5_add_disk(mddev, rdev) == 0) {
@@ -5460,7 +5554,7 @@ static int raid5_start_reshape(mddev_t *mddev)
}
/* When a reshape changes the number of devices, ->degraded
- * is measured against the large of the pre and post number of
+ * is measured against the larger of the pre and post number of
* devices.*/
if (mddev->delta_disks > 0) {
spin_lock_irqsave(&conf->device_lock, flags);
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 2decc597bda7..ce2fcdd4ab90 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2754,6 +2754,7 @@ config MYRI10GE_DCA
config NETXEN_NIC
tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC"
depends on PCI
+ select FW_LOADER
help
This enables the support for NetXen's Gigabit Ethernet card.
@@ -2819,6 +2820,7 @@ config BNX2X
config QLCNIC
tristate "QLOGIC QLCNIC 1/10Gb Converged Ethernet NIC Support"
depends on PCI
+ select FW_LOADER
help
This driver supports QLogic QLE8240 and QLE8242 Converged Ethernet
devices.
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 949d7a9dcf92..117432222a09 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -3073,7 +3073,6 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod;
struct l2_fhdr *rx_hdr;
int rx_pkt = 0, pg_ring_used = 0;
- struct pci_dev *pdev = bp->pdev;
hw_cons = bnx2_get_hw_rx_cons(bnapi);
sw_cons = rxr->rx_cons;
@@ -3099,12 +3098,10 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
skb = rx_buf->skb;
prefetchw(skb);
- if (!get_dma_ops(&pdev->dev)->sync_single_for_cpu) {
- next_rx_buf =
- &rxr->rx_buf_ring[
- RX_RING_IDX(NEXT_RX_BD(sw_cons))];
- prefetch(next_rx_buf->desc);
- }
+ next_rx_buf =
+ &rxr->rx_buf_ring[RX_RING_IDX(NEXT_RX_BD(sw_cons))];
+ prefetch(next_rx_buf->desc);
+
rx_buf->skb = NULL;
dma_addr = dma_unmap_addr(rx_buf, mapping);
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index fe925663d39a..80471269977a 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -3919,8 +3919,9 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev)
HC_INDEX_DEF_C_ETH_ISCSI_CQ_CONS;
context->cstorm_st_context.status_block_id = BNX2X_DEF_SB_ID;
- context->xstorm_st_context.statistics_data = (cli |
- XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE);
+ if (cli < MAX_X_STAT_COUNTER_ID)
+ context->xstorm_st_context.statistics_data = cli |
+ XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE;
context->xstorm_ag_context.cdu_reserved =
CDU_RSRVD_VALUE_TYPE_A(BNX2X_HW_CID(BNX2X_ISCSI_L2_CID, func),
@@ -3928,10 +3929,12 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev)
ETH_CONNECTION_TYPE);
/* reset xstorm per client statistics */
- val = BAR_XSTRORM_INTMEM +
- XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
- for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++)
- CNIC_WR(dev, val + i * 4, 0);
+ if (cli < MAX_X_STAT_COUNTER_ID) {
+ val = BAR_XSTRORM_INTMEM +
+ XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
+ for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++)
+ CNIC_WR(dev, val + i * 4, 0);
+ }
cp->tx_cons_ptr =
&cp->bnx2x_def_status_blk->c_def_status_block.index_values[
@@ -3978,9 +3981,11 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev)
BNX2X_ISCSI_RX_SB_INDEX_NUM;
context->ustorm_st_context.common.clientId = cli;
context->ustorm_st_context.common.status_block_id = BNX2X_DEF_SB_ID;
- context->ustorm_st_context.common.flags =
- USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS;
- context->ustorm_st_context.common.statistics_counter_id = cli;
+ if (cli < MAX_U_STAT_COUNTER_ID) {
+ context->ustorm_st_context.common.flags =
+ USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS;
+ context->ustorm_st_context.common.statistics_counter_id = cli;
+ }
context->ustorm_st_context.common.mc_alignment_log_size = 0;
context->ustorm_st_context.common.bd_buff_size =
cp->l2_single_buf_size;
@@ -4011,10 +4016,13 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev)
/* client tstorm info */
tstorm_client.mtu = cp->l2_single_buf_size - 14;
- tstorm_client.config_flags =
- (TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE |
- TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE);
- tstorm_client.statistics_counter_id = cli;
+ tstorm_client.config_flags = TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE;
+
+ if (cli < MAX_T_STAT_COUNTER_ID) {
+ tstorm_client.config_flags |=
+ TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE;
+ tstorm_client.statistics_counter_id = cli;
+ }
CNIC_WR(dev, BAR_TSTRORM_INTMEM +
TSTORM_CLIENT_CONFIG_OFFSET(port, cli),
@@ -4024,16 +4032,21 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev)
((u32 *)&tstorm_client)[1]);
/* reset tstorm per client statistics */
- val = BAR_TSTRORM_INTMEM +
- TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
- for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++)
- CNIC_WR(dev, val + i * 4, 0);
+ if (cli < MAX_T_STAT_COUNTER_ID) {
+
+ val = BAR_TSTRORM_INTMEM +
+ TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
+ for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++)
+ CNIC_WR(dev, val + i * 4, 0);
+ }
/* reset ustorm per client statistics */
- val = BAR_USTRORM_INTMEM +
- USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
- for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++)
- CNIC_WR(dev, val + i * 4, 0);
+ if (cli < MAX_U_STAT_COUNTER_ID) {
+ val = BAR_USTRORM_INTMEM +
+ USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
+ for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++)
+ CNIC_WR(dev, val + i * 4, 0);
+ }
cp->rx_cons_ptr =
&cp->bnx2x_def_status_blk->u_def_status_block.index_values[
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index 3c58db595285..23786ee34bed 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -1181,7 +1181,8 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
if (netif_msg_drv(priv))
printk(KERN_ERR "%s: Could not attach to PHY\n",
dev->name);
- return PTR_ERR(priv->phy);
+ rc = PTR_ERR(priv->phy);
+ goto fail;
}
if ((rc = register_netdev(dev))) {
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index ebdea0891665..68a80893dce1 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -1047,15 +1047,14 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
goto err_register;
/* print bus type/speed/width info */
- e_info("(PCI%s:%s:%s) ",
- ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
- ((hw->bus_speed == e1000_bus_speed_133) ? "133MHz" :
- (hw->bus_speed == e1000_bus_speed_120) ? "120MHz" :
- (hw->bus_speed == e1000_bus_speed_100) ? "100MHz" :
- (hw->bus_speed == e1000_bus_speed_66) ? "66MHz" : "33MHz"),
- ((hw->bus_width == e1000_bus_width_64) ? "64-bit" : "32-bit"));
-
- e_info("%pM\n", netdev->dev_addr);
+ e_info("(PCI%s:%dMHz:%d-bit) %pM\n",
+ ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
+ ((hw->bus_speed == e1000_bus_speed_133) ? 133 :
+ (hw->bus_speed == e1000_bus_speed_120) ? 120 :
+ (hw->bus_speed == e1000_bus_speed_100) ? 100 :
+ (hw->bus_speed == e1000_bus_speed_66) ? 66 : 33),
+ ((hw->bus_width == e1000_bus_width_64) ? 64 : 32),
+ netdev->dev_addr);
/* carrier off reporting is important to ethtool even BEFORE open */
netif_carrier_off(netdev);
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 0630980a2722..0060e422f171 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -40,7 +40,7 @@
#include <asm/io.h>
#define DRV_NAME "ehea"
-#define DRV_VERSION "EHEA_0103"
+#define DRV_VERSION "EHEA_0105"
/* eHEA capability flags */
#define DLPAR_PORT_ADD_REM 1
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index f547894ff48f..8b92acb448c2 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -867,6 +867,7 @@ static int ehea_poll(struct napi_struct *napi, int budget)
ehea_reset_cq_ep(pr->send_cq);
ehea_reset_cq_n1(pr->recv_cq);
ehea_reset_cq_n1(pr->send_cq);
+ rmb();
cqe = ehea_poll_rq1(pr->qp, &wqe_index);
cqe_skb = ehea_poll_cq(pr->send_cq);
@@ -2859,6 +2860,7 @@ static void ehea_reset_port(struct work_struct *work)
container_of(work, struct ehea_port, reset_task);
struct net_device *dev = port->netdev;
+ mutex_lock(&dlpar_mem_lock);
port->resets++;
mutex_lock(&port->port_lock);
netif_stop_queue(dev);
@@ -2881,6 +2883,7 @@ static void ehea_reset_port(struct work_struct *work)
netif_wake_queue(dev);
out:
mutex_unlock(&port->port_lock);
+ mutex_unlock(&dlpar_mem_lock);
}
static void ehea_rereg_mrs(struct work_struct *work)
@@ -3542,10 +3545,7 @@ static int ehea_mem_notifier(struct notifier_block *nb,
int ret = NOTIFY_BAD;
struct memory_notify *arg = data;
- if (!mutex_trylock(&dlpar_mem_lock)) {
- ehea_info("ehea_mem_notifier must not be called parallelized");
- goto out;
- }
+ mutex_lock(&dlpar_mem_lock);
switch (action) {
case MEM_CANCEL_OFFLINE:
@@ -3574,7 +3574,6 @@ static int ehea_mem_notifier(struct notifier_block *nb,
out_unlock:
mutex_unlock(&dlpar_mem_lock);
-out:
return ret;
}
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c
index 2b3e16db5c82..e0d33281ec98 100644
--- a/drivers/net/enic/vnic_dev.c
+++ b/drivers/net/enic/vnic_dev.c
@@ -709,7 +709,7 @@ int vnic_dev_init_prov(struct vnic_dev *vdev, u8 *buf, u32 len)
{
u64 a0, a1 = len;
int wait = 1000;
- u64 prov_pa;
+ dma_addr_t prov_pa;
void *prov_buf;
int ret;
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 46c69cd06553..28b53d1cd4f1 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -381,10 +381,14 @@ static void gfar_init_mac(struct net_device *ndev)
/* Insert receive time stamps into padding alignment bytes */
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) {
rctrl &= ~RCTRL_PAL_MASK;
- rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE | RCTRL_PADDING(8);
+ rctrl |= RCTRL_PADDING(8);
priv->padding = 8;
}
+ /* Enable HW time stamping if requested from user space */
+ if (priv->hwts_rx_en)
+ rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE;
+
/* keep vlan related bits if it's enabled */
if (priv->vlgrp) {
rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT;
@@ -747,7 +751,8 @@ static int gfar_of_init(struct of_device *ofdev, struct net_device **pdev)
FSL_GIANFAR_DEV_HAS_CSUM |
FSL_GIANFAR_DEV_HAS_VLAN |
FSL_GIANFAR_DEV_HAS_MAGIC_PACKET |
- FSL_GIANFAR_DEV_HAS_EXTENDED_HASH;
+ FSL_GIANFAR_DEV_HAS_EXTENDED_HASH |
+ FSL_GIANFAR_DEV_HAS_TIMER;
ctype = of_get_property(np, "phy-connection-type", NULL);
@@ -805,12 +810,20 @@ static int gfar_hwtstamp_ioctl(struct net_device *netdev,
switch (config.rx_filter) {
case HWTSTAMP_FILTER_NONE:
- priv->hwts_rx_en = 0;
+ if (priv->hwts_rx_en) {
+ stop_gfar(netdev);
+ priv->hwts_rx_en = 0;
+ startup_gfar(netdev);
+ }
break;
default:
if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER))
return -ERANGE;
- priv->hwts_rx_en = 1;
+ if (!priv->hwts_rx_en) {
+ stop_gfar(netdev);
+ priv->hwts_rx_en = 1;
+ startup_gfar(netdev);
+ }
config.rx_filter = HWTSTAMP_FILTER_ALL;
break;
}
@@ -2642,6 +2655,10 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
dma_unmap_single(&priv->ofdev->dev, bdp->bufPtr,
priv->rx_buffer_size, DMA_FROM_DEVICE);
+ if (unlikely(!(bdp->status & RXBD_ERR) &&
+ bdp->length > priv->rx_buffer_size))
+ bdp->status = RXBD_LARGE;
+
/* We drop the frame if we failed to allocate a new buffer */
if (unlikely(!newskb || !(bdp->status & RXBD_LAST) ||
bdp->status & RXBD_ERR)) {
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index c50a7541ffec..3a93a81872b8 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -2077,25 +2077,6 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
return 0;
}
-/*
- * this function must be called before setting the new value of
- * rx_itr_setting
- */
-static bool ixgbe_reenable_rsc(struct ixgbe_adapter *adapter,
- struct ethtool_coalesce *ec)
-{
- /* check the old value and enable RSC if necessary */
- if ((adapter->rx_itr_setting == 0) &&
- (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)) {
- adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
- adapter->netdev->features |= NETIF_F_LRO;
- DPRINTK(PROBE, INFO, "rx-usecs set to %d, re-enabling RSC\n",
- ec->rx_coalesce_usecs);
- return true;
- }
- return false;
-}
-
static int ixgbe_set_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec)
{
@@ -2124,9 +2105,6 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
(1000000/ec->rx_coalesce_usecs < IXGBE_MIN_INT_RATE))
return -EINVAL;
- /* check the old value and enable RSC if necessary */
- need_reset = ixgbe_reenable_rsc(adapter, ec);
-
/* store the value in ints/second */
adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs;
@@ -2135,9 +2113,6 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
/* clear the lower bit as its used for dynamic state */
adapter->rx_itr_setting &= ~1;
} else if (ec->rx_coalesce_usecs == 1) {
- /* check the old value and enable RSC if necessary */
- need_reset = ixgbe_reenable_rsc(adapter, ec);
-
/* 1 means dynamic mode */
adapter->rx_eitr_param = 20000;
adapter->rx_itr_setting = 1;
@@ -2157,10 +2132,11 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
*/
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED;
- netdev->features &= ~NETIF_F_LRO;
- DPRINTK(PROBE, INFO,
- "rx-usecs set to 0, disabling RSC\n");
-
+ if (netdev->features & NETIF_F_LRO) {
+ netdev->features &= ~NETIF_F_LRO;
+ DPRINTK(PROBE, INFO, "rx-usecs set to 0, "
+ "disabling LRO/RSC\n");
+ }
need_reset = true;
}
}
@@ -2255,6 +2231,9 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data)
}
} else if (!adapter->rx_itr_setting) {
netdev->features &= ~ETH_FLAG_LRO;
+ if (data & ETH_FLAG_LRO)
+ DPRINTK(PROBE, INFO, "rx-usecs set to 0, "
+ "LRO/RSC cannot be enabled.\n");
}
}
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index b2af2f67f604..ce30c62a97f7 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -5282,6 +5282,10 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot;
u64 non_eop_descs = 0, restart_queue = 0;
+ if (test_bit(__IXGBE_DOWN, &adapter->state) ||
+ test_bit(__IXGBE_RESETTING, &adapter->state))
+ return;
+
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
u64 rsc_count = 0;
u64 rsc_flush = 0;
diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c
index 09e1911ff510..48325a5beff2 100644
--- a/drivers/net/ixgbe/ixgbe_phy.c
+++ b/drivers/net/ixgbe/ixgbe_phy.c
@@ -575,6 +575,8 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
* 4 SFP_DA_CORE1 - 82599-specific
* 5 SFP_SR/LR_CORE0 - 82599-specific
* 6 SFP_SR/LR_CORE1 - 82599-specific
+ * 7 SFP_act_lmt_DA_CORE0 - 82599-specific
+ * 8 SFP_act_lmt_DA_CORE1 - 82599-specific
*/
if (hw->mac.type == ixgbe_mac_82598EB) {
if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c
index ce5d6e909218..c27f4291b350 100644
--- a/drivers/net/lib82596.c
+++ b/drivers/net/lib82596.c
@@ -1343,7 +1343,7 @@ static void set_multicast_list(struct net_device *dev)
DEB(DEB_MULTI,
printk(KERN_DEBUG
"%s: set multicast list, %d entries, promisc %s, allmulti %s\n",
- dev->name, dev->mc_count,
+ dev->name, netdev_mc_count(dev),
dev->flags & IFF_PROMISC ? "ON" : "OFF",
dev->flags & IFF_ALLMULTI ? "ON" : "OFF"));
diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c
index 8e9704f5c122..869f0ea43a5b 100644
--- a/drivers/net/mipsnet.c
+++ b/drivers/net/mipsnet.c
@@ -247,7 +247,7 @@ static const struct net_device_ops mipsnet_netdev_ops = {
.ndo_set_mac_address = eth_mac_addr,
};
-static int __init mipsnet_probe(struct platform_device *dev)
+static int __devinit mipsnet_probe(struct platform_device *dev)
{
struct net_device *netdev;
int err;
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c
index f26e54716c88..3a41b6a84a68 100644
--- a/drivers/net/netxen/netxen_nic_ctx.c
+++ b/drivers/net/netxen/netxen_nic_ctx.c
@@ -629,7 +629,8 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
if (addr == NULL) {
dev_err(&pdev->dev, "%s: failed to allocate tx desc ring\n",
netdev->name);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto err_out_free;
}
tx_ring->desc_head = (struct cmd_desc_type0 *)addr;
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index 5c496f8d7c49..29d7b93d0493 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -1159,9 +1159,6 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong off)
window = CRB_HI(off);
- if (adapter->ahw.crb_win == window)
- return;
-
writel(window, addr);
if (readl(addr) != window) {
if (printk_ratelimit())
@@ -1169,7 +1166,6 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong off)
"failed to set CRB window to %d off 0x%lx\n",
window, off);
}
- adapter->ahw.crb_win = window;
}
static void __iomem *
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 045a7c8f5bdf..c865dda2adf1 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -218,7 +218,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
if (cmd_buf_arr == NULL) {
dev_err(&pdev->dev, "%s: failed to allocate cmd buffer ring\n",
netdev->name);
- return -ENOMEM;
+ goto err_out;
}
memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
tx_ring->cmd_buf_arr = cmd_buf_arr;
@@ -230,7 +230,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
if (rds_ring == NULL) {
dev_err(&pdev->dev, "%s: failed to allocate rds ring struct\n",
netdev->name);
- return -ENOMEM;
+ goto err_out;
}
recv_ctx->rds_rings = rds_ring;
@@ -1805,9 +1805,10 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
netxen_ctx_msg msg = 0;
struct list_head *head;
+ spin_lock(&rds_ring->lock);
+
producer = rds_ring->producer;
- spin_lock(&rds_ring->lock);
head = &rds_ring->free_list;
while (!list_empty(head)) {
@@ -1829,7 +1830,6 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
producer = get_next_index(producer, rds_ring->num_desc);
}
- spin_unlock(&rds_ring->lock);
if (count) {
rds_ring->producer = producer;
@@ -1853,6 +1853,8 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
NETXEN_RCV_PRODUCER_OFFSET), msg);
}
}
+
+ spin_unlock(&rds_ring->lock);
}
static void
@@ -1864,10 +1866,11 @@ netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
int producer, count = 0;
struct list_head *head;
- producer = rds_ring->producer;
if (!spin_trylock(&rds_ring->lock))
return;
+ producer = rds_ring->producer;
+
head = &rds_ring->free_list;
while (!list_empty(head)) {
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 6f77a768ba88..bfdef72c5d5e 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -1727,6 +1727,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
+ PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "cis/DP83903.cis"),
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 64e6a84bbbbe..307cd1721e91 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -1505,12 +1505,20 @@ irq_done:
writeb(cor & ~COR_IREQ_ENA, smc->base + MOT_LAN + CISREG_COR);
writeb(cor, smc->base + MOT_LAN + CISREG_COR);
}
-#ifdef DOES_NOT_WORK
- if (smc->base != NULL) { /* Megahertz MFC's */
- readb(smc->base+MEGAHERTZ_ISR);
- readb(smc->base+MEGAHERTZ_ISR);
+
+ if ((smc->base != NULL) && /* Megahertz MFC's */
+ (smc->manfid == MANFID_MEGAHERTZ) &&
+ (smc->cardid == PRODID_MEGAHERTZ_EM3288)) {
+
+ u_char tmp;
+ tmp = readb(smc->base+MEGAHERTZ_ISR);
+ tmp = readb(smc->base+MEGAHERTZ_ISR);
+
+ /* Retrigger interrupt if needed */
+ writeb(tmp, smc->base + MEGAHERTZ_ISR);
+ writeb(tmp, smc->base + MEGAHERTZ_ISR);
}
-#endif
+
spin_unlock(&smc->lock);
return IRQ_RETVAL(handled);
}
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
index dbd003453737..29c39ff85de5 100644
--- a/drivers/net/phy/lxt.c
+++ b/drivers/net/phy/lxt.c
@@ -226,6 +226,7 @@ module_exit(lxt_exit);
static struct mdio_device_id lxt_tbl[] = {
{ 0x78100000, 0xfffffff0 },
{ 0x001378e0, 0xfffffff0 },
+ { 0x00137a10, 0xfffffff0 },
{ }
};
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 2111c7bbf578..7985165e84fc 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -717,11 +717,24 @@ static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port)
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
}
+/* Enable Rx/Tx */
+static void sky2_enable_rx_tx(struct sky2_port *sky2)
+{
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ u16 reg;
+
+ reg = gma_read16(hw, port, GM_GP_CTRL);
+ reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
+ gma_write16(hw, port, GM_GP_CTRL, reg);
+}
+
/* Force a renegotiation */
static void sky2_phy_reinit(struct sky2_port *sky2)
{
spin_lock_bh(&sky2->phy_lock);
sky2_phy_init(sky2->hw, sky2->port);
+ sky2_enable_rx_tx(sky2);
spin_unlock_bh(&sky2->phy_lock);
}
@@ -2040,7 +2053,6 @@ static void sky2_link_up(struct sky2_port *sky2)
{
struct sky2_hw *hw = sky2->hw;
unsigned port = sky2->port;
- u16 reg;
static const char *fc_name[] = {
[FC_NONE] = "none",
[FC_TX] = "tx",
@@ -2048,10 +2060,7 @@ static void sky2_link_up(struct sky2_port *sky2)
[FC_BOTH] = "both",
};
- /* enable Rx/Tx */
- reg = gma_read16(hw, port, GM_GP_CTRL);
- reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
- gma_write16(hw, port, GM_GP_CTRL, reg);
+ sky2_enable_rx_tx(sky2);
gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index c0e70006374e..06b552fca63d 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -367,8 +367,8 @@ static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x6F3F, 0x6F3D, };
static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
-#define dr32(reg) readl(de->regs + (reg))
-#define dw32(reg,val) writel((val), de->regs + (reg))
+#define dr32(reg) ioread32(de->regs + (reg))
+#define dw32(reg, val) iowrite32((val), de->regs + (reg))
static void de_rx_err_acct (struct de_private *de, unsigned rx_tail,
@@ -1706,6 +1706,7 @@ static void __devinit de21040_get_mac_address (struct de_private *de)
int value, boguscnt = 100000;
do {
value = dr32(ROMCmd);
+ rmb();
} while (value < 0 && --boguscnt > 0);
de->dev->dev_addr[i] = value;
udelay(1);
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 4a34833b85dd..807470e156af 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3215,6 +3215,8 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
__func__, __LINE__, (u32) skb);
if (skb) {
skb->data = skb->head + NET_SKB_PAD;
+ skb->len = 0;
+ skb_reset_tail_pointer(skb);
__skb_queue_head(&ugeth->rx_recycle, skb);
}
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 0a3c41faea9c..4dd23513c5af 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -1334,7 +1334,6 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp)
/* check for port already opened, if not set the termios */
serial->open_count++;
if (serial->open_count == 1) {
- tty->low_latency = 1;
serial->rx_state = RX_IDLE;
/* Force default termio settings */
_hso_serial_set_termios(tty, NULL);
diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c
index b504bd561362..d14e207de1df 100644
--- a/drivers/net/vxge/vxge-main.c
+++ b/drivers/net/vxge/vxge-main.c
@@ -2262,7 +2262,8 @@ start:
vxge_debug_init(VXGE_ERR,
"%s: memory allocation failed",
VXGE_DRIVER_NAME);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto alloc_entries_failed;
}
vdev->vxge_entries =
@@ -2271,8 +2272,8 @@ start:
if (!vdev->vxge_entries) {
vxge_debug_init(VXGE_ERR, "%s: memory allocation failed",
VXGE_DRIVER_NAME);
- kfree(vdev->entries);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto alloc_vxge_entries_failed;
}
for (i = 0, j = 0; i < vdev->no_of_vpath; i++) {
@@ -2303,22 +2304,32 @@ start:
vxge_debug_init(VXGE_ERR,
"%s: MSI-X enable failed for %d vectors, ret: %d",
VXGE_DRIVER_NAME, vdev->intr_cnt, ret);
+ if ((max_config_vpath != VXGE_USE_DEFAULT) || (ret < 3)) {
+ ret = -ENODEV;
+ goto enable_msix_failed;
+ }
+
kfree(vdev->entries);
kfree(vdev->vxge_entries);
vdev->entries = NULL;
vdev->vxge_entries = NULL;
-
- if ((max_config_vpath != VXGE_USE_DEFAULT) || (ret < 3))
- return -ENODEV;
/* Try with less no of vector by reducing no of vpaths count */
temp = (ret - 1)/2;
vxge_close_vpaths(vdev, temp);
vdev->no_of_vpath = temp;
goto start;
- } else if (ret < 0)
- return -ENODEV;
-
+ } else if (ret < 0) {
+ ret = -ENODEV;
+ goto enable_msix_failed;
+ }
return 0;
+
+enable_msix_failed:
+ kfree(vdev->vxge_entries);
+alloc_vxge_entries_failed:
+ kfree(vdev->entries);
+alloc_entries_failed:
+ return ret;
}
static int vxge_enable_msix(struct vxgedev *vdev)
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
index e0c244b02f05..31c008042bfe 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -126,6 +126,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT;
ah->ah_noise_floor = -95; /* until first NF calibration is run */
sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO;
+ ah->ah_current_channel = &sc->channels[0];
/*
* Find the mac version
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index db72461c486b..29b31a694b59 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -594,6 +594,7 @@ static int prism2_config(struct pcmcia_device *link)
local_info_t *local;
int ret = 1;
struct hostap_cs_priv *hw_priv;
+ unsigned long flags;
PDEBUG(DEBUG_FLOW, "prism2_config()\n");
@@ -625,9 +626,15 @@ static int prism2_config(struct pcmcia_device *link)
local->hw_priv = hw_priv;
hw_priv->link = link;
+ /*
+ * Make sure the IRQ handler cannot proceed until at least
+ * dev->base_addr is initialized.
+ */
+ spin_lock_irqsave(&local->irq_init_lock, flags);
+
ret = pcmcia_request_irq(link, prism2_interrupt);
if (ret)
- goto failed;
+ goto failed_unlock;
/*
* This actually configures the PCMCIA socket -- setting up
@@ -636,11 +643,13 @@ static int prism2_config(struct pcmcia_device *link)
*/
ret = pcmcia_request_configuration(link, &link->conf);
if (ret)
- goto failed;
+ goto failed_unlock;
dev->irq = link->irq;
dev->base_addr = link->io.BasePort1;
+ spin_unlock_irqrestore(&local->irq_init_lock, flags);
+
/* Finally, report what we've done */
printk(KERN_INFO "%s: index 0x%02x: ",
dev_info, link->conf.ConfigIndex);
@@ -667,6 +676,8 @@ static int prism2_config(struct pcmcia_device *link)
return ret;
+ failed_unlock:
+ spin_unlock_irqrestore(&local->irq_init_lock, flags);
failed:
kfree(hw_priv);
prism2_release((u_long)link);
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index ff9b5c882184..2f999fc94f60 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -2621,6 +2621,18 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id)
iface = netdev_priv(dev);
local = iface->local;
+ /* Detect early interrupt before driver is fully configued */
+ spin_lock(&local->irq_init_lock);
+ if (!dev->base_addr) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n",
+ dev->name);
+ }
+ spin_unlock(&local->irq_init_lock);
+ return IRQ_HANDLED;
+ }
+ spin_unlock(&local->irq_init_lock);
+
prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0);
if (local->func->card_present && !local->func->card_present(local)) {
@@ -3138,6 +3150,7 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx,
spin_lock_init(&local->cmdlock);
spin_lock_init(&local->baplock);
spin_lock_init(&local->lock);
+ spin_lock_init(&local->irq_init_lock);
mutex_init(&local->rid_bap_mtx);
if (card_idx < 0 || card_idx >= MAX_PARM_DEVICES)
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
index 3d238917af07..1ba33be98b25 100644
--- a/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -654,7 +654,7 @@ struct local_info {
rwlock_t iface_lock; /* hostap_interfaces read lock; use write lock
* when removing entries from the list.
* TX and RX paths can use read lock. */
- spinlock_t cmdlock, baplock, lock;
+ spinlock_t cmdlock, baplock, lock, irq_init_lock;
struct mutex rid_bap_mtx;
u16 infofid; /* MAC buffer id for info frame */
/* txfid, intransmitfid, next_txtid, and next_alloc are protected by
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index a732f1094e5d..7d614c4d3c62 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -1299,6 +1299,11 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
sta_id = ba_resp->sta_id;
tid = ba_resp->tid;
agg = &priv->stations[sta_id].tid[tid].agg;
+ if (unlikely(agg->txq_id != scd_flow)) {
+ IWL_ERR(priv, "BA scd_flow %d does not match txq_id %d\n",
+ scd_flow, agg->txq_id);
+ return;
+ }
/* Find index just before block-ack window */
index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 7726e67044c0..24aff654fa9c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3391,10 +3391,12 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
int ret;
u8 sta_id;
- sta_priv->common.sta_id = IWL_INVALID_STATION;
-
IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
sta->addr);
+ mutex_lock(&priv->mutex);
+ IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
+ sta->addr);
+ sta_priv->common.sta_id = IWL_INVALID_STATION;
atomic_set(&sta_priv->pending_frames, 0);
if (vif->type == NL80211_IFTYPE_AP)
@@ -3406,6 +3408,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
IWL_ERR(priv, "Unable to add station %pM (%d)\n",
sta->addr, ret);
/* Should we return success if return code is EEXIST ? */
+ mutex_unlock(&priv->mutex);
return ret;
}
@@ -3415,6 +3418,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
sta->addr);
iwl_rs_rate_init(priv, sta, sta_id);
+ mutex_unlock(&priv->mutex);
return 0;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 5d3f51ff2f0d..386c5f96eff8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -491,6 +491,7 @@ void iwl_bg_abort_scan(struct work_struct *work)
mutex_lock(&priv->mutex);
+ cancel_delayed_work_sync(&priv->scan_check);
set_bit(STATUS_SCAN_ABORTING, &priv->status);
iwl_send_scan_abort(priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 83a26361a9b5..c27c13fbb1ae 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -1373,10 +1373,14 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw,
IWL_DEBUG_INFO(priv, "received request to remove station %pM\n",
sta->addr);
+ mutex_lock(&priv->mutex);
+ IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n",
+ sta->addr);
ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr);
if (ret)
IWL_ERR(priv, "Error removing station %pM\n",
sta->addr);
+ mutex_unlock(&priv->mutex);
return ret;
}
EXPORT_SYMBOL(iwl_mac_sta_remove);
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 6c353cacc8d6..a27872de4106 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -3437,10 +3437,13 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
bool is_ap = vif->type == NL80211_IFTYPE_STATION;
u8 sta_id;
- sta_priv->common.sta_id = IWL_INVALID_STATION;
-
IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
sta->addr);
+ mutex_lock(&priv->mutex);
+ IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
+ sta->addr);
+ sta_priv->common.sta_id = IWL_INVALID_STATION;
+
ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap,
&sta_id);
@@ -3448,6 +3451,7 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
IWL_ERR(priv, "Unable to add station %pM (%d)\n",
sta->addr, ret);
/* Should we return success if return code is EEXIST ? */
+ mutex_unlock(&priv->mutex);
return ret;
}
@@ -3457,6 +3461,7 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
sta->addr);
iwl3945_rs_rate_init(priv, sta, sta_id);
+ mutex_unlock(&priv->mutex);
return 0;
}
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
index 6a04c2157f73..817fffc0de4b 100644
--- a/drivers/net/wireless/libertas_tf/main.c
+++ b/drivers/net/wireless/libertas_tf/main.c
@@ -549,7 +549,7 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
prxpd = (struct rxpd *) skb->data;
- stats.flag = 0;
+ memset(&stats, 0, sizeof(stats));
if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK)))
stats.flag |= RX_FLAG_FAILED_FCS_CRC;
stats.freq = priv->cur_freq;
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
index 07c4528f6e6b..a5ea89cde8c4 100644
--- a/drivers/net/wireless/p54/p54pci.c
+++ b/drivers/net/wireless/p54/p54pci.c
@@ -41,6 +41,8 @@ static DEFINE_PCI_DEVICE_TABLE(p54p_table) = {
{ PCI_DEVICE(0x1260, 0x3877) },
/* Intersil PRISM Javelin/Xbow Wireless LAN adapter */
{ PCI_DEVICE(0x1260, 0x3886) },
+ /* Intersil PRISM Xbow Wireless LAN adapter (Symbol AP-300) */
+ { PCI_DEVICE(0x1260, 0xffff) },
{ },
};
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 796828fce34c..c9171be74564 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -340,7 +340,7 @@ int dmar_disabled = 0;
int dmar_disabled = 1;
#endif /*CONFIG_DMAR_DEFAULT_ON*/
-static int __initdata dmar_map_gfx = 1;
+static int dmar_map_gfx = 1;
static int dmar_forcedac;
static int intel_iommu_strict;
@@ -1874,14 +1874,15 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
}
}
if (found) {
+ spin_unlock_irqrestore(&device_domain_lock, flags);
free_devinfo_mem(info);
domain_exit(domain);
domain = found;
} else {
list_add(&info->link, &domain->devices);
list_add(&info->global, &device_domain_list);
+ spin_unlock_irqrestore(&device_domain_lock, flags);
}
- spin_unlock_irqrestore(&device_domain_lock, flags);
}
found_domain:
@@ -3603,7 +3604,8 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
pte = dmar_domain->pgd;
if (dma_pte_present(pte)) {
free_pgtable_page(dmar_domain->pgd);
- dmar_domain->pgd = (struct dma_pte *)dma_pte_addr(pte);
+ dmar_domain->pgd = (struct dma_pte *)
+ phys_to_virt(dma_pte_addr(pte));
}
dmar_domain->agaw--;
}
@@ -3719,6 +3721,12 @@ static void __devinit quirk_iommu_rwbf(struct pci_dev *dev)
*/
printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
rwbf_quirk = 1;
+
+ /* https://bugzilla.redhat.com/show_bug.cgi?id=538163 */
+ if (dev->revision == 0x07) {
+ printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n");
+ dmar_map_gfx = 0;
+ }
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 60f30e7f1c8c..740fb4ea9669 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -2292,6 +2292,7 @@ void pci_msi_off(struct pci_dev *dev)
pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
}
}
+EXPORT_SYMBOL_GPL(pci_msi_off);
#ifndef HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE
int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size)
diff --git a/drivers/pci/pcie/pme/pcie_pme.c b/drivers/pci/pcie/pme/pcie_pme.c
index aac285a16b62..d672a0a63816 100644
--- a/drivers/pci/pcie/pme/pcie_pme.c
+++ b/drivers/pci/pcie/pme/pcie_pme.c
@@ -34,7 +34,7 @@
* being registered. Consequently, the interrupt-based PCIe PME signaling will
* not be used by any PCIe root ports in that case.
*/
-static bool pcie_pme_disabled;
+static bool pcie_pme_disabled = true;
/*
* The PCI Express Base Specification 2.0, Section 6.1.8, states the following:
@@ -64,12 +64,19 @@ bool pcie_pme_msi_disabled;
static int __init pcie_pme_setup(char *str)
{
- if (!strcmp(str, "off"))
- pcie_pme_disabled = true;
- else if (!strcmp(str, "force"))
+ if (!strncmp(str, "auto", 4))
+ pcie_pme_disabled = false;
+ else if (!strncmp(str, "force", 5))
pcie_pme_force_enable = true;
- else if (!strcmp(str, "nomsi"))
- pcie_pme_msi_disabled = true;
+
+ str = strchr(str, ',');
+ if (str) {
+ str++;
+ str += strspn(str, " \t");
+ if (*str && !strcmp(str, "nomsi"))
+ pcie_pme_msi_disabled = true;
+ }
+
return 1;
}
__setup("pcie_pme=", pcie_pme_setup);
diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c
index 92a8f6cacda9..34647fc1ee98 100644
--- a/drivers/rtc/rtc-davinci.c
+++ b/drivers/rtc/rtc-davinci.c
@@ -29,6 +29,7 @@
#include <linux/bcd.h>
#include <linux/platform_device.h>
#include <linux/io.h>
+#include <linux/slab.h>
/*
* The DaVinci RTC is a simple RTC with the following
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index de033b7ac21f..d827ce570a8c 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -777,7 +777,7 @@ static int __devinit ds1307_probe(struct i2c_client *client,
read_rtc:
/* read RTC registers */
- tmp = ds1307->read_block_data(ds1307->client, 0, 8, buf);
+ tmp = ds1307->read_block_data(ds1307->client, ds1307->offset, 8, buf);
if (tmp != 8) {
pr_debug("read error %d\n", tmp);
err = -EIO;
@@ -862,7 +862,7 @@ read_rtc:
if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
tmp += 12;
i2c_smbus_write_byte_data(client,
- DS1307_REG_HOUR,
+ ds1307->offset + DS1307_REG_HOUR,
bin2bcd(tmp));
}
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index 9eb62a256e9a..cd6cf575902e 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -930,6 +930,83 @@ static void cpm_uart_config_port(struct uart_port *port, int flags)
}
}
+#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_CPM_CONSOLE)
+/*
+ * Write a string to the serial port
+ * Note that this is called with interrupts already disabled
+ */
+static void cpm_uart_early_write(struct uart_cpm_port *pinfo,
+ const char *string, u_int count)
+{
+ unsigned int i;
+ cbd_t __iomem *bdp, *bdbase;
+ unsigned char *cpm_outp_addr;
+
+ /* Get the address of the host memory buffer.
+ */
+ bdp = pinfo->tx_cur;
+ bdbase = pinfo->tx_bd_base;
+
+ /*
+ * Now, do each character. This is not as bad as it looks
+ * since this is a holding FIFO and not a transmitting FIFO.
+ * We could add the complexity of filling the entire transmit
+ * buffer, but we would just wait longer between accesses......
+ */
+ for (i = 0; i < count; i++, string++) {
+ /* Wait for transmitter fifo to empty.
+ * Ready indicates output is ready, and xmt is doing
+ * that, not that it is ready for us to send.
+ */
+ while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
+ ;
+
+ /* Send the character out.
+ * If the buffer address is in the CPM DPRAM, don't
+ * convert it.
+ */
+ cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr),
+ pinfo);
+ *cpm_outp_addr = *string;
+
+ out_be16(&bdp->cbd_datlen, 1);
+ setbits16(&bdp->cbd_sc, BD_SC_READY);
+
+ if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
+ bdp = bdbase;
+ else
+ bdp++;
+
+ /* if a LF, also do CR... */
+ if (*string == 10) {
+ while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
+ ;
+
+ cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr),
+ pinfo);
+ *cpm_outp_addr = 13;
+
+ out_be16(&bdp->cbd_datlen, 1);
+ setbits16(&bdp->cbd_sc, BD_SC_READY);
+
+ if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
+ bdp = bdbase;
+ else
+ bdp++;
+ }
+ }
+
+ /*
+ * Finally, Wait for transmitter & holding register to empty
+ * and restore the IER
+ */
+ while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
+ ;
+
+ pinfo->tx_cur = bdp;
+}
+#endif
+
#ifdef CONFIG_CONSOLE_POLL
/* Serial polling routines for writing and reading from the uart while
* in an interrupt or debug context.
@@ -999,7 +1076,7 @@ static void cpm_put_poll_char(struct uart_port *port,
static char ch[2];
ch[0] = (char)c;
- cpm_uart_early_write(pinfo->port.line, ch, 1);
+ cpm_uart_early_write(pinfo, ch, 1);
}
#endif /* CONFIG_CONSOLE_POLL */
@@ -1130,9 +1207,6 @@ static void cpm_uart_console_write(struct console *co, const char *s,
u_int count)
{
struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index];
- unsigned int i;
- cbd_t __iomem *bdp, *bdbase;
- unsigned char *cp;
unsigned long flags;
int nolock = oops_in_progress;
@@ -1142,66 +1216,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
spin_lock_irqsave(&pinfo->port.lock, flags);
}
- /* Get the address of the host memory buffer.
- */
- bdp = pinfo->tx_cur;
- bdbase = pinfo->tx_bd_base;
-
- /*
- * Now, do each character. This is not as bad as it looks
- * since this is a holding FIFO and not a transmitting FIFO.
- * We could add the complexity of filling the entire transmit
- * buffer, but we would just wait longer between accesses......
- */
- for (i = 0; i < count; i++, s++) {
- /* Wait for transmitter fifo to empty.
- * Ready indicates output is ready, and xmt is doing
- * that, not that it is ready for us to send.
- */
- while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
- ;
-
- /* Send the character out.
- * If the buffer address is in the CPM DPRAM, don't
- * convert it.
- */
- cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
- *cp = *s;
-
- out_be16(&bdp->cbd_datlen, 1);
- setbits16(&bdp->cbd_sc, BD_SC_READY);
-
- if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
- bdp = bdbase;
- else
- bdp++;
-
- /* if a LF, also do CR... */
- if (*s == 10) {
- while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
- ;
-
- cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
- *cp = 13;
-
- out_be16(&bdp->cbd_datlen, 1);
- setbits16(&bdp->cbd_sc, BD_SC_READY);
-
- if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
- bdp = bdbase;
- else
- bdp++;
- }
- }
-
- /*
- * Finally, Wait for transmitter & holding register to empty
- * and restore the IER
- */
- while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
- ;
-
- pinfo->tx_cur = bdp;
+ cpm_uart_early_write(pinfo, s, count);
if (unlikely(nolock)) {
local_irq_restore(flags);
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 526307368f8b..ab17c08ddc03 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -821,6 +821,7 @@ static struct pcmcia_device_id serial_ids[] = {
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
+ PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "cis/3CCFEM556.cis"),
diff --git a/drivers/staging/batman-adv/bat_sysfs.c b/drivers/staging/batman-adv/bat_sysfs.c
index e2c000b80ca0..212bc21e6d68 100644
--- a/drivers/staging/batman-adv/bat_sysfs.c
+++ b/drivers/staging/batman-adv/bat_sysfs.c
@@ -225,9 +225,9 @@ static struct bat_attribute *mesh_attrs[] = {
NULL,
};
-static ssize_t transtable_local_read(struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buff, loff_t off, size_t count)
+static ssize_t transtable_local_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buff, loff_t off, size_t count)
{
struct device *dev = to_dev(kobj->parent);
struct net_device *net_dev = to_net_dev(dev);
@@ -235,9 +235,9 @@ static ssize_t transtable_local_read(struct kobject *kobj,
return hna_local_fill_buffer_text(net_dev, buff, count, off);
}
-static ssize_t transtable_global_read(struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buff, loff_t off, size_t count)
+static ssize_t transtable_global_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buff, loff_t off, size_t count)
{
struct device *dev = to_dev(kobj->parent);
struct net_device *net_dev = to_net_dev(dev);
@@ -245,9 +245,9 @@ static ssize_t transtable_global_read(struct kobject *kobj,
return hna_global_fill_buffer_text(net_dev, buff, count, off);
}
-static ssize_t originators_read(struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buff, loff_t off, size_t count)
+static ssize_t originators_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buff, loff_t off, size_t count)
{
struct device *dev = to_dev(kobj->parent);
struct net_device *net_dev = to_net_dev(dev);
@@ -255,9 +255,9 @@ static ssize_t originators_read(struct kobject *kobj,
return orig_fill_buffer_text(net_dev, buff, count, off);
}
-static ssize_t vis_data_read(struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buff, loff_t off, size_t count)
+static ssize_t vis_data_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buff, loff_t off, size_t count)
{
struct device *dev = to_dev(kobj->parent);
struct net_device *net_dev = to_net_dev(dev);
diff --git a/drivers/staging/batman-adv/device.c b/drivers/staging/batman-adv/device.c
index 7eb6559e0315..32204b5572d0 100644
--- a/drivers/staging/batman-adv/device.c
+++ b/drivers/staging/batman-adv/device.c
@@ -196,7 +196,7 @@ ssize_t bat_device_read(struct file *file, char __user *buf, size_t count,
kfree(device_packet);
if (error)
- return error;
+ return -EFAULT;
return sizeof(struct icmp_packet);
}
diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
index 36a254cd4413..39d112b708e3 100644
--- a/drivers/staging/comedi/drivers/adl_pci9111.c
+++ b/drivers/staging/comedi/drivers/adl_pci9111.c
@@ -824,9 +824,12 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,
plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
false, true, true);
- dev_private->scan_delay =
- (async_cmd->scan_begin_arg / (async_cmd->convert_arg *
- async_cmd->chanlist_len)) - 1;
+ if (async_cmd->scan_begin_src == TRIG_TIMER) {
+ dev_private->scan_delay =
+ (async_cmd->scan_begin_arg /
+ (async_cmd->convert_arg *
+ async_cmd->chanlist_len)) - 1;
+ }
break;
diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
index 81829d6fd287..c374bee25068 100644
--- a/drivers/staging/comedi/drivers/cb_pcidda.c
+++ b/drivers/staging/comedi/drivers/cb_pcidda.c
@@ -52,7 +52,6 @@ Please report success/failure with other different cards to
#include "8255.h"
#define PCI_VENDOR_ID_CB 0x1307 /* PCI vendor number of ComputerBoards */
-#define N_BOARDS 10 /* Number of boards in cb_pcidda_boards */
#define EEPROM_SIZE 128 /* number of entries in eeprom */
#define MAX_AO_CHANNELS 8 /* maximum number of ao channels for supported boards */
@@ -307,7 +306,7 @@ static int cb_pcidda_attach(struct comedi_device *dev,
continue;
}
}
- for (index = 0; index < N_BOARDS; index++) {
+ for (index = 0; index < ARRAY_SIZE(cb_pcidda_boards); index++) {
if (cb_pcidda_boards[index].device_id ==
pcidev->device) {
goto found;
diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c
index 3f53b4d1e4cf..12db555a3a5d 100644
--- a/drivers/staging/hv/channel_mgmt.c
+++ b/drivers/staging/hv/channel_mgmt.c
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/completion.h>
#include "osd.h"
#include "logging.h"
#include "vmbus_private.h"
@@ -293,6 +294,25 @@ void FreeVmbusChannel(struct vmbus_channel *Channel)
Channel);
}
+
+DECLARE_COMPLETION(hv_channel_ready);
+
+/*
+ * Count initialized channels, and ensure all channels are ready when hv_vmbus
+ * module loading completes.
+ */
+static void count_hv_channel(void)
+{
+ static int counter;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
+ if (++counter == MAX_MSG_TYPES)
+ complete(&hv_channel_ready);
+ spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
+}
+
+
/*
* VmbusChannelProcessOffer - Process the offer by creating a channel/device
* associated with this offer
@@ -373,22 +393,21 @@ static void VmbusChannelProcessOffer(void *context)
* can cleanup properly
*/
newChannel->State = CHANNEL_OPEN_STATE;
- cnt = 0;
- while (cnt != MAX_MSG_TYPES) {
+ /* Open IC channels */
+ for (cnt = 0; cnt < MAX_MSG_TYPES; cnt++) {
if (memcmp(&newChannel->OfferMsg.Offer.InterfaceType,
&hv_cb_utils[cnt].data,
- sizeof(struct hv_guid)) == 0) {
+ sizeof(struct hv_guid)) == 0 &&
+ VmbusChannelOpen(newChannel, 2 * PAGE_SIZE,
+ 2 * PAGE_SIZE, NULL, 0,
+ hv_cb_utils[cnt].callback,
+ newChannel) == 0) {
+ hv_cb_utils[cnt].channel = newChannel;
DPRINT_INFO(VMBUS, "%s",
- hv_cb_utils[cnt].log_msg);
-
- if (VmbusChannelOpen(newChannel, 2 * PAGE_SIZE,
- 2 * PAGE_SIZE, NULL, 0,
- hv_cb_utils[cnt].callback,
- newChannel) == 0)
- hv_cb_utils[cnt].channel = newChannel;
+ hv_cb_utils[cnt].log_msg);
+ count_hv_channel();
}
- cnt++;
}
}
DPRINT_EXIT(VMBUS);
diff --git a/drivers/staging/hv/hv_utils.c b/drivers/staging/hv/hv_utils.c
index 8a49aafea37a..2adc9b48ca9c 100644
--- a/drivers/staging/hv/hv_utils.c
+++ b/drivers/staging/hv/hv_utils.c
@@ -24,6 +24,8 @@
#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/reboot.h>
+#include <linux/dmi.h>
+#include <linux/pci.h>
#include "logging.h"
#include "osd.h"
@@ -251,10 +253,36 @@ static void heartbeat_onchannelcallback(void *context)
DPRINT_EXIT(VMBUS);
}
+static const struct pci_device_id __initconst
+hv_utils_pci_table[] __maybe_unused = {
+ { PCI_DEVICE(0x1414, 0x5353) }, /* Hyper-V emulated VGA controller */
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, hv_utils_pci_table);
+
+
+static const struct dmi_system_id __initconst
+hv_utils_dmi_table[] __maybe_unused = {
+ {
+ .ident = "Hyper-V",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
+ DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
+ },
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(dmi, hv_utils_dmi_table);
+
+
static int __init init_hyperv_utils(void)
{
printk(KERN_INFO "Registering HyperV Utility Driver\n");
+ if (!dmi_check_system(hv_utils_dmi_table))
+ return -ENODEV;
+
hv_cb_utils[HV_SHUTDOWN_MSG].channel->OnChannelCallback =
&shutdown_onchannelcallback;
hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback;
diff --git a/drivers/staging/hv/vmbus.h b/drivers/staging/hv/vmbus.h
index 0c6ee0f487f3..3c14b2926e00 100644
--- a/drivers/staging/hv/vmbus.h
+++ b/drivers/staging/hv/vmbus.h
@@ -74,4 +74,6 @@ int vmbus_child_driver_register(struct driver_context *driver_ctx);
void vmbus_child_driver_unregister(struct driver_context *driver_ctx);
void vmbus_get_interface(struct vmbus_channel_interface *interface);
+extern struct completion hv_channel_ready;
+
#endif /* _VMBUS_H_ */
diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
index c21731a12ca7..22c80ece6388 100644
--- a/drivers/staging/hv/vmbus_drv.c
+++ b/drivers/staging/hv/vmbus_drv.c
@@ -27,6 +27,7 @@
#include <linux/pci.h>
#include <linux/dmi.h>
#include <linux/slab.h>
+#include <linux/completion.h>
#include "version_info.h"
#include "osd.h"
#include "logging.h"
@@ -356,6 +357,8 @@ static int vmbus_bus_init(int (*drv_init)(struct hv_driver *drv))
vmbus_drv_obj->GetChannelOffers();
+ wait_for_completion(&hv_channel_ready);
+
cleanup:
DPRINT_EXIT(VMBUS_DRV);
diff --git a/drivers/staging/mrst-touchscreen/intel-mid-touch.c b/drivers/staging/mrst-touchscreen/intel-mid-touch.c
index 1db00975a594..abba22f921be 100644
--- a/drivers/staging/mrst-touchscreen/intel-mid-touch.c
+++ b/drivers/staging/mrst-touchscreen/intel-mid-touch.c
@@ -817,9 +817,9 @@ static int mrstouch_remove(struct spi_device *spi)
free_irq(mrstouchdevp->irq, mrstouchdevp);
input_unregister_device(mrstouchdevp->input);
input_free_device(mrstouchdevp->input);
- kfree(mrstouchdevp);
if (mrstouchdevp->pendet_thrd)
kthread_stop(mrstouchdevp->pendet_thrd);
+ kfree(mrstouchdevp);
return 0;
}
diff --git a/drivers/staging/rt2860/usb_main_dev.c b/drivers/staging/rt2860/usb_main_dev.c
index b740662d095a..674769d2b59b 100644
--- a/drivers/staging/rt2860/usb_main_dev.c
+++ b/drivers/staging/rt2860/usb_main_dev.c
@@ -77,6 +77,7 @@ struct usb_device_id rtusb_usb_id[] = {
{USB_DEVICE(0x083A, 0x7522)}, /* Arcadyan */
{USB_DEVICE(0x0CDE, 0x0022)}, /* ZCOM */
{USB_DEVICE(0x0586, 0x3416)}, /* Zyxel */
+ {USB_DEVICE(0x0586, 0x341a)}, /* Zyxel NWD-270N */
{USB_DEVICE(0x0CDE, 0x0025)}, /* Zyxel */
{USB_DEVICE(0x1740, 0x9701)}, /* EnGenius */
{USB_DEVICE(0x1740, 0x9702)}, /* EnGenius */
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
index dacefea78113..49ab9fa9ffa7 100644
--- a/drivers/staging/rtl8187se/r8180_core.c
+++ b/drivers/staging/rtl8187se/r8180_core.c
@@ -66,8 +66,6 @@ static int hwseqnum = 0;
static int hwwep = 0;
static int channels = 0x3fff;
-#define eqMacAddr(a, b) (((a)[0] == (b)[0] && (a)[1] == (b)[1] && (a)[2] == (b)[2] && (a)[3] == (b)[3] && (a)[4] == (b)[4] && (a)[5] == (b)[5]) ? 1 : 0)
-#define cpMacAddr(des, src) ((des)[0] = (src)[0], (des)[1] = (src)[1], (des)[2] = (src)[2], (des)[3] = (src)[3], (des)[4] = (src)[4], (des)[5] = (src)[5])
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, rtl8180_pci_id_tbl);
MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c
index 447d6474a70c..1b6890611fb6 100644
--- a/drivers/staging/rtl8192su/r8192U_core.c
+++ b/drivers/staging/rtl8192su/r8192U_core.c
@@ -112,28 +112,29 @@ u32 rt_global_debug_component = \
#define CAM_CONTENT_COUNT 8
static const struct usb_device_id rtl8192_usb_id_tbl[] = {
- /* Realtek */
- {USB_DEVICE(0x0bda, 0x8171)},
- {USB_DEVICE(0x0bda, 0x8192)},
- {USB_DEVICE(0x0bda, 0x8709)},
- /* Corega */
- {USB_DEVICE(0x07aa, 0x0043)},
- /* Belkin */
- {USB_DEVICE(0x050d, 0x805E)},
- {USB_DEVICE(0x050d, 0x815F)}, /* Belkin F5D8053 v6 */
- /* Sitecom */
- {USB_DEVICE(0x0df6, 0x0031)},
- {USB_DEVICE(0x0df6, 0x004b)}, /* WL-349 */
- /* EnGenius */
- {USB_DEVICE(0x1740, 0x9201)},
- /* Dlink */
- {USB_DEVICE(0x2001, 0x3301)},
- /* Zinwell */
- {USB_DEVICE(0x5a57, 0x0290)},
- /* Guillemot */
- {USB_DEVICE(0x06f8, 0xe031)},
- //92SU
+ {USB_DEVICE(0x0bda, 0x8171)}, /* Realtek */
{USB_DEVICE(0x0bda, 0x8172)},
+ {USB_DEVICE(0x0bda, 0x8173)},
+ {USB_DEVICE(0x0bda, 0x8174)},
+ {USB_DEVICE(0x0bda, 0x8712)},
+ {USB_DEVICE(0x0bda, 0x8713)},
+ {USB_DEVICE(0x07aa, 0x0047)},
+ {USB_DEVICE(0x07d1, 0x3303)},
+ {USB_DEVICE(0x07d1, 0x3302)},
+ {USB_DEVICE(0x07d1, 0x3300)},
+ {USB_DEVICE(0x1740, 0x9603)},
+ {USB_DEVICE(0x1740, 0x9605)},
+ {USB_DEVICE(0x050d, 0x815F)},
+ {USB_DEVICE(0x06f8, 0xe031)},
+ {USB_DEVICE(0x7392, 0x7611)},
+ {USB_DEVICE(0x7392, 0x7612)},
+ {USB_DEVICE(0x7392, 0x7622)},
+ {USB_DEVICE(0x0DF6, 0x0045)},
+ {USB_DEVICE(0x0E66, 0x0015)},
+ {USB_DEVICE(0x0E66, 0x0016)},
+ {USB_DEVICE(0x0b05, 0x1786)},
+ /* these are not in the official list */
+ {USB_DEVICE(0x0df6, 0x004b)}, /* WL-349 */
{}
};
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
index 2bede271a2f0..f38472c2e75c 100644
--- a/drivers/staging/rtl8192u/r8192U_core.c
+++ b/drivers/staging/rtl8192u/r8192U_core.c
@@ -121,6 +121,8 @@ static const struct usb_device_id rtl8192_usb_id_tbl[] = {
{USB_DEVICE(0x2001, 0x3301)},
/* Zinwell */
{USB_DEVICE(0x5a57, 0x0290)},
+ /* LG */
+ {USB_DEVICE(0x043e, 0x7a01)},
{}
};
diff --git a/drivers/staging/tm6000/tm6000-alsa.c b/drivers/staging/tm6000/tm6000-alsa.c
index ce081cd44ad4..273e26ede650 100644
--- a/drivers/staging/tm6000/tm6000-alsa.c
+++ b/drivers/staging/tm6000/tm6000-alsa.c
@@ -15,6 +15,7 @@
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/usb.h>
+#include <linux/slab.h>
#include <asm/delay.h>
#include <sound/core.h>
diff --git a/drivers/staging/tm6000/tm6000-cards.c b/drivers/staging/tm6000/tm6000-cards.c
index cedd9044022f..6a9ae40c7c6d 100644
--- a/drivers/staging/tm6000/tm6000-cards.c
+++ b/drivers/staging/tm6000/tm6000-cards.c
@@ -24,6 +24,7 @@
#include <linux/i2c.h>
#include <linux/usb.h>
#include <linux/version.h>
+#include <linux/slab.h>
#include <media/v4l2-common.h>
#include <media/tuner.h>
#include <media/tvaudio.h>
diff --git a/drivers/staging/tm6000/tm6000-core.c b/drivers/staging/tm6000/tm6000-core.c
index 27f3f551b545..c3690e3580da 100644
--- a/drivers/staging/tm6000/tm6000-core.c
+++ b/drivers/staging/tm6000/tm6000-core.c
@@ -22,6 +22,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/i2c.h>
#include "tm6000.h"
diff --git a/drivers/staging/tm6000/tm6000-dvb.c b/drivers/staging/tm6000/tm6000-dvb.c
index 261e66acbe46..86c1c8b5f25a 100644
--- a/drivers/staging/tm6000/tm6000-dvb.c
+++ b/drivers/staging/tm6000/tm6000-dvb.c
@@ -18,6 +18,7 @@
*/
#include <linux/kernel.h>
+#include <linux/slab.h>
#include <linux/usb.h>
#include "tm6000.h"
diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c
index 52408164036f..6a499f0eb594 100644
--- a/drivers/staging/usbip/usbip_common.c
+++ b/drivers/staging/usbip/usbip_common.c
@@ -378,47 +378,67 @@ int usbip_thread(void *param)
complete_and_exit(&ut->thread_done, 0);
}
+static void stop_rx_thread(struct usbip_device *ud)
+{
+ if (ud->tcp_rx.thread != NULL) {
+ send_sig(SIGKILL, ud->tcp_rx.thread, 1);
+ wait_for_completion(&ud->tcp_rx.thread_done);
+ usbip_udbg("rx_thread for ud %p has finished\n", ud);
+ }
+}
+
+static void stop_tx_thread(struct usbip_device *ud)
+{
+ if (ud->tcp_tx.thread != NULL) {
+ send_sig(SIGKILL, ud->tcp_tx.thread, 1);
+ wait_for_completion(&ud->tcp_tx.thread_done);
+ usbip_udbg("tx_thread for ud %p has finished\n", ud);
+ }
+}
+
int usbip_start_threads(struct usbip_device *ud)
{
/*
* threads are invoked per one device (per one connection).
*/
struct task_struct *th;
+ int err = 0;
th = kthread_run(usbip_thread, (void *)&ud->tcp_rx, "usbip");
if (IS_ERR(th)) {
printk(KERN_WARNING
"Unable to start control thread\n");
- return PTR_ERR(th);
+ err = PTR_ERR(th);
+ goto ust_exit;
}
+
th = kthread_run(usbip_thread, (void *)&ud->tcp_tx, "usbip");
if (IS_ERR(th)) {
printk(KERN_WARNING
"Unable to start control thread\n");
- return PTR_ERR(th);
+ err = PTR_ERR(th);
+ goto tx_thread_err;
}
/* confirm threads are starting */
wait_for_completion(&ud->tcp_rx.thread_done);
wait_for_completion(&ud->tcp_tx.thread_done);
+
return 0;
+
+tx_thread_err:
+ stop_rx_thread(ud);
+
+ust_exit:
+ return err;
}
EXPORT_SYMBOL_GPL(usbip_start_threads);
void usbip_stop_threads(struct usbip_device *ud)
{
/* kill threads related to this sdev, if v.c. exists */
- if (ud->tcp_rx.thread != NULL) {
- send_sig(SIGKILL, ud->tcp_rx.thread, 1);
- wait_for_completion(&ud->tcp_rx.thread_done);
- usbip_udbg("rx_thread for ud %p has finished\n", ud);
- }
-
- if (ud->tcp_tx.thread != NULL) {
- send_sig(SIGKILL, ud->tcp_tx.thread, 1);
- wait_for_completion(&ud->tcp_tx.thread_done);
- usbip_udbg("tx_thread for ud %p has finished\n", ud);
- }
+ stop_rx_thread(ud);
+ stop_tx_thread(ud);
}
EXPORT_SYMBOL_GPL(usbip_stop_threads);
diff --git a/drivers/staging/wlags49_h2/wl_enc.c b/drivers/staging/wlags49_h2/wl_enc.c
index 48c44c8fdb28..26cf5486edd6 100644
--- a/drivers/staging/wlags49_h2/wl_enc.c
+++ b/drivers/staging/wlags49_h2/wl_enc.c
@@ -62,6 +62,7 @@
/*******************************************************************************
* include files
******************************************************************************/
+#include <linux/string.h>
#include <wl_version.h>
#include <debug.h>
diff --git a/drivers/staging/wlags49_h2/wl_sysfs.h b/drivers/staging/wlags49_h2/wl_sysfs.h
index 6d96d03cf490..fa658c38001e 100644
--- a/drivers/staging/wlags49_h2/wl_sysfs.h
+++ b/drivers/staging/wlags49_h2/wl_sysfs.h
@@ -2,6 +2,6 @@
extern void register_wlags_sysfs(struct net_device *);
extern void unregister_wlags_sysfs(struct net_device *);
#else
-static void register_wlags_sysfs(struct net_device *) { return; };
-static void unregister_wlags_sysfs(struct net_device *) { return; };
+static inline void register_wlags_sysfs(struct net_device *net) { }
+static inline void unregister_wlags_sysfs(struct net_device *net) { }
#endif
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index de98a94d1853..a6bd53ace035 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1272,8 +1272,7 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg)
static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
{
- int w, i;
- struct usb_interface *intf;
+ int w;
/* Remote wakeup is needed only when we actually go to sleep.
* For things like FREEZE and QUIESCE, if the device is already
@@ -1285,16 +1284,10 @@ static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
return;
}
- /* If remote wakeup is permitted, see whether any interface drivers
+ /* Enable remote wakeup if it is allowed, even if no interface drivers
* actually want it.
*/
- w = 0;
- if (device_may_wakeup(&udev->dev) && udev->actconfig) {
- for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
- intf = udev->actconfig->interface[i];
- w |= intf->needs_remote_wakeup;
- }
- }
+ w = device_may_wakeup(&udev->dev);
/* If the device is autosuspended with the wrong wakeup setting,
* autoresume now so the setting can be changed.
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index a73e08fdab36..fd4c36ea5e46 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -416,8 +416,11 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
/* A length of zero means transfer the whole sg list */
len = length;
if (len == 0) {
- for_each_sg(sg, sg, nents, i)
- len += sg->length;
+ struct scatterlist *sg2;
+ int j;
+
+ for_each_sg(sg, sg2, nents, j)
+ len += sg2->length;
}
} else {
/*
diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c
index 38226e9a371d..95dd4662d6a8 100644
--- a/drivers/usb/gadget/f_eem.c
+++ b/drivers/usb/gadget/f_eem.c
@@ -469,8 +469,7 @@ static int eem_unwrap(struct gether *port,
crc = get_unaligned_le32(skb->data + len
- ETH_FCS_LEN);
crc2 = ~crc32_le(~0,
- skb->data,
- skb->len - ETH_FCS_LEN);
+ skb->data, len - ETH_FCS_LEN);
} else {
crc = get_unaligned_be32(skb->data + len
- ETH_FCS_LEN);
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 7d05a0be5c60..4ce899c9b165 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -321,8 +321,8 @@ struct fsg_dev;
/* Data shared by all the FSG instances. */
struct fsg_common {
struct usb_gadget *gadget;
- struct fsg_dev *fsg;
- struct fsg_dev *prev_fsg;
+ struct fsg_dev *fsg, *new_fsg;
+ wait_queue_head_t fsg_wait;
/* filesem protects: backing files in use */
struct rw_semaphore filesem;
@@ -351,7 +351,6 @@ struct fsg_common {
enum fsg_state state; /* For exception handling */
unsigned int exception_req_tag;
- u8 config, new_config;
enum data_direction data_dir;
u32 data_size;
u32 data_size_from_cmnd;
@@ -595,7 +594,7 @@ static int fsg_setup(struct usb_function *f,
u16 w_value = le16_to_cpu(ctrl->wValue);
u16 w_length = le16_to_cpu(ctrl->wLength);
- if (!fsg->common->config)
+ if (!fsg_is_set(fsg->common))
return -EOPNOTSUPP;
switch (ctrl->bRequest) {
@@ -2303,24 +2302,20 @@ static int alloc_request(struct fsg_common *common, struct usb_ep *ep,
return -ENOMEM;
}
-/*
- * Reset interface setting and re-init endpoint state (toggle etc).
- * Call with altsetting < 0 to disable the interface. The only other
- * available altsetting is 0, which enables the interface.
- */
-static int do_set_interface(struct fsg_common *common, int altsetting)
+/* Reset interface setting and re-init endpoint state (toggle etc). */
+static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg)
{
- int rc = 0;
- int i;
- const struct usb_endpoint_descriptor *d;
+ const struct usb_endpoint_descriptor *d;
+ struct fsg_dev *fsg;
+ int i, rc = 0;
if (common->running)
DBG(common, "reset interface\n");
reset:
/* Deallocate the requests */
- if (common->prev_fsg) {
- struct fsg_dev *fsg = common->prev_fsg;
+ if (common->fsg) {
+ fsg = common->fsg;
for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
struct fsg_buffhd *bh = &common->buffhds[i];
@@ -2345,88 +2340,53 @@ reset:
fsg->bulk_out_enabled = 0;
}
- common->prev_fsg = 0;
+ common->fsg = NULL;
+ wake_up(&common->fsg_wait);
}
common->running = 0;
- if (altsetting < 0 || rc != 0)
+ if (!new_fsg || rc)
return rc;
- DBG(common, "set interface %d\n", altsetting);
+ common->fsg = new_fsg;
+ fsg = common->fsg;
- if (fsg_is_set(common)) {
- struct fsg_dev *fsg = common->fsg;
- common->prev_fsg = common->fsg;
+ /* Enable the endpoints */
+ d = fsg_ep_desc(common->gadget,
+ &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc);
+ rc = enable_endpoint(common, fsg->bulk_in, d);
+ if (rc)
+ goto reset;
+ fsg->bulk_in_enabled = 1;
+
+ d = fsg_ep_desc(common->gadget,
+ &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc);
+ rc = enable_endpoint(common, fsg->bulk_out, d);
+ if (rc)
+ goto reset;
+ fsg->bulk_out_enabled = 1;
+ common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize);
+ clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
- /* Enable the endpoints */
- d = fsg_ep_desc(common->gadget,
- &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc);
- rc = enable_endpoint(common, fsg->bulk_in, d);
+ /* Allocate the requests */
+ for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
+ struct fsg_buffhd *bh = &common->buffhds[i];
+
+ rc = alloc_request(common, fsg->bulk_in, &bh->inreq);
if (rc)
goto reset;
- fsg->bulk_in_enabled = 1;
-
- d = fsg_ep_desc(common->gadget,
- &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc);
- rc = enable_endpoint(common, fsg->bulk_out, d);
+ rc = alloc_request(common, fsg->bulk_out, &bh->outreq);
if (rc)
goto reset;
- fsg->bulk_out_enabled = 1;
- common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize);
- clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
-
- /* Allocate the requests */
- for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
- struct fsg_buffhd *bh = &common->buffhds[i];
-
- rc = alloc_request(common, fsg->bulk_in, &bh->inreq);
- if (rc)
- goto reset;
- rc = alloc_request(common, fsg->bulk_out, &bh->outreq);
- if (rc)
- goto reset;
- bh->inreq->buf = bh->outreq->buf = bh->buf;
- bh->inreq->context = bh->outreq->context = bh;
- bh->inreq->complete = bulk_in_complete;
- bh->outreq->complete = bulk_out_complete;
- }
-
- common->running = 1;
- for (i = 0; i < common->nluns; ++i)
- common->luns[i].unit_attention_data = SS_RESET_OCCURRED;
- return rc;
- } else {
- return -EIO;
- }
-}
-
-
-/*
- * Change our operational configuration. This code must agree with the code
- * that returns config descriptors, and with interface altsetting code.
- *
- * It's also responsible for power management interactions. Some
- * configurations might not work with our current power sources.
- * For now we just assume the gadget is always self-powered.
- */
-static int do_set_config(struct fsg_common *common, u8 new_config)
-{
- int rc = 0;
-
- /* Disable the single interface */
- if (common->config != 0) {
- DBG(common, "reset config\n");
- common->config = 0;
- rc = do_set_interface(common, -1);
+ bh->inreq->buf = bh->outreq->buf = bh->buf;
+ bh->inreq->context = bh->outreq->context = bh;
+ bh->inreq->complete = bulk_in_complete;
+ bh->outreq->complete = bulk_out_complete;
}
- /* Enable the interface */
- if (new_config != 0) {
- common->config = new_config;
- rc = do_set_interface(common, 0);
- if (rc != 0)
- common->config = 0; /* Reset on errors */
- }
+ common->running = 1;
+ for (i = 0; i < common->nluns; ++i)
+ common->luns[i].unit_attention_data = SS_RESET_OCCURRED;
return rc;
}
@@ -2437,9 +2397,7 @@ static int do_set_config(struct fsg_common *common, u8 new_config)
static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
{
struct fsg_dev *fsg = fsg_from_func(f);
- fsg->common->prev_fsg = fsg->common->fsg;
- fsg->common->fsg = fsg;
- fsg->common->new_config = 1;
+ fsg->common->new_fsg = fsg;
raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
return 0;
}
@@ -2447,9 +2405,7 @@ static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
static void fsg_disable(struct usb_function *f)
{
struct fsg_dev *fsg = fsg_from_func(f);
- fsg->common->prev_fsg = fsg->common->fsg;
- fsg->common->fsg = fsg;
- fsg->common->new_config = 0;
+ fsg->common->new_fsg = NULL;
raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
}
@@ -2459,19 +2415,17 @@ static void fsg_disable(struct usb_function *f)
static void handle_exception(struct fsg_common *common)
{
siginfo_t info;
- int sig;
int i;
struct fsg_buffhd *bh;
enum fsg_state old_state;
- u8 new_config;
struct fsg_lun *curlun;
unsigned int exception_req_tag;
- int rc;
/* Clear the existing signals. Anything but SIGUSR1 is converted
* into a high-priority EXIT exception. */
for (;;) {
- sig = dequeue_signal_lock(current, &current->blocked, &info);
+ int sig =
+ dequeue_signal_lock(current, &current->blocked, &info);
if (!sig)
break;
if (sig != SIGUSR1) {
@@ -2482,7 +2436,7 @@ static void handle_exception(struct fsg_common *common)
}
/* Cancel all the pending transfers */
- if (fsg_is_set(common)) {
+ if (likely(common->fsg)) {
for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
bh = &common->buffhds[i];
if (bh->inreq_busy)
@@ -2523,7 +2477,6 @@ static void handle_exception(struct fsg_common *common)
common->next_buffhd_to_fill = &common->buffhds[0];
common->next_buffhd_to_drain = &common->buffhds[0];
exception_req_tag = common->exception_req_tag;
- new_config = common->new_config;
old_state = common->state;
if (old_state == FSG_STATE_ABORT_BULK_OUT)
@@ -2573,12 +2526,12 @@ static void handle_exception(struct fsg_common *common)
break;
case FSG_STATE_CONFIG_CHANGE:
- rc = do_set_config(common, new_config);
+ do_set_interface(common, common->new_fsg);
break;
case FSG_STATE_EXIT:
case FSG_STATE_TERMINATED:
- do_set_config(common, 0); /* Free resources */
+ do_set_interface(common, NULL); /* Free resources */
spin_lock_irq(&common->lock);
common->state = FSG_STATE_TERMINATED; /* Stop the thread */
spin_unlock_irq(&common->lock);
@@ -2863,6 +2816,7 @@ buffhds_first_it:
goto error_release;
}
init_completion(&common->thread_notifier);
+ init_waitqueue_head(&common->fsg_wait);
#undef OR
@@ -2957,9 +2911,17 @@ static void fsg_common_release(struct kref *ref)
static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct fsg_dev *fsg = fsg_from_func(f);
+ struct fsg_common *common = fsg->common;
DBG(fsg, "unbind\n");
- fsg_common_put(fsg->common);
+ if (fsg->common->fsg == fsg) {
+ fsg->common->new_fsg = NULL;
+ raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
+ /* FIXME: make interruptible or killable somehow? */
+ wait_event(common->fsg_wait, common->fsg != fsg);
+ }
+
+ fsg_common_put(common);
usb_free_descriptors(fsg->function.descriptors);
usb_free_descriptors(fsg->function.hs_descriptors);
kfree(fsg);
@@ -2970,7 +2932,6 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
{
struct fsg_dev *fsg = fsg_from_func(f);
struct usb_gadget *gadget = c->cdev->gadget;
- int rc;
int i;
struct usb_ep *ep;
@@ -2996,6 +2957,11 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
ep->driver_data = fsg->common; /* claim the endpoint */
fsg->bulk_out = ep;
+ /* Copy descriptors */
+ f->descriptors = usb_copy_descriptors(fsg_fs_function);
+ if (unlikely(!f->descriptors))
+ return -ENOMEM;
+
if (gadget_is_dualspeed(gadget)) {
/* Assume endpoint addresses are the same for both speeds */
fsg_hs_bulk_in_desc.bEndpointAddress =
@@ -3003,16 +2969,17 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
fsg_hs_bulk_out_desc.bEndpointAddress =
fsg_fs_bulk_out_desc.bEndpointAddress;
f->hs_descriptors = usb_copy_descriptors(fsg_hs_function);
- if (unlikely(!f->hs_descriptors))
+ if (unlikely(!f->hs_descriptors)) {
+ usb_free_descriptors(f->descriptors);
return -ENOMEM;
+ }
}
return 0;
autoconf_fail:
ERROR(fsg, "unable to autoconfigure all endpoints\n");
- rc = -ENOTSUPP;
- return rc;
+ return -ENOTSUPP;
}
@@ -3036,11 +3003,6 @@ static int fsg_add(struct usb_composite_dev *cdev,
fsg->function.name = FSG_DRIVER_DESC;
fsg->function.strings = fsg_strings_array;
- fsg->function.descriptors = usb_copy_descriptors(fsg_fs_function);
- if (unlikely(!fsg->function.descriptors)) {
- rc = -ENOMEM;
- goto error_free_fsg;
- }
fsg->function.bind = fsg_bind;
fsg->function.unbind = fsg_unbind;
fsg->function.setup = fsg_setup;
@@ -3056,19 +3018,9 @@ static int fsg_add(struct usb_composite_dev *cdev,
rc = usb_add_function(c, &fsg->function);
if (unlikely(rc))
- goto error_free_all;
-
- fsg_common_get(fsg->common);
- return 0;
-
-error_free_all:
- usb_free_descriptors(fsg->function.descriptors);
- /* fsg_bind() might have copied those; or maybe not? who cares
- * -- free it just in case. */
- usb_free_descriptors(fsg->function.hs_descriptors);
-error_free_fsg:
- kfree(fsg);
-
+ kfree(fsg);
+ else
+ fsg_common_get(fsg->common);
return rc;
}
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c
index 4b0e4a040d6f..d1af253a9105 100644
--- a/drivers/usb/gadget/g_ffs.c
+++ b/drivers/usb/gadget/g_ffs.c
@@ -392,6 +392,17 @@ static int __gfs_do_config(struct usb_configuration *c,
if (unlikely(ret < 0))
return ret;
+ /* After previous do_configs there may be some invalid
+ * pointers in c->interface array. This happens every time
+ * a user space function with fewer interfaces than a user
+ * space function that was run before the new one is run. The
+ * compasit's set_config() assumes that if there is no more
+ * then MAX_CONFIG_INTERFACES interfaces in a configuration
+ * then there is a NULL pointer after the last interface in
+ * c->interface array. We need to make sure this is true. */
+ if (c->next_interface_id < ARRAY_SIZE(c->interface))
+ c->interface[c->next_interface_id] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index 43abf55d8c60..4c3ac5c42237 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -82,7 +82,7 @@ static struct class *usb_gadget_class;
struct printer_dev {
spinlock_t lock; /* lock this structure */
/* lock buffer lists during read/write calls */
- spinlock_t lock_printer_io;
+ struct mutex lock_printer_io;
struct usb_gadget *gadget;
struct usb_request *req; /* for control responses */
u8 config;
@@ -567,7 +567,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
DBG(dev, "printer_read trying to read %d bytes\n", (int)len);
- spin_lock(&dev->lock_printer_io);
+ mutex_lock(&dev->lock_printer_io);
spin_lock_irqsave(&dev->lock, flags);
/* We will use this flag later to check if a printer reset happened
@@ -601,7 +601,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
* call or not.
*/
if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
return -EAGAIN;
}
@@ -648,7 +648,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
if (dev->reset_printer) {
list_add(&current_rx_req->list, &dev->rx_reqs);
spin_unlock_irqrestore(&dev->lock, flags);
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
return -EAGAIN;
}
@@ -673,7 +673,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
dev->current_rx_buf = current_rx_buf;
spin_unlock_irqrestore(&dev->lock, flags);
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
DBG(dev, "printer_read returned %d bytes\n", (int)bytes_copied);
@@ -697,7 +697,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
if (len == 0)
return -EINVAL;
- spin_lock(&dev->lock_printer_io);
+ mutex_lock(&dev->lock_printer_io);
spin_lock_irqsave(&dev->lock, flags);
/* Check if a printer reset happens while we have interrupts on */
@@ -713,7 +713,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
* a NON-Blocking call or not.
*/
if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
return -EAGAIN;
}
@@ -752,7 +752,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
if (copy_from_user(req->buf, buf, size)) {
list_add(&req->list, &dev->tx_reqs);
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
return bytes_copied;
}
@@ -766,14 +766,14 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
if (dev->reset_printer) {
list_add(&req->list, &dev->tx_reqs);
spin_unlock_irqrestore(&dev->lock, flags);
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
return -EAGAIN;
}
if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) {
list_add(&req->list, &dev->tx_reqs);
spin_unlock_irqrestore(&dev->lock, flags);
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
return -EAGAIN;
}
@@ -782,7 +782,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
}
spin_unlock_irqrestore(&dev->lock, flags);
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
DBG(dev, "printer_write sent %d bytes\n", (int)bytes_copied);
@@ -820,11 +820,11 @@ printer_poll(struct file *fd, poll_table *wait)
unsigned long flags;
int status = 0;
- spin_lock(&dev->lock_printer_io);
+ mutex_lock(&dev->lock_printer_io);
spin_lock_irqsave(&dev->lock, flags);
setup_rx_reqs(dev);
spin_unlock_irqrestore(&dev->lock, flags);
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
poll_wait(fd, &dev->rx_wait, wait);
poll_wait(fd, &dev->tx_wait, wait);
@@ -1461,7 +1461,7 @@ autoconf_fail:
}
spin_lock_init(&dev->lock);
- spin_lock_init(&dev->lock_printer_io);
+ mutex_init(&dev->lock_printer_io);
INIT_LIST_HEAD(&dev->tx_reqs);
INIT_LIST_HEAD(&dev->tx_reqs_active);
INIT_LIST_HEAD(&dev->rx_reqs);
@@ -1594,7 +1594,7 @@ cleanup(void)
{
int status;
- spin_lock(&usb_printer_gadget.lock_printer_io);
+ mutex_lock(&usb_printer_gadget.lock_printer_io);
class_destroy(usb_gadget_class);
unregister_chrdev_region(g_printer_devno, 2);
@@ -1602,6 +1602,6 @@ cleanup(void)
if (status)
ERROR(dev, "usb_gadget_unregister_driver %x\n", status);
- spin_unlock(&usb_printer_gadget.lock_printer_io);
+ mutex_unlock(&usb_printer_gadget.lock_printer_io);
}
module_exit(cleanup);
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index d5f4c1d45c97..e724a051bfdd 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -1700,9 +1700,13 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
if (!driver || driver != udc->driver || !driver->unbind)
return -EINVAL;
- dprintk(DEBUG_NORMAL,"usb_gadget_register_driver() '%s'\n",
+ dprintk(DEBUG_NORMAL, "usb_gadget_unregister_driver() '%s'\n",
driver->driver.name);
+ /* report disconnect */
+ if (driver->disconnect)
+ driver->disconnect(&udc->gadget);
+
driver->unbind(&udc->gadget);
device_del(&udc->gadget.dev);
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 16bdf77f582a..3e8dcb5455e3 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -536,17 +536,11 @@ recycle:
list_move(&req->list, &port->read_pool);
}
- /* Push from tty to ldisc; this is immediate with low_latency, and
- * may trigger callbacks to this driver ... so drop the spinlock.
+ /* Push from tty to ldisc; without low_latency set this is handled by
+ * a workqueue, so we won't get callbacks and can hold port_lock
*/
if (tty && do_push) {
- spin_unlock_irq(&port->port_lock);
tty_flip_buffer_push(tty);
- wake_up_interruptible(&tty->read_wait);
- spin_lock_irq(&port->port_lock);
-
- /* tty may have been closed */
- tty = port->port_tty;
}
@@ -784,11 +778,6 @@ static int gs_open(struct tty_struct *tty, struct file *file)
port->open_count = 1;
port->openclose = false;
- /* low_latency means ldiscs work in tasklet context, without
- * needing a workqueue schedule ... easier to keep up.
- */
- tty->low_latency = 1;
-
/* if connected, start the I/O stream */
if (port->port_usb) {
struct gserial *gser = port->port_usb;
@@ -1195,6 +1184,7 @@ void gserial_cleanup(void)
n_ports = 0;
tty_unregister_driver(gs_tty_driver);
+ put_tty_driver(gs_tty_driver);
gs_tty_driver = NULL;
pr_debug("%s: cleaned up ttyGS* support\n", __func__);
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index 544ccfd7056e..bd4027745aa7 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -207,10 +207,17 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
/* Initialize the transceiver */
if (pdata->otg) {
pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET;
- if (otg_init(pdata->otg) != 0)
- dev_err(dev, "unable to init transceiver\n");
- else if (otg_set_vbus(pdata->otg, 1) != 0)
+ ret = otg_init(pdata->otg);
+ if (ret) {
+ dev_err(dev, "unable to init transceiver, probably missing\n");
+ ret = -ENODEV;
+ goto err_add;
+ }
+ ret = otg_set_vbus(pdata->otg, 1);
+ if (ret) {
dev_err(dev, "unable to enable vbus on transceiver\n");
+ goto err_add;
+ }
}
priv->hcd = hcd;
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
index 20a0dfe0fe36..0587ad4ce5c2 100644
--- a/drivers/usb/host/isp1362-hcd.c
+++ b/drivers/usb/host/isp1362-hcd.c
@@ -2224,12 +2224,9 @@ static void remove_debug_file(struct isp1362_hcd *isp1362_hcd)
/*-------------------------------------------------------------------------*/
-static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
+static void __isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
{
int tmp = 20;
- unsigned long flags;
-
- spin_lock_irqsave(&isp1362_hcd->lock, flags);
isp1362_write_reg16(isp1362_hcd, HCSWRES, HCSWRES_MAGIC);
isp1362_write_reg32(isp1362_hcd, HCCMDSTAT, OHCI_HCR);
@@ -2240,6 +2237,14 @@ static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
}
if (!tmp)
pr_err("Software reset timeout\n");
+}
+
+static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&isp1362_hcd->lock, flags);
+ __isp1362_sw_reset(isp1362_hcd);
spin_unlock_irqrestore(&isp1362_hcd->lock, flags);
}
@@ -2418,7 +2423,7 @@ static void isp1362_hc_stop(struct usb_hcd *hcd)
if (isp1362_hcd->board && isp1362_hcd->board->reset)
isp1362_hcd->board->reset(hcd->self.controller, 1);
else
- isp1362_sw_reset(isp1362_hcd);
+ __isp1362_sw_reset(isp1362_hcd);
if (isp1362_hcd->board && isp1362_hcd->board->clock)
isp1362_hcd->board->clock(hcd->self.controller, 0);
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 1a2bb4ce638f..77be3c24a427 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -1065,7 +1065,7 @@ static void r8a66597_usb_connect(struct r8a66597 *r8a66597, int port)
else if (speed == LSMODE)
rh->port |= USB_PORT_STAT_LOW_SPEED;
- rh->port &= USB_PORT_STAT_RESET;
+ rh->port &= ~USB_PORT_STAT_RESET;
rh->port |= USB_PORT_STAT_ENABLE;
}
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 9012098add6b..94e6934edb09 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -182,8 +182,12 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
* set, but other sections talk about dealing with the chain bit set. This was
* fixed in the 0.96 specification errata, but we have to assume that all 0.95
* xHCI hardware can't handle the chain bit being cleared on a link TRB.
+ *
+ * @more_trbs_coming: Will you enqueue more TRBs before calling
+ * prepare_transfer()?
*/
-static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer)
+static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
+ bool consumer, bool more_trbs_coming)
{
u32 chain;
union xhci_trb *next;
@@ -199,15 +203,28 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
while (last_trb(xhci, ring, ring->enq_seg, next)) {
if (!consumer) {
if (ring != xhci->event_ring) {
- if (chain) {
- next->link.control |= TRB_CHAIN;
-
- /* Give this link TRB to the hardware */
- wmb();
- next->link.control ^= TRB_CYCLE;
- } else {
+ /*
+ * If the caller doesn't plan on enqueueing more
+ * TDs before ringing the doorbell, then we
+ * don't want to give the link TRB to the
+ * hardware just yet. We'll give the link TRB
+ * back in prepare_ring() just before we enqueue
+ * the TD at the top of the ring.
+ */
+ if (!chain && !more_trbs_coming)
break;
+
+ /* If we're not dealing with 0.95 hardware,
+ * carry over the chain bit of the previous TRB
+ * (which may mean the chain bit is cleared).
+ */
+ if (!xhci_link_trb_quirk(xhci)) {
+ next->link.control &= ~TRB_CHAIN;
+ next->link.control |= chain;
}
+ /* Give this link TRB to the hardware */
+ wmb();
+ next->link.control ^= TRB_CYCLE;
}
/* Toggle the cycle bit after the last ring segment. */
if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {
@@ -1707,9 +1724,12 @@ void xhci_handle_event(struct xhci_hcd *xhci)
/*
* Generic function for queueing a TRB on a ring.
* The caller must have checked to make sure there's room on the ring.
+ *
+ * @more_trbs_coming: Will you enqueue more TRBs before calling
+ * prepare_transfer()?
*/
static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
- bool consumer,
+ bool consumer, bool more_trbs_coming,
u32 field1, u32 field2, u32 field3, u32 field4)
{
struct xhci_generic_trb *trb;
@@ -1719,7 +1739,7 @@ static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
trb->field[1] = field2;
trb->field[2] = field3;
trb->field[3] = field4;
- inc_enq(xhci, ring, consumer);
+ inc_enq(xhci, ring, consumer, more_trbs_coming);
}
/*
@@ -1988,6 +2008,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
int trb_buff_len, this_sg_len, running_total;
bool first_trb;
u64 addr;
+ bool more_trbs_coming;
struct xhci_generic_trb *start_trb;
int start_cycle;
@@ -2073,7 +2094,11 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
length_field = TRB_LEN(trb_buff_len) |
remainder |
TRB_INTR_TARGET(0);
- queue_trb(xhci, ep_ring, false,
+ if (num_trbs > 1)
+ more_trbs_coming = true;
+ else
+ more_trbs_coming = false;
+ queue_trb(xhci, ep_ring, false, more_trbs_coming,
lower_32_bits(addr),
upper_32_bits(addr),
length_field,
@@ -2124,6 +2149,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
int num_trbs;
struct xhci_generic_trb *start_trb;
bool first_trb;
+ bool more_trbs_coming;
int start_cycle;
u32 field, length_field;
@@ -2212,7 +2238,11 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
length_field = TRB_LEN(trb_buff_len) |
remainder |
TRB_INTR_TARGET(0);
- queue_trb(xhci, ep_ring, false,
+ if (num_trbs > 1)
+ more_trbs_coming = true;
+ else
+ more_trbs_coming = false;
+ queue_trb(xhci, ep_ring, false, more_trbs_coming,
lower_32_bits(addr),
upper_32_bits(addr),
length_field,
@@ -2291,7 +2321,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
/* Queue setup TRB - see section 6.4.1.2.1 */
/* FIXME better way to translate setup_packet into two u32 fields? */
setup = (struct usb_ctrlrequest *) urb->setup_packet;
- queue_trb(xhci, ep_ring, false,
+ queue_trb(xhci, ep_ring, false, true,
/* FIXME endianness is probably going to bite my ass here. */
setup->bRequestType | setup->bRequest << 8 | setup->wValue << 16,
setup->wIndex | setup->wLength << 16,
@@ -2307,7 +2337,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
if (urb->transfer_buffer_length > 0) {
if (setup->bRequestType & USB_DIR_IN)
field |= TRB_DIR_IN;
- queue_trb(xhci, ep_ring, false,
+ queue_trb(xhci, ep_ring, false, true,
lower_32_bits(urb->transfer_dma),
upper_32_bits(urb->transfer_dma),
length_field,
@@ -2324,7 +2354,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
field = 0;
else
field = TRB_DIR_IN;
- queue_trb(xhci, ep_ring, false,
+ queue_trb(xhci, ep_ring, false, false,
0,
0,
TRB_INTR_TARGET(0),
@@ -2361,7 +2391,7 @@ static int queue_command(struct xhci_hcd *xhci, u32 field1, u32 field2,
"unfailable commands failed.\n");
return -ENOMEM;
}
- queue_trb(xhci, xhci->cmd_ring, false, field1, field2, field3,
+ queue_trb(xhci, xhci->cmd_ring, false, false, field1, field2, field3,
field4 | xhci->cmd_ring->cycle_state);
return 0;
}
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index fad70bc83555..3b795c56221f 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -219,8 +219,8 @@ static int musb_ulpi_write(struct otg_transceiver *otg,
return 0;
}
#else
-#define musb_ulpi_read(a, b) NULL
-#define musb_ulpi_write(a, b, c) NULL
+#define musb_ulpi_read NULL
+#define musb_ulpi_write NULL
#endif
static struct otg_io_access_ops musb_ulpi_access = {
@@ -451,10 +451,6 @@ void musb_hnp_stop(struct musb *musb)
* @param power
*/
-#define STAGE0_MASK (MUSB_INTR_RESUME | MUSB_INTR_SESSREQ \
- | MUSB_INTR_VBUSERROR | MUSB_INTR_CONNECT \
- | MUSB_INTR_RESET)
-
static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
u8 devctl, u8 power)
{
@@ -642,7 +638,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
handled = IRQ_HANDLED;
}
-
+#endif
if (int_usb & MUSB_INTR_SUSPEND) {
DBG(1, "SUSPEND (%s) devctl %02x power %02x\n",
otg_state_string(musb), devctl, power);
@@ -705,6 +701,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
}
}
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
if (int_usb & MUSB_INTR_CONNECT) {
struct usb_hcd *hcd = musb_to_hcd(musb);
void __iomem *mbase = musb->mregs;
@@ -1597,7 +1594,7 @@ irqreturn_t musb_interrupt(struct musb *musb)
/* the core can interrupt us for multiple reasons; docs have
* a generic interrupt flowchart to follow
*/
- if (musb->int_usb & STAGE0_MASK)
+ if (musb->int_usb)
retval |= musb_stage0_irq(musb, musb->int_usb,
devctl, power);
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index b22d02dea7d3..91d67794e350 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -470,7 +470,8 @@ struct musb_csr_regs {
struct musb_context_registers {
-#ifdef CONFIG_PM
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
+ defined(CONFIG_ARCH_OMAP4)
u32 otg_sysconfig, otg_forcestandby;
#endif
u8 power;
@@ -484,7 +485,8 @@ struct musb_context_registers {
struct musb_csr_regs index_regs[MUSB_C_NUM_EPS];
};
-#ifdef CONFIG_PM
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
+ defined(CONFIG_ARCH_OMAP4)
extern void musb_platform_save_context(struct musb *musb,
struct musb_context_registers *musb_context);
extern void musb_platform_restore_context(struct musb *musb,
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index 1008044a3bbc..dc66e4376d49 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -132,18 +132,9 @@ static void configure_channel(struct dma_channel *channel,
if (mode) {
csr |= 1 << MUSB_HSDMA_MODE1_SHIFT;
BUG_ON(len < packet_sz);
-
- if (packet_sz >= 64) {
- csr |= MUSB_HSDMA_BURSTMODE_INCR16
- << MUSB_HSDMA_BURSTMODE_SHIFT;
- } else if (packet_sz >= 32) {
- csr |= MUSB_HSDMA_BURSTMODE_INCR8
- << MUSB_HSDMA_BURSTMODE_SHIFT;
- } else if (packet_sz >= 16) {
- csr |= MUSB_HSDMA_BURSTMODE_INCR4
- << MUSB_HSDMA_BURSTMODE_SHIFT;
- }
}
+ csr |= MUSB_HSDMA_BURSTMODE_INCR16
+ << MUSB_HSDMA_BURSTMODE_SHIFT;
csr |= (musb_channel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT)
| (1 << MUSB_HSDMA_ENABLE_SHIFT)
diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c
index b1b346932946..d331b222ad21 100644
--- a/drivers/usb/otg/ulpi.c
+++ b/drivers/usb/otg/ulpi.c
@@ -59,12 +59,17 @@ static int ulpi_set_flags(struct otg_transceiver *otg)
static int ulpi_init(struct otg_transceiver *otg)
{
- int i, vid, pid;
-
- vid = (otg_io_read(otg, ULPI_VENDOR_ID_HIGH) << 8) |
- otg_io_read(otg, ULPI_VENDOR_ID_LOW);
- pid = (otg_io_read(otg, ULPI_PRODUCT_ID_HIGH) << 8) |
- otg_io_read(otg, ULPI_PRODUCT_ID_LOW);
+ int i, vid, pid, ret;
+ u32 ulpi_id = 0;
+
+ for (i = 0; i < 4; i++) {
+ ret = otg_io_read(otg, ULPI_PRODUCT_ID_HIGH - i);
+ if (ret < 0)
+ return ret;
+ ulpi_id = (ulpi_id << 8) | ret;
+ }
+ vid = ulpi_id & 0xffff;
+ pid = ulpi_id >> 16;
pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid);
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 79dd1ae195e5..da7e334b0407 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -653,7 +653,6 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
{ USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_PID) },
{ USB_DEVICE(EVOLUTION_VID, EVO_RCM4_PID) },
- { USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) },
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 94d86c3febcb..bbc159a1df45 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -501,13 +501,6 @@
#define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */
/*
- * Contec products (http://www.contec.com)
- * Submitted by Daniel Sangorrin
- */
-#define CONTEC_VID 0x06CE /* Vendor ID */
-#define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */
-
-/*
* Definitions for B&B Electronics products.
*/
#define BANDB_VID 0x0856 /* B&B Electronics Vendor ID */
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index 04bb759536bb..93d72eb8cafc 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -139,6 +139,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
"Could not set interface, error %d\n",
retval);
retval = -ENODEV;
+ kfree(data);
}
return retval;
}
@@ -155,6 +156,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
"Could not set interface, error %d\n",
retval);
retval = -ENODEV;
+ kfree(data);
}
return retval;
}
@@ -163,6 +165,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
default:
dev_err(&serial->dev->dev,
"unknown number of interfaces: %d\n", nintf);
+ kfree(data);
return -ENODEV;
}
diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c
index 76e7dac6f259..70b1d9d51c96 100644
--- a/drivers/video/geode/gxfb_core.c
+++ b/drivers/video/geode/gxfb_core.c
@@ -40,7 +40,7 @@ static int vram;
static int vt_switch;
/* Modes relevant to the GX (taken from modedb.c) */
-static struct fb_videomode gx_modedb[] __initdata = {
+static struct fb_videomode gx_modedb[] __devinitdata = {
/* 640x480-60 VESA */
{ NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2,
0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
@@ -110,14 +110,15 @@ static struct fb_videomode gx_modedb[] __initdata = {
#ifdef CONFIG_OLPC
#include <asm/olpc.h>
-static struct fb_videomode gx_dcon_modedb[] __initdata = {
+static struct fb_videomode gx_dcon_modedb[] __devinitdata = {
/* The only mode the DCON has is 1200x900 */
{ NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
FB_VMODE_NONINTERLACED, 0 }
};
-static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
+static void __devinit get_modedb(struct fb_videomode **modedb,
+ unsigned int *size)
{
if (olpc_has_dcon()) {
*modedb = (struct fb_videomode *) gx_dcon_modedb;
@@ -129,7 +130,8 @@ static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
}
#else
-static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
+static void __devinit get_modedb(struct fb_videomode **modedb,
+ unsigned int *size)
{
*modedb = (struct fb_videomode *) gx_modedb;
*size = ARRAY_SIZE(gx_modedb);
@@ -226,7 +228,8 @@ static int gxfb_blank(int blank_mode, struct fb_info *info)
return gx_blank_display(info, blank_mode);
}
-static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
+static int __devinit gxfb_map_video_memory(struct fb_info *info,
+ struct pci_dev *dev)
{
struct gxfb_par *par = info->par;
int ret;
@@ -290,7 +293,7 @@ static struct fb_ops gxfb_ops = {
.fb_imageblit = cfb_imageblit,
};
-static struct fb_info * __init gxfb_init_fbinfo(struct device *dev)
+static struct fb_info *__devinit gxfb_init_fbinfo(struct device *dev)
{
struct gxfb_par *par;
struct fb_info *info;
@@ -371,7 +374,8 @@ static int gxfb_resume(struct pci_dev *pdev)
}
#endif
-static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int __devinit gxfb_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
{
struct gxfb_par *par;
struct fb_info *info;
@@ -451,7 +455,7 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i
return ret;
}
-static void gxfb_remove(struct pci_dev *pdev)
+static void __devexit gxfb_remove(struct pci_dev *pdev)
{
struct fb_info *info = pci_get_drvdata(pdev);
struct gxfb_par *par = info->par;
diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/geode/lxfb_core.c
index 1a18da86d3fa..39bdbedf43b4 100644
--- a/drivers/video/geode/lxfb_core.c
+++ b/drivers/video/geode/lxfb_core.c
@@ -35,7 +35,7 @@ static int vt_switch;
* we try to make it something sane - 640x480-60 is sane
*/
-static struct fb_videomode geode_modedb[] __initdata = {
+static struct fb_videomode geode_modedb[] __devinitdata = {
/* 640x480-60 */
{ NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2,
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
@@ -219,14 +219,15 @@ static struct fb_videomode geode_modedb[] __initdata = {
#ifdef CONFIG_OLPC
#include <asm/olpc.h>
-static struct fb_videomode olpc_dcon_modedb[] __initdata = {
+static struct fb_videomode olpc_dcon_modedb[] __devinitdata = {
/* The only mode the DCON has is 1200x900 */
{ NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
FB_VMODE_NONINTERLACED, 0 }
};
-static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
+static void __devinit get_modedb(struct fb_videomode **modedb,
+ unsigned int *size)
{
if (olpc_has_dcon()) {
*modedb = (struct fb_videomode *) olpc_dcon_modedb;
@@ -238,7 +239,8 @@ static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
}
#else
-static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
+static void __devinit get_modedb(struct fb_videomode **modedb,
+ unsigned int *size)
{
*modedb = (struct fb_videomode *) geode_modedb;
*size = ARRAY_SIZE(geode_modedb);
@@ -334,7 +336,7 @@ static int lxfb_blank(int blank_mode, struct fb_info *info)
}
-static int __init lxfb_map_video_memory(struct fb_info *info,
+static int __devinit lxfb_map_video_memory(struct fb_info *info,
struct pci_dev *dev)
{
struct lxfb_par *par = info->par;
@@ -412,7 +414,7 @@ static struct fb_ops lxfb_ops = {
.fb_imageblit = cfb_imageblit,
};
-static struct fb_info * __init lxfb_init_fbinfo(struct device *dev)
+static struct fb_info * __devinit lxfb_init_fbinfo(struct device *dev)
{
struct lxfb_par *par;
struct fb_info *info;
@@ -496,7 +498,7 @@ static int lxfb_resume(struct pci_dev *pdev)
#define lxfb_resume NULL
#endif
-static int __init lxfb_probe(struct pci_dev *pdev,
+static int __devinit lxfb_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct lxfb_par *par;
@@ -588,7 +590,7 @@ err:
return ret;
}
-static void lxfb_remove(struct pci_dev *pdev)
+static void __devexit lxfb_remove(struct pci_dev *pdev)
{
struct fb_info *info = pci_get_drvdata(pdev);
struct lxfb_par *par = info->par;
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
index d4cde79ea15e..81687ed26ba9 100644
--- a/drivers/video/nuc900fb.c
+++ b/drivers/video/nuc900fb.c
@@ -596,8 +596,6 @@ static int __devinit nuc900fb_probe(struct platform_device *pdev)
goto release_regs;
}
- nuc900_driver_clksrc_div(&pdev->dev, "ext", 0x2);
-
fbi->clk = clk_get(&pdev->dev, NULL);
if (!fbi->clk || IS_ERR(fbi->clk)) {
printk(KERN_ERR "nuc900-lcd:failed to get lcd clock source\n");
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
index 43ab7d8b66b2..7767338f8b14 100644
--- a/drivers/video/omap/lcdc.c
+++ b/drivers/video/omap/lcdc.c
@@ -572,22 +572,12 @@ static enum omapfb_update_mode omap_lcdc_get_update_mode(void)
/* PM code called only in internal controller mode */
static void omap_lcdc_suspend(void)
{
- if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
- disable_controller();
- omap_stop_lcd_dma();
- }
+ omap_lcdc_set_update_mode(OMAPFB_UPDATE_DISABLED);
}
static void omap_lcdc_resume(void)
{
- if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
- setup_regs();
- load_palette();
- setup_lcd_dma();
- set_load_mode(OMAP_LCDC_LOAD_FRAME);
- enable_irqs(OMAP_LCDC_IRQ_DONE);
- enable_controller();
- }
+ omap_lcdc_set_update_mode(OMAPFB_AUTO_UPDATE);
}
static void omap_lcdc_get_caps(int plane, struct omapfb_caps *caps)
diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c
index 1162603c72e5..eada9f12efc7 100644
--- a/drivers/video/omap/rfbi.c
+++ b/drivers/video/omap/rfbi.c
@@ -26,6 +26,7 @@
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/platform_device.h>
#include "omapfb.h"
#include "dispc.h"
@@ -83,13 +84,13 @@ static inline u32 rfbi_read_reg(int idx)
static int rfbi_get_clocks(void)
{
- rfbi.dss_ick = clk_get(&dispc.fbdev->dssdev->dev, "ick");
+ rfbi.dss_ick = clk_get(&rfbi.fbdev->dssdev->dev, "ick");
if (IS_ERR(rfbi.dss_ick)) {
dev_err(rfbi.fbdev->dev, "can't get ick\n");
return PTR_ERR(rfbi.dss_ick);
}
- rfbi.dss1_fck = clk_get(&dispc.fbdev->dssdev->dev, "dss1_fck");
+ rfbi.dss1_fck = clk_get(&rfbi.fbdev->dssdev->dev, "dss1_fck");
if (IS_ERR(rfbi.dss1_fck)) {
dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n");
clk_put(rfbi.dss_ick);
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
index 95896f387927..ef8d9d558fc7 100644
--- a/drivers/virtio/virtio_pci.c
+++ b/drivers/virtio/virtio_pci.c
@@ -636,6 +636,9 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev,
INIT_LIST_HEAD(&vp_dev->virtqueues);
spin_lock_init(&vp_dev->lock);
+ /* Disable MSI/MSIX to bring device to a known good state. */
+ pci_msi_off(pci_dev);
+
/* enable the device */
err = pci_enable_device(pci_dev);
if (err)
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 1ca88908723b..afe7e21dd0ae 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -119,7 +119,7 @@ static int vring_add_indirect(struct vring_virtqueue *vq,
desc = kmalloc((out + in) * sizeof(struct vring_desc), gfp);
if (!desc)
- return vq->vring.num;
+ return -ENOMEM;
/* Transfer entries from the sg list into the indirect page */
for (i = 0; i < out; i++) {
diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c
index 1cddf92cb9a6..750bc5281d79 100644
--- a/drivers/watchdog/at32ap700x_wdt.c
+++ b/drivers/watchdog/at32ap700x_wdt.c
@@ -346,9 +346,13 @@ static int __init at32_wdt_probe(struct platform_device *pdev)
} else {
wdt->users = 0;
}
- wdt->miscdev.minor = WATCHDOG_MINOR;
- wdt->miscdev.name = "watchdog";
- wdt->miscdev.fops = &at32_wdt_fops;
+
+ wdt->miscdev.minor = WATCHDOG_MINOR;
+ wdt->miscdev.name = "watchdog";
+ wdt->miscdev.fops = &at32_wdt_fops;
+ wdt->miscdev.parent = &pdev->dev;
+
+ platform_set_drvdata(pdev, wdt);
if (at32_wdt_settimeout(timeout)) {
at32_wdt_settimeout(TIMEOUT_DEFAULT);
@@ -360,17 +364,17 @@ static int __init at32_wdt_probe(struct platform_device *pdev)
ret = misc_register(&wdt->miscdev);
if (ret) {
dev_dbg(&pdev->dev, "failed to register wdt miscdev\n");
- goto err_iounmap;
+ goto err_register;
}
- platform_set_drvdata(pdev, wdt);
- wdt->miscdev.parent = &pdev->dev;
dev_info(&pdev->dev,
"AT32AP700X WDT at 0x%p, timeout %d sec (nowayout=%d)\n",
wdt->regs, wdt->timeout, nowayout);
return 0;
+err_register:
+ platform_set_drvdata(pdev, NULL);
err_iounmap:
iounmap(wdt->regs);
err_free:
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index ea25885781bb..2ee7dac55a3c 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -330,7 +330,6 @@ static void imx2_wdt_shutdown(struct platform_device *pdev)
}
static struct platform_driver imx2_wdt_driver = {
- .probe = imx2_wdt_probe,
.remove = __exit_p(imx2_wdt_remove),
.shutdown = imx2_wdt_shutdown,
.driver = {
OpenPOWER on IntegriCloud