summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/dispatcher/dsmethod.c2
-rw-r--r--drivers/acpi/executer/exmutex.c4
-rw-r--r--drivers/ata/ahci.c8
-rw-r--r--drivers/ata/ata_piix.c9
-rw-r--r--drivers/ata/libata-acpi.c165
-rw-r--r--drivers/ata/libata-core.c2
-rw-r--r--drivers/ata/libata-pmp.c7
-rw-r--r--drivers/ata/libata-scsi.c3
-rw-r--r--drivers/ata/libata-sff.c115
-rw-r--r--drivers/ata/pata_icside.c2
-rw-r--r--drivers/ata/pata_rb532_cf.c4
-rw-r--r--drivers/ata/pata_scc.c5
-rw-r--r--drivers/ata/sata_fsl.c224
-rw-r--r--drivers/ata/sata_mv.c101
-rw-r--r--drivers/base/core.c15
-rw-r--r--drivers/block/brd.c2
-rw-r--r--drivers/block/virtio_blk.c7
-rw-r--r--drivers/char/Kconfig4
-rw-r--r--drivers/char/drm/drm_sysfs.c2
-rw-r--r--drivers/char/hw_random/Kconfig9
-rw-r--r--drivers/char/hw_random/Makefile1
-rw-r--r--drivers/char/hw_random/virtio-rng.c155
-rw-r--r--drivers/char/ip2/Makefile4
-rw-r--r--drivers/char/ip2/ip2main.c23
-rw-r--r--drivers/char/pcmcia/ipwireless/hardware.c20
-rw-r--r--drivers/char/vt.c15
-rw-r--r--drivers/cpufreq/cpufreq.c8
-rw-r--r--drivers/cpufreq/freq_table.c5
-rw-r--r--drivers/edac/mpc85xx_edac.c3
-rw-r--r--drivers/firmware/edd.c2
-rw-r--r--drivers/gpio/gpiolib.c6
-rw-r--r--drivers/gpio/mcp23s08.c2
-rw-r--r--drivers/gpio/pca953x.c1
-rw-r--r--drivers/hwmon/Kconfig14
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/hdaps.c2
-rw-r--r--drivers/hwmon/i5k_amb.c39
-rw-r--r--drivers/hwmon/ibmaem.c1111
-rw-r--r--drivers/infiniband/core/mad.c4
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_qp.c2
-rw-r--r--drivers/infiniband/hw/ehca/ehca_reqs.c6
-rw-r--r--drivers/infiniband/hw/ipath/ipath_kernel.h5
-rw-r--r--drivers/infiniband/hw/ipath/ipath_mad.c4
-rw-r--r--drivers/infiniband/hw/ipath/ipath_sdma.c16
-rw-r--r--drivers/infiniband/hw/ipath/ipath_uc.c4
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs.c3
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c15
-rw-r--r--drivers/infiniband/hw/mthca/mthca_main.c14
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c6
-rw-r--r--drivers/input/keyboard/atkbd.c2
-rw-r--r--drivers/input/keyboard/pxa27x_keypad.c38
-rw-r--r--drivers/input/misc/apanel.c1
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h7
-rw-r--r--drivers/input/serio/i8042.c33
-rw-r--r--drivers/input/tablet/gtco.c17
-rw-r--r--drivers/input/touchscreen/wm9713.c22
-rw-r--r--drivers/input/touchscreen/wm97xx-core.c25
-rw-r--r--drivers/isdn/hysdn/hycapi.c6
-rw-r--r--drivers/lguest/lguest_device.c25
-rw-r--r--drivers/md/bitmap.c17
-rw-r--r--drivers/md/md.c81
-rw-r--r--drivers/md/multipath.c3
-rw-r--r--drivers/md/raid1.c29
-rw-r--r--drivers/md/raid10.c14
-rw-r--r--drivers/md/raid5.c54
-rw-r--r--drivers/media/Makefile7
-rw-r--r--drivers/media/common/tuners/Kconfig1
-rw-r--r--drivers/media/common/tuners/mxl5005s.c4
-rw-r--r--drivers/media/common/tuners/tda18271-common.c4
-rw-r--r--drivers/media/common/tuners/tda827x.c4
-rw-r--r--drivers/media/common/tuners/tea5761.c2
-rw-r--r--drivers/media/common/tuners/tuner-i2c.h8
-rw-r--r--drivers/media/common/tuners/tuner-simple.c6
-rw-r--r--drivers/media/common/tuners/tuner-xc2028.c87
-rw-r--r--drivers/media/dvb/b2c2/flexcop-usb.c2
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c46
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c12
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig2
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_devices.c21
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-firmware.c2
-rw-r--r--drivers/media/dvb/dvb-usb/gp8psk.c10
-rw-r--r--drivers/media/dvb/dvb-usb/m920x.c7
-rw-r--r--drivers/media/dvb/frontends/dib0070.h15
-rw-r--r--drivers/media/dvb/frontends/dib7000p.h15
-rw-r--r--drivers/media/dvb/frontends/or51132.c6
-rw-r--r--drivers/media/dvb/ttpci/av7110.c9
-rw-r--r--drivers/media/dvb/ttpci/av7110_av.c34
-rw-r--r--drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c2
-rw-r--r--drivers/media/dvb/ttusb-dec/Kconfig2
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusb_dec.c25
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusbdecfe.c10
-rw-r--r--drivers/media/video/au0828/Kconfig2
-rw-r--r--drivers/media/video/au0828/au0828-dvb.c6
-rw-r--r--drivers/media/video/bt8xx/bttv-cards.c5
-rw-r--r--drivers/media/video/bt8xx/bttv-risc.c8
-rw-r--r--drivers/media/video/btcx-risc.c2
-rw-r--r--drivers/media/video/btcx-risc.h4
-rw-r--r--drivers/media/video/cx18/cx18-av-core.c81
-rw-r--r--drivers/media/video/cx18/cx18-cards.c4
-rw-r--r--drivers/media/video/cx18/cx18-controls.c6
-rw-r--r--drivers/media/video/cx18/cx18-driver.c26
-rw-r--r--drivers/media/video/cx18/cx18-driver.h9
-rw-r--r--drivers/media/video/cx18/cx18-fileops.c13
-rw-r--r--drivers/media/video/cx18/cx18-gpio.c33
-rw-r--r--drivers/media/video/cx18/cx18-ioctl.c12
-rw-r--r--drivers/media/video/cx18/cx18-irq.c12
-rw-r--r--drivers/media/video/cx18/cx18-mailbox.c8
-rw-r--r--drivers/media/video/cx18/cx18-streams.c37
-rw-r--r--drivers/media/video/cx23885/cx23885-core.c8
-rw-r--r--drivers/media/video/cx88/cx88-cards.c13
-rw-r--r--drivers/media/video/cx88/cx88-core.c8
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c8
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h10
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.c2
-rw-r--r--drivers/media/video/ivtv/ivtv-irq.c8
-rw-r--r--drivers/media/video/ivtv/ivtv-queue.c2
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.c30
-rw-r--r--drivers/media/video/ivtv/ivtv-version.h4
-rw-r--r--drivers/media/video/ivtv/ivtv-yuv.c2
-rw-r--r--drivers/media/video/ivtv/ivtv-yuv.h2
-rw-r--r--drivers/media/video/saa7134/saa7134-empress.c3
-rw-r--r--drivers/media/video/tuner-core.c60
-rw-r--r--drivers/media/video/usbvideo/quickcam_messenger.c2
-rw-r--r--drivers/media/video/zoran.h4
-rw-r--r--drivers/media/video/zoran_device.c2
-rw-r--r--drivers/media/video/zoran_driver.c10
-rw-r--r--drivers/message/fusion/mptfc.c2
-rw-r--r--drivers/message/fusion/mptsas.c2
-rw-r--r--drivers/message/fusion/mptscsih.c8
-rw-r--r--drivers/misc/fujitsu-laptop.c6
-rw-r--r--drivers/misc/kgdbts.c33
-rw-r--r--drivers/misc/thinkpad_acpi.c10
-rw-r--r--drivers/mmc/card/block.c2
-rw-r--r--drivers/mtd/devices/m25p80.c4
-rw-r--r--drivers/mtd/maps/ck804xrom.c18
-rw-r--r--drivers/mtd/maps/omap_nor.c2
-rw-r--r--drivers/mtd/nand/pxa3xx_nand.c2
-rw-r--r--drivers/mtd/onenand/generic.c2
-rw-r--r--drivers/mtd/redboot.c2
-rw-r--r--drivers/net/3c509.c2
-rw-r--r--drivers/net/Kconfig2
-rw-r--r--drivers/net/atlx/atl1.c1
-rw-r--r--drivers/net/au1000_eth.c7
-rw-r--r--drivers/net/bfin_mac.c1
-rw-r--r--drivers/net/cpmac.c234
-rw-r--r--drivers/net/cs89x0.c10
-rw-r--r--drivers/net/dm9000.c2
-rw-r--r--drivers/net/e1000e/netdev.c4
-rw-r--r--drivers/net/ehea/ehea_main.c5
-rw-r--r--drivers/net/forcedeth.c1
-rw-r--r--drivers/net/fs_enet/fs_enet-main.c2
-rw-r--r--drivers/net/hamradio/scc.c3
-rw-r--r--drivers/net/myri10ge/myri10ge.c4
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c4
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c12
-rw-r--r--drivers/net/pcnet32.c4
-rw-r--r--drivers/net/phy/Kconfig2
-rw-r--r--drivers/net/phy/phy_device.c1
-rw-r--r--drivers/net/pppol2tp.c111
-rw-r--r--drivers/net/s2io-regs.h2
-rw-r--r--drivers/net/s2io.c496
-rw-r--r--drivers/net/s2io.h22
-rw-r--r--drivers/net/sb1250-mac.c67
-rw-r--r--drivers/net/sc92031.c8
-rw-r--r--drivers/net/sfc/bitfield.h7
-rw-r--r--drivers/net/sfc/boards.c9
-rw-r--r--drivers/net/sfc/efx.c84
-rw-r--r--drivers/net/sfc/falcon.c87
-rw-r--r--drivers/net/sfc/falcon.h5
-rw-r--r--drivers/net/sfc/falcon_hwdefs.h4
-rw-r--r--drivers/net/sfc/falcon_io.h29
-rw-r--r--drivers/net/sfc/falcon_xmac.c12
-rw-r--r--drivers/net/sfc/net_driver.h44
-rw-r--r--drivers/net/sfc/rx.c48
-rw-r--r--drivers/net/sfc/selftest.c14
-rw-r--r--drivers/net/sfc/sfe4001.c14
-rw-r--r--drivers/net/sfc/tenxpress.c4
-rw-r--r--drivers/net/sfc/tx.c11
-rw-r--r--drivers/net/sfc/workarounds.h2
-rw-r--r--drivers/net/sfc/xfp_phy.c4
-rw-r--r--drivers/net/sky2.c29
-rw-r--r--drivers/net/sunhme.c4
-rw-r--r--drivers/net/tokenring/3c359.h2
-rw-r--r--drivers/net/tokenring/olympic.h2
-rw-r--r--drivers/net/tulip/tulip_core.c10
-rw-r--r--drivers/net/tulip/uli526x.c16
-rw-r--r--drivers/net/ucc_geth.c9
-rw-r--r--drivers/net/ucc_geth_ethtool.c3
-rw-r--r--drivers/net/usb/asix.c4
-rw-r--r--drivers/net/usb/rndis_host.c2
-rw-r--r--drivers/net/virtio_net.c39
-rw-r--r--drivers/net/wan/hdlc.c19
-rw-r--r--drivers/net/wan/hdlc_cisco.c82
-rw-r--r--drivers/net/wireless/airo.c2
-rw-r--r--drivers/net/wireless/b43/b43.h1
-rw-r--r--drivers/net/wireless/b43/main.c70
-rw-r--r--drivers/net/wireless/b43legacy/main.c17
-rw-r--r--drivers/net/wireless/ipw2200.c27
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-rs.c3
-rw-r--r--drivers/net/wireless/libertas/debugfs.c4
-rw-r--r--drivers/net/wireless/p54/p54usb.c1
-rw-r--r--drivers/net/wireless/rndis_wlan.c65
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h5
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c8
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c1
-rw-r--r--drivers/net/wireless/rtl8180_grf5101.c2
-rw-r--r--drivers/net/wireless/rtl8180_max2820.c5
-rw-r--r--drivers/net/wireless/rtl8180_sa2400.c2
-rw-r--r--drivers/net/xen-netfront.c6
-rw-r--r--drivers/of/of_i2c.c1
-rw-r--r--drivers/pci/hotplug/pci_hotplug_core.c7
-rw-r--r--drivers/pci/hotplug/pciehp.h11
-rw-r--r--drivers/pci/hotplug/pciehp_core.c6
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c36
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c129
-rw-r--r--drivers/pci/hotplug/rpadlpar_sysfs.c8
-rw-r--r--drivers/pci/hotplug/shpchp_core.c4
-rw-r--r--drivers/pci/pcie/aspm.c20
-rw-r--r--drivers/pcmcia/electra_cf.c1
-rw-r--r--drivers/pnp/quirks.c2
-rw-r--r--drivers/pnp/system.c2
-rw-r--r--drivers/rtc/Kconfig8
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-ds1374.c2
-rw-r--r--drivers/rtc/rtc-ppc.c69
-rw-r--r--drivers/s390/block/dasd.c28
-rw-r--r--drivers/s390/char/raw3270.c9
-rw-r--r--drivers/s390/char/sclp_config.c2
-rw-r--r--drivers/s390/char/sclp_vt220.c27
-rw-r--r--drivers/s390/char/tape.h3
-rw-r--r--drivers/s390/char/tape_block.c4
-rw-r--r--drivers/s390/char/tape_core.c16
-rw-r--r--drivers/s390/kvm/kvm_virtio.c18
-rw-r--r--drivers/scsi/3w-9xxx.c6
-rw-r--r--drivers/scsi/aha152x.c4
-rw-r--r--drivers/scsi/atp870u.c2
-rw-r--r--drivers/scsi/hptiop.c12
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c2
-rw-r--r--drivers/scsi/ibmvscsi/viosrp.h3
-rw-r--r--drivers/scsi/qla1280.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c13
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h3
-rw-r--r--drivers/scsi/qla2xxx/qla_inline.h4
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c63
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c12
-rw-r--r--drivers/scsi/qla2xxx/qla_mid.c19
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c30
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h2
-rw-r--r--drivers/scsi/scsi_sysfs.c7
-rw-r--r--drivers/serial/8250.c4
-rw-r--r--drivers/serial/8250.h5
-rw-r--r--drivers/serial/8250_pci.c7
-rw-r--r--drivers/serial/atmel_serial.c2
-rw-r--r--drivers/serial/sb1250-duart.c2
-rw-r--r--drivers/serial/serial_core.c15
-rw-r--r--drivers/serial/ucc_uart.c2
-rw-r--r--drivers/spi/spidev.c166
-rw-r--r--drivers/ssb/driver_pcicore.c4
-rw-r--r--drivers/usb/c67x00/c67x00-ll-hpi.c12
-rw-r--r--drivers/usb/class/cdc-wdm.c4
-rw-r--r--drivers/usb/core/generic.c5
-rw-r--r--drivers/usb/core/hcd.h2
-rw-r--r--drivers/usb/core/hub.c15
-rw-r--r--drivers/usb/core/quirks.c4
-rw-r--r--drivers/usb/core/sysfs.c44
-rw-r--r--drivers/usb/gadget/fsl_usb2_udc.c2
-rw-r--r--drivers/usb/host/ehci-au1xxx.c1
-rw-r--r--drivers/usb/host/ehci-fsl.c7
-rw-r--r--drivers/usb/host/ehci-hub.c16
-rw-r--r--drivers/usb/host/ehci-ixp4xx.c4
-rw-r--r--drivers/usb/host/ehci-orion.c8
-rw-r--r--drivers/usb/host/ehci-pci.c4
-rw-r--r--drivers/usb/host/ehci-ppc-of.c2
-rw-r--r--drivers/usb/host/ehci-ppc-soc.c1
-rw-r--r--drivers/usb/host/ehci-ps3.c1
-rw-r--r--drivers/usb/host/ehci-sched.c67
-rw-r--r--drivers/usb/host/ehci.h5
-rw-r--r--drivers/usb/host/isp1760-if.c4
-rw-r--r--drivers/usb/misc/Kconfig11
-rw-r--r--drivers/usb/misc/Makefile1
-rw-r--r--drivers/usb/misc/isight_firmware.c131
-rw-r--r--drivers/usb/serial/ftdi_sio.c264
-rw-r--r--drivers/usb/serial/ftdi_sio.h267
-rw-r--r--drivers/usb/serial/option.c34
-rw-r--r--drivers/usb/serial/pl2303.c1
-rw-r--r--drivers/usb/serial/pl2303.h1
-rw-r--r--drivers/usb/storage/unusual_devs.h10
-rw-r--r--drivers/video/aty/atyfb_base.c2
-rw-r--r--drivers/video/aty/radeon_base.c4
-rw-r--r--drivers/video/console/fbcon.c4
-rw-r--r--drivers/video/matrox/matroxfb_base.h2
-rw-r--r--drivers/video/modedb.c2
-rw-r--r--drivers/video/pxafb.c1
-rw-r--r--drivers/video/s3c2410fb.c130
-rw-r--r--drivers/video/s3c2410fb.h20
-rw-r--r--drivers/video/sis/sis_main.c2
-rw-r--r--drivers/video/sm501fb.c8
-rw-r--r--drivers/virtio/virtio.c8
-rw-r--r--drivers/virtio/virtio_pci.c7
-rw-r--r--drivers/virtio/virtio_ring.c8
-rw-r--r--drivers/watchdog/Kconfig13
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/bfin_wdt.c111
-rw-r--r--drivers/watchdog/booke_wdt.c88
-rw-r--r--drivers/watchdog/geodewdt.c308
-rw-r--r--drivers/watchdog/hpwdt.c27
-rw-r--r--drivers/watchdog/iTCO_wdt.c14
-rw-r--r--drivers/watchdog/w83697hf_wdt.c38
310 files changed, 5713 insertions, 2083 deletions
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index e48a3ea03117..2509809a36cf 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -565,7 +565,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
acpi_os_release_mutex(method_desc->method.
mutex->mutex.os_mutex);
- method_desc->method.mutex->mutex.thread_id = 0;
+ method_desc->method.mutex->mutex.thread_id = NULL;
}
}
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c
index c873ab40cd0e..a8bf3d713e28 100644
--- a/drivers/acpi/executer/exmutex.c
+++ b/drivers/acpi/executer/exmutex.c
@@ -326,7 +326,7 @@ acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc)
/* Clear mutex info */
- obj_desc->mutex.thread_id = 0;
+ obj_desc->mutex.thread_id = NULL;
return_ACPI_STATUS(status);
}
@@ -463,7 +463,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
/* Mark mutex unowned */
obj_desc->mutex.owner_thread = NULL;
- obj_desc->mutex.thread_id = 0;
+ obj_desc->mutex.thread_id = NULL;
/* Update Thread sync_level (Last mutex is the important one) */
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 97f83fb2ee2e..544b7d6c617c 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -502,10 +502,10 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(NVIDIA, 0x0bcd), board_ahci }, /* MCP7B */
{ PCI_VDEVICE(NVIDIA, 0x0bce), board_ahci }, /* MCP7B */
{ PCI_VDEVICE(NVIDIA, 0x0bcf), board_ahci }, /* MCP7B */
- { PCI_VDEVICE(NVIDIA, 0x0bd0), board_ahci }, /* MCP7B */
- { PCI_VDEVICE(NVIDIA, 0x0bd1), board_ahci }, /* MCP7B */
- { PCI_VDEVICE(NVIDIA, 0x0bd2), board_ahci }, /* MCP7B */
- { PCI_VDEVICE(NVIDIA, 0x0bd3), board_ahci }, /* MCP7B */
+ { PCI_VDEVICE(NVIDIA, 0x0bc4), board_ahci }, /* MCP7B */
+ { PCI_VDEVICE(NVIDIA, 0x0bc5), board_ahci }, /* MCP7B */
+ { PCI_VDEVICE(NVIDIA, 0x0bc6), board_ahci }, /* MCP7B */
+ { PCI_VDEVICE(NVIDIA, 0x0bc7), board_ahci }, /* MCP7B */
/* SiS */
{ PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index a9027b8fbdd5..81b7ae376951 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -247,10 +247,11 @@ static const struct pci_device_id piix_pci_tbl[] = {
{ 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
/* SATA Controller 2 IDE (ICH8) */
{ 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
- /* Mobile SATA Controller IDE (ICH8M) */
- { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
/* Mobile SATA Controller IDE (ICH8M), Apple */
{ 0x8086, 0x2828, 0x106b, 0x00a0, 0, 0, ich8m_apple_sata },
+ { 0x8086, 0x2828, 0x106b, 0x00a1, 0, 0, ich8m_apple_sata },
+ /* Mobile SATA Controller IDE (ICH8M) */
+ { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
/* SATA Controller IDE (ICH9) */
{ 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
/* SATA Controller IDE (ICH9) */
@@ -526,7 +527,7 @@ static struct ata_port_info piix_port_info[] = {
[ich8m_apple_sata] =
{
- .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR,
+ .flags = PIIX_SATA_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA6,
@@ -573,6 +574,8 @@ static const struct ich_laptop ich_laptop[] = {
{ 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */
{ 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */
{ 0x24CA, 0x1025, 0x0061 }, /* ICH4 on ACER Aspire 2023WLMi */
+ { 0x24CA, 0x1025, 0x003d }, /* ICH4 on ACER TM290 */
+ { 0x266F, 0x1025, 0x0066 }, /* ICH6 on ACER Aspire 1694WLMi */
{ 0x2653, 0x1043, 0x82D8 }, /* ICH6M on Asus Eee 701 */
/* end marker */
{ 0, }
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index dbf6ca781f66..3ff8b14420d9 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -118,12 +118,62 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap)
ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;
}
-static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device
- *dev, u32 event)
+static void ata_acpi_eject_device(acpi_handle handle)
+{
+ struct acpi_object_list arg_list;
+ union acpi_object arg;
+
+ arg_list.count = 1;
+ arg_list.pointer = &arg;
+ arg.type = ACPI_TYPE_INTEGER;
+ arg.integer.value = 1;
+
+ if (ACPI_FAILURE(acpi_evaluate_object(handle, "_EJ0",
+ &arg_list, NULL)))
+ printk(KERN_ERR "Failed to evaluate _EJ0!\n");
+}
+
+/* @ap and @dev are the same as ata_acpi_handle_hotplug() */
+static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev)
+{
+ if (dev)
+ dev->flags |= ATA_DFLAG_DETACH;
+ else {
+ struct ata_link *tlink;
+ struct ata_device *tdev;
+
+ ata_port_for_each_link(tlink, ap)
+ ata_link_for_each_dev(tdev, tlink)
+ tdev->flags |= ATA_DFLAG_DETACH;
+ }
+
+ ata_port_schedule_eh(ap);
+}
+
+/**
+ * ata_acpi_handle_hotplug - ACPI event handler backend
+ * @ap: ATA port ACPI event occurred
+ * @dev: ATA device ACPI event occurred (can be NULL)
+ * @event: ACPI event which occurred
+ * @is_dock_event: boolean indicating whether the event was a dock one
+ *
+ * All ACPI bay / device realted events end up in this function. If
+ * the event is port-wide @dev is NULL. If the event is specific to a
+ * device, @dev points to it.
+ *
+ * Hotplug (as opposed to unplug) notification is always handled as
+ * port-wide while unplug only kills the target device on device-wide
+ * event.
+ *
+ * LOCKING:
+ * ACPI notify handler context. May sleep.
+ */
+static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
+ u32 event, int is_dock_event)
{
char event_string[12];
char *envp[] = { event_string, NULL };
- struct ata_eh_info *ehi;
+ struct ata_eh_info *ehi = &ap->link.eh_info;
struct kobject *kobj = NULL;
int wait = 0;
unsigned long flags;
@@ -131,87 +181,100 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device
unsigned long sta;
acpi_status status;
- if (!ap)
- ap = dev->link->ap;
- ehi = &ap->link.eh_info;
-
- spin_lock_irqsave(ap->lock, flags);
-
- if (dev)
+ if (dev) {
+ if (dev->sdev)
+ kobj = &dev->sdev->sdev_gendev.kobj;
handle = dev->acpi_handle;
- else
+ } else {
+ kobj = &ap->dev->kobj;
handle = ap->acpi_handle;
+ }
status = acpi_get_handle(handle, "_EJ0", &tmphandle);
- if (ACPI_FAILURE(status)) {
- /* This device is not ejectable */
- spin_unlock_irqrestore(ap->lock, flags);
+ if (ACPI_FAILURE(status))
+ /* This device does not support hotplug */
return;
- }
- status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
- if (ACPI_FAILURE(status)) {
- printk ("Unable to determine bay status\n");
- spin_unlock_irqrestore(ap->lock, flags);
- return;
- }
+ spin_lock_irqsave(ap->lock, flags);
switch (event) {
case ACPI_NOTIFY_BUS_CHECK:
case ACPI_NOTIFY_DEVICE_CHECK:
ata_ehi_push_desc(ehi, "ACPI event");
- if (!sta) {
- /* Device has been unplugged */
- if (dev)
- dev->flags |= ATA_DFLAG_DETACH;
- else {
- struct ata_link *tlink;
- struct ata_device *tdev;
-
- ata_port_for_each_link(tlink, ap) {
- ata_link_for_each_dev(tdev, tlink) {
- tdev->flags |=
- ATA_DFLAG_DETACH;
- }
- }
- }
- ata_port_schedule_eh(ap);
- wait = 1;
- } else {
+
+ status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+ if (ACPI_FAILURE(status)) {
+ ata_port_printk(ap, KERN_ERR,
+ "acpi: failed to determine bay status (0x%x)\n",
+ status);
+ break;
+ }
+
+ if (sta) {
ata_ehi_hotplugged(ehi);
ata_port_freeze(ap);
+ } else {
+ /* The device has gone - unplug it */
+ ata_acpi_detach_device(ap, dev);
+ wait = 1;
}
+ break;
+ case ACPI_NOTIFY_EJECT_REQUEST:
+ ata_ehi_push_desc(ehi, "ACPI event");
+
+ if (!is_dock_event)
+ break;
+
+ /* undock event - immediate unplug */
+ ata_acpi_detach_device(ap, dev);
+ wait = 1;
+ break;
}
+ /* make sure kobj doesn't go away while ap->lock is released */
+ kobject_get(kobj);
+
spin_unlock_irqrestore(ap->lock, flags);
- if (wait)
+ if (wait) {
ata_port_wait_eh(ap);
+ ata_acpi_eject_device(handle);
+ }
- if (dev) {
- if (dev->sdev)
- kobj = &dev->sdev->sdev_gendev.kobj;
- } else
- kobj = &ap->dev->kobj;
-
- if (kobj) {
+ if (kobj && !is_dock_event) {
sprintf(event_string, "BAY_EVENT=%d", event);
kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
}
+
+ kobject_put(kobj);
+}
+
+static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data)
+{
+ struct ata_device *dev = data;
+
+ ata_acpi_handle_hotplug(dev->link->ap, dev, event, 1);
+}
+
+static void ata_acpi_ap_notify_dock(acpi_handle handle, u32 event, void *data)
+{
+ struct ata_port *ap = data;
+
+ ata_acpi_handle_hotplug(ap, NULL, event, 1);
}
static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data)
{
struct ata_device *dev = data;
- ata_acpi_handle_hotplug(NULL, dev, event);
+ ata_acpi_handle_hotplug(dev->link->ap, dev, event, 0);
}
static void ata_acpi_ap_notify(acpi_handle handle, u32 event, void *data)
{
struct ata_port *ap = data;
- ata_acpi_handle_hotplug(ap, NULL, event);
+ ata_acpi_handle_hotplug(ap, NULL, event, 0);
}
/**
@@ -252,7 +315,7 @@ void ata_acpi_associate(struct ata_host *host)
ata_acpi_ap_notify, ap);
/* we might be on a docking station */
register_hotplug_dock_device(ap->acpi_handle,
- ata_acpi_ap_notify, ap);
+ ata_acpi_ap_notify_dock, ap);
}
for (j = 0; j < ata_link_max_devices(&ap->link); j++) {
@@ -264,7 +327,7 @@ void ata_acpi_associate(struct ata_host *host)
ata_acpi_dev_notify, dev);
/* we might be on a docking station */
register_hotplug_dock_device(dev->acpi_handle,
- ata_acpi_dev_notify, dev);
+ ata_acpi_dev_notify_dock, dev);
}
}
}
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 3c89f205c83f..cc816ca623d3 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5403,7 +5403,7 @@ static void ata_host_stop(struct device *gendev, void *res)
*/
static void ata_finalize_port_ops(struct ata_port_operations *ops)
{
- static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+ static DEFINE_SPINLOCK(lock);
const struct ata_port_operations *cur;
void **begin = (void **)ops;
void **end = (void **)&ops->inherits;
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
index 0f9386d4a5a0..7daf4c0f6216 100644
--- a/drivers/ata/libata-pmp.c
+++ b/drivers/ata/libata-pmp.c
@@ -322,9 +322,12 @@ static void sata_pmp_quirks(struct ata_port *ap)
if (vendor == 0x1095 && devid == 0x3726) {
/* sil3726 quirks */
ata_port_for_each_link(link, ap) {
- /* class code report is unreliable */
+ /* Class code report is unreliable and SRST
+ * times out under certain configurations.
+ */
if (link->pmp < 5)
- link->flags |= ATA_LFLAG_ASSUME_ATA;
+ link->flags |= ATA_LFLAG_NO_SRST |
+ ATA_LFLAG_ASSUME_ATA;
/* port 5 is for SEMB device and it doesn't like SRST */
if (link->pmp == 5)
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index aeb6e01d82ce..2e6e1622dc6d 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1637,6 +1637,7 @@ defer:
/**
* ata_scsi_rbuf_get - Map response buffer.
+ * @cmd: SCSI command containing buffer to be mapped.
* @flags: unsigned long variable to store irq enable status
* @copy_in: copy in from user buffer
*
@@ -1954,7 +1955,7 @@ static unsigned int ata_msense_ctl_mode(u8 *buf)
/**
* ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page
- * @bufp: output buffer
+ * @buf: output buffer
*
* Generate a generic MODE SENSE r/w error recovery page.
*
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 3c2d2289f85e..215d18672a5a 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -247,7 +247,7 @@ u8 ata_sff_check_status(struct ata_port *ap)
* LOCKING:
* Inherited from caller.
*/
-u8 ata_sff_altstatus(struct ata_port *ap)
+static u8 ata_sff_altstatus(struct ata_port *ap)
{
if (ap->ops->sff_check_altstatus)
return ap->ops->sff_check_altstatus(ap);
@@ -256,6 +256,93 @@ u8 ata_sff_altstatus(struct ata_port *ap)
}
/**
+ * ata_sff_irq_status - Check if the device is busy
+ * @ap: port where the device is
+ *
+ * Determine if the port is currently busy. Uses altstatus
+ * if available in order to avoid clearing shared IRQ status
+ * when finding an IRQ source. Non ctl capable devices don't
+ * share interrupt lines fortunately for us.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static u8 ata_sff_irq_status(struct ata_port *ap)
+{
+ u8 status;
+
+ if (ap->ops->sff_check_altstatus || ap->ioaddr.altstatus_addr) {
+ status = ata_sff_altstatus(ap);
+ /* Not us: We are busy */
+ if (status & ATA_BUSY)
+ return status;
+ }
+ /* Clear INTRQ latch */
+ status = ap->ops->sff_check_status(ap);
+ return status;
+}
+
+/**
+ * ata_sff_sync - Flush writes
+ * @ap: Port to wait for.
+ *
+ * CAUTION:
+ * If we have an mmio device with no ctl and no altstatus
+ * method this will fail. No such devices are known to exist.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+
+static void ata_sff_sync(struct ata_port *ap)
+{
+ if (ap->ops->sff_check_altstatus)
+ ap->ops->sff_check_altstatus(ap);
+ else if (ap->ioaddr.altstatus_addr)
+ ioread8(ap->ioaddr.altstatus_addr);
+}
+
+/**
+ * ata_sff_pause - Flush writes and wait 400nS
+ * @ap: Port to pause for.
+ *
+ * CAUTION:
+ * If we have an mmio device with no ctl and no altstatus
+ * method this will fail. No such devices are known to exist.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+
+void ata_sff_pause(struct ata_port *ap)
+{
+ ata_sff_sync(ap);
+ ndelay(400);
+}
+
+/**
+ * ata_sff_dma_pause - Pause before commencing DMA
+ * @ap: Port to pause for.
+ *
+ * Perform I/O fencing and ensure sufficient cycle delays occur
+ * for the HDMA1:0 transition
+ */
+
+void ata_sff_dma_pause(struct ata_port *ap)
+{
+ if (ap->ops->sff_check_altstatus || ap->ioaddr.altstatus_addr) {
+ /* An altstatus read will cause the needed delay without
+ messing up the IRQ status */
+ ata_sff_altstatus(ap);
+ return;
+ }
+ /* There are no DMA controllers without ctl. BUG here to ensure
+ we never violate the HDMA1:0 transition timing and risk
+ corruption. */
+ BUG();
+}
+
+/**
* ata_sff_busy_sleep - sleep until BSY clears, or timeout
* @ap: port containing status register to be polled
* @tmout_pat: impatience timeout
@@ -742,7 +829,7 @@ static void ata_pio_sectors(struct ata_queued_cmd *qc)
} else
ata_pio_sector(qc);
- ata_sff_altstatus(qc->ap); /* flush */
+ ata_sff_sync(qc->ap); /* flush */
}
/**
@@ -763,8 +850,9 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
WARN_ON(qc->dev->cdb_len < 12);
ap->ops->sff_data_xfer(qc->dev, qc->cdb, qc->dev->cdb_len, 1);
- ata_sff_altstatus(ap); /* flush */
-
+ ata_sff_sync(ap);
+ /* FIXME: If the CDB is for DMA do we need to do the transition delay
+ or is bmdma_start guaranteed to do it ? */
switch (qc->tf.protocol) {
case ATAPI_PROT_PIO:
ap->hsm_task_state = HSM_ST;
@@ -905,7 +993,7 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)
if (unlikely(__atapi_pio_bytes(qc, bytes)))
goto err_out;
- ata_sff_altstatus(ap); /* flush */
+ ata_sff_sync(ap); /* flush */
return;
@@ -1489,14 +1577,10 @@ inline unsigned int ata_sff_host_intr(struct ata_port *ap,
goto idle_irq;
}
- /* check altstatus */
- status = ata_sff_altstatus(ap);
- if (status & ATA_BUSY)
- goto idle_irq;
- /* check main status, clearing INTRQ */
- status = ap->ops->sff_check_status(ap);
- if (unlikely(status & ATA_BUSY))
+ /* check main status, clearing INTRQ if needed */
+ status = ata_sff_irq_status(ap);
+ if (status & ATA_BUSY)
goto idle_irq;
/* ack bmdma irq events */
@@ -2030,7 +2114,7 @@ void ata_sff_error_handler(struct ata_port *ap)
ap->ops->bmdma_stop(qc);
}
- ata_sff_altstatus(ap);
+ ata_sff_sync(ap); /* FIXME: We don't need this */
ap->ops->sff_check_status(ap);
ap->ops->sff_irq_clear(ap);
@@ -2203,7 +2287,7 @@ void ata_bmdma_stop(struct ata_queued_cmd *qc)
mmio + ATA_DMA_CMD);
/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
- ata_sff_altstatus(ap); /* dummy read */
+ ata_sff_dma_pause(ap);
}
/**
@@ -2722,7 +2806,8 @@ EXPORT_SYMBOL_GPL(ata_sff_qc_prep);
EXPORT_SYMBOL_GPL(ata_sff_dumb_qc_prep);
EXPORT_SYMBOL_GPL(ata_sff_dev_select);
EXPORT_SYMBOL_GPL(ata_sff_check_status);
-EXPORT_SYMBOL_GPL(ata_sff_altstatus);
+EXPORT_SYMBOL_GPL(ata_sff_dma_pause);
+EXPORT_SYMBOL_GPL(ata_sff_pause);
EXPORT_SYMBOL_GPL(ata_sff_busy_sleep);
EXPORT_SYMBOL_GPL(ata_sff_wait_ready);
EXPORT_SYMBOL_GPL(ata_sff_tf_load);
diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
index 17138436423d..cf9e9848f8b5 100644
--- a/drivers/ata/pata_icside.c
+++ b/drivers/ata/pata_icside.c
@@ -270,7 +270,7 @@ static void pata_icside_bmdma_stop(struct ata_queued_cmd *qc)
disable_dma(state->dma);
/* see ata_bmdma_stop */
- ata_sff_altstatus(ap);
+ ata_sff_dma_pause(ap);
}
static u8 pata_icside_bmdma_status(struct ata_port *ap)
diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c
index a108d259f19d..f8b3ffc8ae9e 100644
--- a/drivers/ata/pata_rb532_cf.c
+++ b/drivers/ata/pata_rb532_cf.c
@@ -57,7 +57,9 @@ static inline void rb532_pata_finish_io(struct ata_port *ap)
struct ata_host *ah = ap->host;
struct rb532_cf_info *info = ah->private_data;
- ata_sff_altstatus(ap);
+ /* FIXME: Keep previous delay. If this is merely a fence then
+ ata_sff_sync might be sufficient. */
+ ata_sff_dma_pause(ap);
ndelay(RB500_CF_IO_DELAY);
set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
index e965b251ca24..bbf5aa345e68 100644
--- a/drivers/ata/pata_scc.c
+++ b/drivers/ata/pata_scc.c
@@ -726,7 +726,7 @@ static void scc_bmdma_stop (struct ata_queued_cmd *qc)
in_be32(bmid_base + SCC_DMA_CMD) & ~ATA_DMA_START);
/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
- ata_sff_altstatus(ap); /* dummy read */
+ ata_sff_dma_pause(ap); /* dummy read */
}
/**
@@ -747,7 +747,8 @@ static u8 scc_bmdma_status (struct ata_port *ap)
return host_stat;
/* errata A252,A308 workaround: Step4 */
- if ((ata_sff_altstatus(ap) & ATA_ERR) && (int_status & INTSTS_INTRQ))
+ if ((scc_check_altstatus(ap) & ATA_ERR)
+ && (int_status & INTSTS_INTRQ))
return (host_stat | ATA_DMA_INTR);
/* errata A308 workaround Step5 */
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 853559e32315..3924e7209a44 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -34,7 +34,7 @@ enum {
SATA_FSL_HOST_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
- ATA_FLAG_NCQ),
+ ATA_FLAG_PMP | ATA_FLAG_NCQ),
SATA_FSL_MAX_CMDS = SATA_FSL_QUEUE_DEPTH,
SATA_FSL_CMD_HDR_SIZE = 16, /* 4 DWORDS */
@@ -395,7 +395,7 @@ static void sata_fsl_qc_prep(struct ata_queued_cmd *qc)
cd = (struct command_desc *)pp->cmdentry + tag;
cd_paddr = pp->cmdentry_paddr + tag * SATA_FSL_CMD_DESC_SIZE;
- ata_tf_to_fis(&qc->tf, 0, 1, (u8 *) &cd->cfis);
+ ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, (u8 *) &cd->cfis);
VPRINTK("Dumping cfis : 0x%x, 0x%x, 0x%x\n",
cd->cfis[0], cd->cfis[1], cd->cfis[2]);
@@ -438,6 +438,8 @@ static unsigned int sata_fsl_qc_issue(struct ata_queued_cmd *qc)
ioread32(CA + hcr_base),
ioread32(CE + hcr_base), ioread32(CC + hcr_base));
+ iowrite32(qc->dev->link->pmp, CQPMP + hcr_base);
+
/* Simply queue command to the controller/device */
iowrite32(1 << tag, CQ + hcr_base);
@@ -558,11 +560,36 @@ static void sata_fsl_thaw(struct ata_port *ap)
ioread32(hcr_base + HCONTROL), ioread32(hcr_base + HSTATUS));
}
+static void sata_fsl_pmp_attach(struct ata_port *ap)
+{
+ struct sata_fsl_host_priv *host_priv = ap->host->private_data;
+ void __iomem *hcr_base = host_priv->hcr_base;
+ u32 temp;
+
+ temp = ioread32(hcr_base + HCONTROL);
+ iowrite32((temp | HCONTROL_PMP_ATTACHED), hcr_base + HCONTROL);
+}
+
+static void sata_fsl_pmp_detach(struct ata_port *ap)
+{
+ struct sata_fsl_host_priv *host_priv = ap->host->private_data;
+ void __iomem *hcr_base = host_priv->hcr_base;
+ u32 temp;
+
+ temp = ioread32(hcr_base + HCONTROL);
+ temp &= ~HCONTROL_PMP_ATTACHED;
+ iowrite32(temp, hcr_base + HCONTROL);
+
+ /* enable interrupts on the controller/port */
+ temp = ioread32(hcr_base + HCONTROL);
+ iowrite32((temp | DEFAULT_PORT_IRQ_ENABLE_MASK), hcr_base + HCONTROL);
+
+}
+
static int sata_fsl_port_start(struct ata_port *ap)
{
struct device *dev = ap->host->dev;
struct sata_fsl_port_priv *pp;
- int retval;
void *mem;
dma_addr_t mem_dma;
struct sata_fsl_host_priv *host_priv = ap->host->private_data;
@@ -688,12 +715,13 @@ static int sata_fsl_prereset(struct ata_link *link, unsigned long deadline)
}
static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
- unsigned long deadline)
+ unsigned long deadline)
{
struct ata_port *ap = link->ap;
struct sata_fsl_port_priv *pp = ap->private_data;
struct sata_fsl_host_priv *host_priv = ap->host->private_data;
void __iomem *hcr_base = host_priv->hcr_base;
+ int pmp = sata_srst_pmp(link);
u32 temp;
struct ata_taskfile tf;
u8 *cfis;
@@ -703,6 +731,9 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
DPRINTK("in xx_softreset\n");
+ if (pmp != SATA_PMP_CTRL_PORT)
+ goto issue_srst;
+
try_offline_again:
/*
* Force host controller to go off-line, aborting current operations
@@ -746,6 +777,7 @@ try_offline_again:
temp = ioread32(hcr_base + HCONTROL);
temp |= (HCONTROL_ONLINE_PHY_RST | HCONTROL_SNOOP_ENABLE);
+ temp |= HCONTROL_PMP_ATTACHED;
iowrite32(temp, hcr_base + HCONTROL);
temp = ata_wait_register(hcr_base + HSTATUS, ONLINE, 0, 1, 500);
@@ -771,7 +803,8 @@ try_offline_again:
ata_port_printk(ap, KERN_WARNING,
"No Device OR PHYRDY change,Hstatus = 0x%x\n",
ioread32(hcr_base + HSTATUS));
- goto err;
+ *class = ATA_DEV_NONE;
+ goto out;
}
/*
@@ -783,7 +816,8 @@ try_offline_again:
if ((temp & 0xFF) != 0x18) {
ata_port_printk(ap, KERN_WARNING, "No Signature Update\n");
- goto err;
+ *class = ATA_DEV_NONE;
+ goto out;
} else {
ata_port_printk(ap, KERN_INFO,
"Signature Update detected @ %d msecs\n",
@@ -798,6 +832,7 @@ try_offline_again:
* reached here, we can send a command to the target device
*/
+issue_srst:
DPRINTK("Sending SRST/device reset\n");
ata_tf_init(link->device, &tf);
@@ -808,7 +843,7 @@ try_offline_again:
SRST_CMD | CMD_DESC_SNOOP_ENABLE, 0, 0, 5);
tf.ctl |= ATA_SRST; /* setup SRST bit in taskfile control reg */
- ata_tf_to_fis(&tf, 0, 0, cfis);
+ ata_tf_to_fis(&tf, pmp, 0, cfis);
DPRINTK("Dumping cfis : 0x%x, 0x%x, 0x%x, 0x%x\n",
cfis[0], cfis[1], cfis[2], cfis[3]);
@@ -854,8 +889,10 @@ try_offline_again:
sata_fsl_setup_cmd_hdr_entry(pp, 0, CMD_DESC_SNOOP_ENABLE, 0, 0, 5);
tf.ctl &= ~ATA_SRST; /* 2nd H2D Ctl. register FIS */
- ata_tf_to_fis(&tf, 0, 0, cfis);
+ ata_tf_to_fis(&tf, pmp, 0, cfis);
+ if (pmp != SATA_PMP_CTRL_PORT)
+ iowrite32(pmp, CQPMP + hcr_base);
iowrite32(1, CQ + hcr_base);
msleep(150); /* ?? */
@@ -886,12 +923,21 @@ try_offline_again:
VPRINTK("cereg = 0x%x\n", ioread32(hcr_base + CE));
}
+out:
return 0;
err:
return -EIO;
}
+static void sata_fsl_error_handler(struct ata_port *ap)
+{
+
+ DPRINTK("in xx_error_handler\n");
+ sata_pmp_error_handler(ap);
+
+}
+
static void sata_fsl_post_internal_cmd(struct ata_queued_cmd *qc)
{
if (qc->flags & ATA_QCFLAG_FAILED)
@@ -905,18 +951,21 @@ static void sata_fsl_post_internal_cmd(struct ata_queued_cmd *qc)
static void sata_fsl_error_intr(struct ata_port *ap)
{
- struct ata_link *link = &ap->link;
- struct ata_eh_info *ehi = &link->eh_info;
struct sata_fsl_host_priv *host_priv = ap->host->private_data;
void __iomem *hcr_base = host_priv->hcr_base;
- u32 hstatus, dereg, cereg = 0, SError = 0;
+ u32 hstatus, dereg=0, cereg = 0, SError = 0;
unsigned int err_mask = 0, action = 0;
- struct ata_queued_cmd *qc;
- int freeze = 0;
+ int freeze = 0, abort=0;
+ struct ata_link *link = NULL;
+ struct ata_queued_cmd *qc = NULL;
+ struct ata_eh_info *ehi;
hstatus = ioread32(hcr_base + HSTATUS);
cereg = ioread32(hcr_base + CE);
+ /* first, analyze and record host port events */
+ link = &ap->link;
+ ehi = &link->eh_info;
ata_ehi_clear_desc(ehi);
/*
@@ -926,42 +975,28 @@ static void sata_fsl_error_intr(struct ata_port *ap)
sata_fsl_scr_read(ap, SCR_ERROR, &SError);
if (unlikely(SError & 0xFFFF0000)) {
sata_fsl_scr_write(ap, SCR_ERROR, SError);
- err_mask |= AC_ERR_ATA_BUS;
}
DPRINTK("error_intr,hStat=0x%x,CE=0x%x,DE =0x%x,SErr=0x%x\n",
hstatus, cereg, ioread32(hcr_base + DE), SError);
- /* handle single device errors */
- if (cereg) {
- /*
- * clear the command error, also clears queue to the device
- * in error, and we can (re)issue commands to this device.
- * When a device is in error all commands queued into the
- * host controller and at the device are considered aborted
- * and the queue for that device is stopped. Now, after
- * clearing the device error, we can issue commands to the
- * device to interrogate it to find the source of the error.
- */
- dereg = ioread32(hcr_base + DE);
- iowrite32(dereg, hcr_base + DE);
- iowrite32(cereg, hcr_base + CE);
+ /* handle fatal errors */
+ if (hstatus & FATAL_ERROR_DECODE) {
+ ehi->err_mask |= AC_ERR_ATA_BUS;
+ ehi->action |= ATA_EH_SOFTRESET;
- DPRINTK("single device error, CE=0x%x, DE=0x%x\n",
- ioread32(hcr_base + CE), ioread32(hcr_base + DE));
/*
- * We should consider this as non fatal error, and TF must
- * be updated as done below.
+ * Ignore serror in case of fatal errors as we always want
+ * to do a soft-reset of the FSL SATA controller. Analyzing
+ * serror may cause libata to schedule a hard-reset action,
+ * and hard-reset currently does not do controller
+ * offline/online, causing command timeouts and leads to an
+ * un-recoverable state, hence make libATA ignore
+ * autopsy in case of fatal errors.
*/
- err_mask |= AC_ERR_DEV;
- }
+ ehi->flags |= ATA_EHI_NO_AUTOPSY;
- /* handle fatal errors */
- if (hstatus & FATAL_ERROR_DECODE) {
- err_mask |= AC_ERR_ATA_BUS;
- action |= ATA_EH_RESET;
- /* how will fatal error interrupts be completed ?? */
freeze = 1;
}
@@ -971,30 +1006,83 @@ static void sata_fsl_error_intr(struct ata_port *ap)
/* Setup a soft-reset EH action */
ata_ehi_hotplugged(ehi);
+ ata_ehi_push_desc(ehi, "%s", "PHY RDY changed");
freeze = 1;
}
- /* record error info */
- qc = ata_qc_from_tag(ap, link->active_tag);
+ /* handle single device errors */
+ if (cereg) {
+ /*
+ * clear the command error, also clears queue to the device
+ * in error, and we can (re)issue commands to this device.
+ * When a device is in error all commands queued into the
+ * host controller and at the device are considered aborted
+ * and the queue for that device is stopped. Now, after
+ * clearing the device error, we can issue commands to the
+ * device to interrogate it to find the source of the error.
+ */
+ abort = 1;
+
+ DPRINTK("single device error, CE=0x%x, DE=0x%x\n",
+ ioread32(hcr_base + CE), ioread32(hcr_base + DE));
- if (qc)
+ /* find out the offending link and qc */
+ if (ap->nr_pmp_links) {
+ dereg = ioread32(hcr_base + DE);
+ iowrite32(dereg, hcr_base + DE);
+ iowrite32(cereg, hcr_base + CE);
+
+ if (dereg < ap->nr_pmp_links) {
+ link = &ap->pmp_link[dereg];
+ ehi = &link->eh_info;
+ qc = ata_qc_from_tag(ap, link->active_tag);
+ /*
+ * We should consider this as non fatal error,
+ * and TF must be updated as done below.
+ */
+
+ err_mask |= AC_ERR_DEV;
+
+ } else {
+ err_mask |= AC_ERR_HSM;
+ action |= ATA_EH_HARDRESET;
+ freeze = 1;
+ }
+ } else {
+ dereg = ioread32(hcr_base + DE);
+ iowrite32(dereg, hcr_base + DE);
+ iowrite32(cereg, hcr_base + CE);
+
+ qc = ata_qc_from_tag(ap, link->active_tag);
+ /*
+ * We should consider this as non fatal error,
+ * and TF must be updated as done below.
+ */
+ err_mask |= AC_ERR_DEV;
+ }
+ }
+
+ /* record error info */
+ if (qc) {
qc->err_mask |= err_mask;
- else
+ } else
ehi->err_mask |= err_mask;
ehi->action |= action;
- ehi->serror |= SError;
/* freeze or abort */
if (freeze)
ata_port_freeze(ap);
- else
- ata_port_abort(ap);
+ else if (abort) {
+ if (qc)
+ ata_link_abort(qc->dev->link);
+ else
+ ata_port_abort(ap);
+ }
}
static void sata_fsl_host_intr(struct ata_port *ap)
{
- struct ata_link *link = &ap->link;
struct sata_fsl_host_priv *host_priv = ap->host->private_data;
void __iomem *hcr_base = host_priv->hcr_base;
u32 hstatus, qc_active = 0;
@@ -1017,10 +1105,19 @@ static void sata_fsl_host_intr(struct ata_port *ap)
return;
}
- if (link->sactive) { /* only true for NCQ commands */
+ /* Read command completed register */
+ qc_active = ioread32(hcr_base + CC);
+
+ VPRINTK("Status of all queues :\n");
+ VPRINTK("qc_active/CC = 0x%x, CA = 0x%x, CE=0x%x,CQ=0x%x,apqa=0x%x\n",
+ qc_active,
+ ioread32(hcr_base + CA),
+ ioread32(hcr_base + CE),
+ ioread32(hcr_base + CQ),
+ ap->qc_active);
+
+ if (qc_active & ap->qc_active) {
int i;
- /* Read command completed register */
- qc_active = ioread32(hcr_base + CC);
/* clear CC bit, this will also complete the interrupt */
iowrite32(qc_active, hcr_base + CC);
@@ -1032,8 +1129,9 @@ static void sata_fsl_host_intr(struct ata_port *ap)
for (i = 0; i < SATA_FSL_QUEUE_DEPTH; i++) {
if (qc_active & (1 << i)) {
qc = ata_qc_from_tag(ap, i);
- if (qc)
+ if (qc) {
ata_qc_complete(qc);
+ }
DPRINTK
("completing ncq cmd,tag=%d,CC=0x%x,CA=0x%x\n",
i, ioread32(hcr_base + CC),
@@ -1042,19 +1140,21 @@ static void sata_fsl_host_intr(struct ata_port *ap)
}
return;
- } else if (ap->qc_active) {
+ } else if ((ap->qc_active & (1 << ATA_TAG_INTERNAL))) {
iowrite32(1, hcr_base + CC);
- qc = ata_qc_from_tag(ap, link->active_tag);
+ qc = ata_qc_from_tag(ap, ATA_TAG_INTERNAL);
- DPRINTK("completing non-ncq cmd, tag=%d,CC=0x%x\n",
- link->active_tag, ioread32(hcr_base + CC));
+ DPRINTK("completing non-ncq cmd, CC=0x%x\n",
+ ioread32(hcr_base + CC));
- if (qc)
+ if (qc) {
ata_qc_complete(qc);
+ }
} else {
/* Spurious Interrupt!! */
DPRINTK("spurious interrupt!!, CC = 0x%x\n",
ioread32(hcr_base + CC));
+ iowrite32(qc_active, hcr_base + CC);
return;
}
}
@@ -1130,9 +1230,6 @@ static int sata_fsl_init_controller(struct ata_host *host)
iowrite32(0x00000FFFF, hcr_base + CE);
iowrite32(0x00000FFFF, hcr_base + DE);
- /* initially assuming no Port multiplier, set CQPMP to 0 */
- iowrite32(0x0, hcr_base + CQPMP);
-
/*
* host controller will be brought on-line, during xx_port_start()
* callback, that should also initiate the OOB, COMINIT sequence
@@ -1154,8 +1251,8 @@ static struct scsi_host_template sata_fsl_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
};
-static const struct ata_port_operations sata_fsl_ops = {
- .inherits = &sata_port_ops,
+static struct ata_port_operations sata_fsl_ops = {
+ .inherits = &sata_pmp_port_ops,
.qc_prep = sata_fsl_qc_prep,
.qc_issue = sata_fsl_qc_issue,
@@ -1168,10 +1265,15 @@ static const struct ata_port_operations sata_fsl_ops = {
.thaw = sata_fsl_thaw,
.prereset = sata_fsl_prereset,
.softreset = sata_fsl_softreset,
+ .pmp_softreset = sata_fsl_softreset,
+ .error_handler = sata_fsl_error_handler,
.post_internal_cmd = sata_fsl_post_internal_cmd,
.port_start = sata_fsl_port_start,
.port_stop = sata_fsl_port_stop,
+
+ .pmp_attach = sata_fsl_pmp_attach,
+ .pmp_detach = sata_fsl_pmp_detach,
};
static const struct ata_port_info sata_fsl_port_info[] = {
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index fb81f0c7a8c2..60391e9a84db 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -72,7 +72,7 @@
#include <linux/libata.h>
#define DRV_NAME "sata_mv"
-#define DRV_VERSION "1.21"
+#define DRV_VERSION "1.24"
enum {
/* BAR's are enumerated in terms of pci_resource_start() terms */
@@ -122,8 +122,6 @@ enum {
/* Host Flags */
MV_FLAG_DUAL_HC = (1 << 30), /* two SATA Host Controllers */
MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */
- /* SoC integrated controllers, no PCI interface */
- MV_FLAG_SOC = (1 << 28),
MV_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
@@ -226,6 +224,11 @@ enum {
PHY_MODE3 = 0x310,
PHY_MODE4 = 0x314,
+ PHY_MODE4_CFG_MASK = 0x00000003, /* phy internal config field */
+ PHY_MODE4_CFG_VALUE = 0x00000001, /* phy internal config field */
+ PHY_MODE4_RSVD_ZEROS = 0x5de3fffa, /* Gen2e always write zeros */
+ PHY_MODE4_RSVD_ONES = 0x00000005, /* Gen2e always write ones */
+
PHY_MODE2 = 0x330,
SATA_IFCTL_OFS = 0x344,
SATA_TESTCTL_OFS = 0x348,
@@ -356,12 +359,12 @@ enum {
MV_HP_ERRATA_50XXB2 = (1 << 2),
MV_HP_ERRATA_60X1B2 = (1 << 3),
MV_HP_ERRATA_60X1C0 = (1 << 4),
- MV_HP_ERRATA_XX42A0 = (1 << 5),
MV_HP_GEN_I = (1 << 6), /* Generation I: 50xx */
MV_HP_GEN_II = (1 << 7), /* Generation II: 60xx */
MV_HP_GEN_IIE = (1 << 8), /* Generation IIE: 6042/7042 */
MV_HP_PCIE = (1 << 9), /* PCIe bus/regs: 7042 */
MV_HP_CUT_THROUGH = (1 << 10), /* can use EDMA cut-through */
+ MV_HP_FLAG_SOC = (1 << 11), /* SystemOnChip, no PCI */
/* Port private flags (pp_flags) */
MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */
@@ -374,7 +377,7 @@ enum {
#define IS_GEN_II(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_II)
#define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
#define IS_PCIE(hpriv) ((hpriv)->hp_flags & MV_HP_PCIE)
-#define HAS_PCI(host) (!((host)->ports[0]->flags & MV_FLAG_SOC))
+#define IS_SOC(hpriv) ((hpriv)->hp_flags & MV_HP_FLAG_SOC)
#define WINDOW_CTRL(i) (0x20030 + ((i) << 4))
#define WINDOW_BASE(i) (0x20034 + ((i) << 4))
@@ -652,7 +655,7 @@ static const struct ata_port_info mv_port_info[] = {
.port_ops = &mv_iie_ops,
},
{ /* chip_soc */
- .flags = MV_GENIIE_FLAGS | MV_FLAG_SOC,
+ .flags = MV_GENIIE_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA6,
.port_ops = &mv_iie_ops,
@@ -812,12 +815,7 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio,
writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | index,
port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
-
- if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
- writelfl((pp->crqb_dma & 0xffffffff) | index,
- port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
- else
- writelfl(index, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
+ writelfl(index, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
/*
* initialize response queue
@@ -827,13 +825,7 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio,
WARN_ON(pp->crpb_dma & 0xff);
writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
-
- if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
- writelfl((pp->crpb_dma & 0xffffffff) | index,
- port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
- else
- writelfl(index, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
-
+ writelfl(index, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) | index,
port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
}
@@ -1254,7 +1246,7 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq)
cfg |= (1 << 23); /* do not mask PM field in rx'd FIS */
cfg |= (1 << 22); /* enab 4-entry host queue cache */
- if (HAS_PCI(ap->host))
+ if (!IS_SOC(hpriv))
cfg |= (1 << 18); /* enab early completion */
if (hpriv->hp_flags & MV_HP_CUT_THROUGH)
cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */
@@ -2225,7 +2217,7 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
* a bogus register value which can indicate HW removal or PCI fault.
*/
if (pending_irqs && main_irq_cause != 0xffffffffU) {
- if (unlikely((pending_irqs & PCI_ERR) && HAS_PCI(host)))
+ if (unlikely((pending_irqs & PCI_ERR) && !IS_SOC(hpriv)))
handled = mv_pci_error(host, hpriv->base);
else
handled = mv_host_intr(host, pending_irqs);
@@ -2547,7 +2539,7 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
int fix_phy_mode4 =
hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
- u32 m2, tmp;
+ u32 m2, m3;
if (fix_phy_mode2) {
m2 = readl(port_mmio + PHY_MODE2);
@@ -2564,28 +2556,36 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
udelay(200);
}
- /* who knows what this magic does */
- tmp = readl(port_mmio + PHY_MODE3);
- tmp &= ~0x7F800000;
- tmp |= 0x2A800000;
- writel(tmp, port_mmio + PHY_MODE3);
-
- if (fix_phy_mode4) {
- u32 m4;
-
- m4 = readl(port_mmio + PHY_MODE4);
-
- if (hp_flags & MV_HP_ERRATA_60X1B2)
- tmp = readl(port_mmio + PHY_MODE3);
+ /*
+ * Gen-II/IIe PHY_MODE3 errata RM#2:
+ * Achieves better receiver noise performance than the h/w default:
+ */
+ m3 = readl(port_mmio + PHY_MODE3);
+ m3 = (m3 & 0x1f) | (0x5555601 << 5);
- /* workaround for errata FEr SATA#10 (part 1) */
- m4 = (m4 & ~(1 << 1)) | (1 << 0);
+ /* Guideline 88F5182 (GL# SATA-S11) */
+ if (IS_SOC(hpriv))
+ m3 &= ~0x1c;
+ if (fix_phy_mode4) {
+ u32 m4 = readl(port_mmio + PHY_MODE4);
+ /*
+ * Enforce reserved-bit restrictions on GenIIe devices only.
+ * For earlier chipsets, force only the internal config field
+ * (workaround for errata FEr SATA#10 part 1).
+ */
+ if (IS_GEN_IIE(hpriv))
+ m4 = (m4 & ~PHY_MODE4_RSVD_ZEROS) | PHY_MODE4_RSVD_ONES;
+ else
+ m4 = (m4 & ~PHY_MODE4_CFG_MASK) | PHY_MODE4_CFG_VALUE;
writel(m4, port_mmio + PHY_MODE4);
-
- if (hp_flags & MV_HP_ERRATA_60X1B2)
- writel(tmp, port_mmio + PHY_MODE3);
}
+ /*
+ * Workaround for 60x1-B2 errata SATA#13:
+ * Any write to PHY_MODE4 (above) may corrupt PHY_MODE3,
+ * so we must always rewrite PHY_MODE3 after PHY_MODE4.
+ */
+ writel(m3, port_mmio + PHY_MODE3);
/* Revert values of pre-emphasis and signal amps to the saved ones */
m2 = readl(port_mmio + PHY_MODE2);
@@ -2876,7 +2876,7 @@ static unsigned int mv_in_pcix_mode(struct ata_host *host)
void __iomem *mmio = hpriv->base;
u32 reg;
- if (!HAS_PCI(host) || !IS_PCIE(hpriv))
+ if (IS_SOC(hpriv) || !IS_PCIE(hpriv))
return 0; /* not PCI-X capable */
reg = readl(mmio + MV_PCI_MODE_OFS);
if ((reg & MV_PCI_MODE_MASK) == 0)
@@ -3003,10 +3003,7 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
hp_flags |= MV_HP_CUT_THROUGH;
switch (pdev->revision) {
- case 0x0:
- hp_flags |= MV_HP_ERRATA_XX42A0;
- break;
- case 0x1:
+ case 0x2: /* Rev.B0: the first/only public release */
hp_flags |= MV_HP_ERRATA_60X1C0;
break;
default:
@@ -3018,7 +3015,7 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
break;
case chip_soc:
hpriv->ops = &mv_soc_ops;
- hp_flags |= MV_HP_ERRATA_60X1C0;
+ hp_flags |= MV_HP_FLAG_SOC | MV_HP_ERRATA_60X1C0;
break;
default:
@@ -3062,12 +3059,12 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
if (rc)
goto done;
- if (HAS_PCI(host)) {
- hpriv->main_irq_cause_addr = mmio + PCI_HC_MAIN_IRQ_CAUSE_OFS;
- hpriv->main_irq_mask_addr = mmio + PCI_HC_MAIN_IRQ_MASK_OFS;
- } else {
+ if (IS_SOC(hpriv)) {
hpriv->main_irq_cause_addr = mmio + SOC_HC_MAIN_IRQ_CAUSE_OFS;
hpriv->main_irq_mask_addr = mmio + SOC_HC_MAIN_IRQ_MASK_OFS;
+ } else {
+ hpriv->main_irq_cause_addr = mmio + PCI_HC_MAIN_IRQ_CAUSE_OFS;
+ hpriv->main_irq_mask_addr = mmio + PCI_HC_MAIN_IRQ_MASK_OFS;
}
/* global interrupt mask: 0 == mask everything */
@@ -3093,7 +3090,7 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
mv_port_init(&ap->ioaddr, port_mmio);
#ifdef CONFIG_PCI
- if (HAS_PCI(host)) {
+ if (!IS_SOC(hpriv)) {
unsigned int offset = port_mmio - mmio;
ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio");
ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port");
@@ -3113,7 +3110,7 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
}
- if (HAS_PCI(host)) {
+ if (!IS_SOC(hpriv)) {
/* Clear any currently outstanding host interrupt conditions */
writelfl(0, mmio + hpriv->irq_cause_ofs);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 72eccae4904b..422cfcad486d 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -760,6 +760,21 @@ static void device_remove_class_symlinks(struct device *dev)
}
/**
+ * dev_set_name - set a device name
+ * @dev: device
+ */
+int dev_set_name(struct device *dev, const char *fmt, ...)
+{
+ va_list vargs;
+
+ va_start(vargs, fmt);
+ vsnprintf(dev->bus_id, sizeof(dev->bus_id), fmt, vargs);
+ va_end(vargs);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dev_set_name);
+
+/**
* device_add - add device to device hierarchy.
* @dev: device.
*
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index a196ef7f147f..24b97b0bef99 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -397,6 +397,7 @@ module_param(max_part, int, 0);
MODULE_PARM_DESC(max_part, "Maximum number of partitions per RAM disk");
MODULE_LICENSE("GPL");
MODULE_ALIAS_BLOCKDEV_MAJOR(RAMDISK_MAJOR);
+MODULE_ALIAS("rd");
#ifndef MODULE
/* Legacy boot options - nonmodular */
@@ -447,6 +448,7 @@ static struct brd_device *brd_alloc(int i)
disk->fops = &brd_fops;
disk->private_data = brd;
disk->queue = brd->brd_queue;
+ disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;
sprintf(disk->disk_name, "ram%d", i);
set_capacity(disk, rd_size * 2);
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 84e064ffee52..dd7ea203f940 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -260,6 +260,10 @@ static int virtblk_probe(struct virtio_device *vdev)
if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER))
blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL);
+ /* If disk is read-only in the host, the guest should obey */
+ if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO))
+ set_disk_ro(vblk->disk, 1);
+
/* Host must always specify the capacity. */
vdev->config->get(vdev, offsetof(struct virtio_blk_config, capacity),
&cap, sizeof(cap));
@@ -311,6 +315,7 @@ static void virtblk_remove(struct virtio_device *vdev)
/* Stop all the virtqueues. */
vdev->config->reset(vdev);
+ del_gendisk(vblk->disk);
blk_cleanup_queue(vblk->disk->queue);
put_disk(vblk->disk);
mempool_destroy(vblk->pool);
@@ -325,7 +330,7 @@ static struct virtio_device_id id_table[] = {
static unsigned int features[] = {
VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX,
- VIRTIO_BLK_F_GEOMETRY,
+ VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO,
};
static struct virtio_driver virtio_blk = {
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 595a925c62a9..d307bf26af58 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -118,8 +118,8 @@ config COMPUTONE
order to become a dial-in server. If you have a card like that, say
Y here and read <file:Documentation/computone.txt>.
- To compile this driver as modules, choose M here: the
- modules will be called ip2 and ip2main.
+ To compile this driver as module, choose M here: the
+ module will be called ip2.
config ROCKETPORT
tristate "Comtrol RocketPort support"
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
index 9a32169e88fb..af211a0ef179 100644
--- a/drivers/char/drm/drm_sysfs.c
+++ b/drivers/char/drm/drm_sysfs.c
@@ -34,8 +34,6 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
struct drm_minor *drm_minor = to_drm_minor(dev);
struct drm_device *drm_dev = drm_minor->dev;
- printk(KERN_ERR "%s\n", __func__);
-
if (drm_dev->driver->suspend)
return drm_dev->driver->suspend(drm_dev, state);
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 8d6c2089d2a8..efd0b4db7c8e 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -112,3 +112,12 @@ config HW_RANDOM_PASEMI
If unsure, say Y.
+config HW_RANDOM_VIRTIO
+ tristate "VirtIO Random Number Generator support"
+ depends on HW_RANDOM && VIRTIO
+ ---help---
+ This driver provides kernel-side support for the virtual Random Number
+ Generator hardware.
+
+ To compile this driver as a module, choose M here: the
+ module will be called virtio-rng. If unsure, say N.
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index c8b7300e2fb1..b4940ddbb35f 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o
obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o
obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o
obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o
+obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
new file mode 100644
index 000000000000..d0e563e4fc39
--- /dev/null
+++ b/drivers/char/hw_random/virtio-rng.c
@@ -0,0 +1,155 @@
+/*
+ * Randomness driver for virtio
+ * Copyright (C) 2007, 2008 Rusty Russell IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/err.h>
+#include <linux/hw_random.h>
+#include <linux/scatterlist.h>
+#include <linux/spinlock.h>
+#include <linux/virtio.h>
+#include <linux/virtio_rng.h>
+
+/* The host will fill any buffer we give it with sweet, sweet randomness. We
+ * give it 64 bytes at a time, and the hwrng framework takes it 4 bytes at a
+ * time. */
+#define RANDOM_DATA_SIZE 64
+
+static struct virtqueue *vq;
+static u32 *random_data;
+static unsigned int data_left;
+static DECLARE_COMPLETION(have_data);
+
+static void random_recv_done(struct virtqueue *vq)
+{
+ int len;
+
+ /* We never get spurious callbacks. */
+ if (!vq->vq_ops->get_buf(vq, &len))
+ BUG();
+
+ data_left = len / sizeof(random_data[0]);
+ complete(&have_data);
+}
+
+static void register_buffer(void)
+{
+ struct scatterlist sg;
+
+ sg_init_one(&sg, random_data, RANDOM_DATA_SIZE);
+ /* There should always be room for one buffer. */
+ if (vq->vq_ops->add_buf(vq, &sg, 0, 1, random_data) != 0)
+ BUG();
+ vq->vq_ops->kick(vq);
+}
+
+/* At least we don't udelay() in a loop like some other drivers. */
+static int virtio_data_present(struct hwrng *rng, int wait)
+{
+ if (data_left)
+ return 1;
+
+ if (!wait)
+ return 0;
+
+ wait_for_completion(&have_data);
+ return 1;
+}
+
+/* virtio_data_present() must have succeeded before this is called. */
+static int virtio_data_read(struct hwrng *rng, u32 *data)
+{
+ BUG_ON(!data_left);
+
+ *data = random_data[--data_left];
+
+ if (!data_left) {
+ init_completion(&have_data);
+ register_buffer();
+ }
+ return sizeof(*data);
+}
+
+static struct hwrng virtio_hwrng = {
+ .name = "virtio",
+ .data_present = virtio_data_present,
+ .data_read = virtio_data_read,
+};
+
+static int virtrng_probe(struct virtio_device *vdev)
+{
+ int err;
+
+ /* We expect a single virtqueue. */
+ vq = vdev->config->find_vq(vdev, 0, random_recv_done);
+ if (IS_ERR(vq))
+ return PTR_ERR(vq);
+
+ err = hwrng_register(&virtio_hwrng);
+ if (err) {
+ vdev->config->del_vq(vq);
+ return err;
+ }
+
+ register_buffer();
+ return 0;
+}
+
+static void virtrng_remove(struct virtio_device *vdev)
+{
+ vdev->config->reset(vdev);
+ hwrng_unregister(&virtio_hwrng);
+ vdev->config->del_vq(vq);
+}
+
+static struct virtio_device_id id_table[] = {
+ { VIRTIO_ID_RNG, VIRTIO_DEV_ANY_ID },
+ { 0 },
+};
+
+static struct virtio_driver virtio_rng = {
+ .driver.name = KBUILD_MODNAME,
+ .driver.owner = THIS_MODULE,
+ .id_table = id_table,
+ .probe = virtrng_probe,
+ .remove = __devexit_p(virtrng_remove),
+};
+
+static int __init init(void)
+{
+ int err;
+
+ random_data = kmalloc(RANDOM_DATA_SIZE, GFP_KERNEL);
+ if (!random_data)
+ return -ENOMEM;
+
+ err = register_virtio_driver(&virtio_rng);
+ if (err)
+ kfree(random_data);
+ return err;
+}
+
+static void __exit fini(void)
+{
+ kfree(random_data);
+ unregister_virtio_driver(&virtio_rng);
+}
+module_init(init);
+module_exit(fini);
+
+MODULE_DEVICE_TABLE(virtio, id_table);
+MODULE_DESCRIPTION("Virtio random number driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/ip2/Makefile b/drivers/char/ip2/Makefile
index 6bfe2543ddc2..939618f62fe1 100644
--- a/drivers/char/ip2/Makefile
+++ b/drivers/char/ip2/Makefile
@@ -2,7 +2,7 @@
# Makefile for the Computone IntelliPort Plus Driver
#
-obj-$(CONFIG_COMPUTONE) += ip2.o ip2main.o
+obj-$(CONFIG_COMPUTONE) += ip2.o
-ip2-objs := ip2base.o
+ip2-objs := ip2base.o ip2main.o
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index 70957acaa960..c12cf8fc4be0 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -346,27 +346,6 @@ have_requested_irq( char irq )
}
/******************************************************************************/
-/* Function: init_module() */
-/* Parameters: None */
-/* Returns: Success (0) */
-/* */
-/* Description: */
-/* This is a required entry point for an installable module. It simply calls */
-/* the driver initialisation function and returns what it returns. */
-/******************************************************************************/
-#ifdef MODULE
-static int __init
-ip2_init_module(void)
-{
-#ifdef IP2DEBUG_INIT
- printk (KERN_DEBUG "Loading module ...\n" );
-#endif
- return 0;
-}
-module_init(ip2_init_module);
-#endif /* MODULE */
-
-/******************************************************************************/
/* Function: cleanup_module() */
/* Parameters: None */
/* Returns: Nothing */
@@ -779,8 +758,6 @@ out:
return err;
}
-EXPORT_SYMBOL(ip2_loadmain);
-
/******************************************************************************/
/* Function: ip2_init_board() */
/* Parameters: Index of board in configuration structure */
diff --git a/drivers/char/pcmcia/ipwireless/hardware.c b/drivers/char/pcmcia/ipwireless/hardware.c
index fa9d3c945f31..ba6340ae98af 100644
--- a/drivers/char/pcmcia/ipwireless/hardware.c
+++ b/drivers/char/pcmcia/ipwireless/hardware.c
@@ -251,10 +251,11 @@ struct ipw_hardware {
int init_loops;
struct timer_list setup_timer;
+ /* Flag if hw is ready to send next packet */
int tx_ready;
- struct list_head tx_queue[NL_NUM_OF_PRIORITIES];
- /* True if any packets are queued for transmission */
+ /* Count of pending packets to be sent */
int tx_queued;
+ struct list_head tx_queue[NL_NUM_OF_PRIORITIES];
int rx_bytes_queued;
struct list_head rx_queue;
@@ -404,6 +405,8 @@ static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data,
spin_lock_irqsave(&hw->spinlock, flags);
+ hw->tx_ready = 0;
+
if (hw->hw_version == HW_VERSION_1) {
outw((unsigned short) length, hw->base_port + IODWR);
@@ -492,6 +495,7 @@ static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet)
spin_lock_irqsave(&hw->spinlock, flags);
list_add(&packet->queue, &hw->tx_queue[0]);
+ hw->tx_queued++;
spin_unlock_irqrestore(&hw->spinlock, flags);
} else {
if (packet->packet_callback)
@@ -949,12 +953,10 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit)
unsigned long flags;
spin_lock_irqsave(&hw->spinlock, flags);
- if (hw->tx_queued && hw->tx_ready != 0) {
+ if (hw->tx_queued && hw->tx_ready) {
int priority;
struct ipw_tx_packet *packet = NULL;
- hw->tx_ready--;
-
/* Pick a packet */
for (priority = 0; priority < priority_limit; priority++) {
if (!list_empty(&hw->tx_queue[priority])) {
@@ -963,6 +965,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit)
struct ipw_tx_packet,
queue);
+ hw->tx_queued--;
list_del(&packet->queue);
break;
@@ -973,6 +976,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit)
spin_unlock_irqrestore(&hw->spinlock, flags);
return 0;
}
+
spin_unlock_irqrestore(&hw->spinlock, flags);
/* Send */
@@ -1063,7 +1067,7 @@ static irqreturn_t ipwireless_handle_v1_interrupt(int irq,
if (irqn & IR_TXINTR) {
ack |= IR_TXINTR;
spin_lock_irqsave(&hw->spinlock, flags);
- hw->tx_ready++;
+ hw->tx_ready = 1;
spin_unlock_irqrestore(&hw->spinlock, flags);
}
/* Received data */
@@ -1170,7 +1174,7 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq,
if (memrxdone & MEMRX_RX_DONE) {
writew(0, &hw->memory_info_regs->memreg_rx_done);
spin_lock_irqsave(&hw->spinlock, flags);
- hw->tx_ready++;
+ hw->tx_ready = 1;
spin_unlock_irqrestore(&hw->spinlock, flags);
tx = 1;
}
@@ -1234,7 +1238,7 @@ static void send_packet(struct ipw_hardware *hw, int priority,
spin_lock_irqsave(&hw->spinlock, flags);
list_add_tail(&packet->queue, &hw->tx_queue[priority]);
- hw->tx_queued = 1;
+ hw->tx_queued++;
spin_unlock_irqrestore(&hw->spinlock, flags);
flush_packets_to_hw(hw);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index fa1ffbf2c621..935f1c207a1f 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -434,7 +434,7 @@ static void update_attr(struct vc_data *vc)
vc->vc_blink, vc->vc_underline,
vc->vc_reverse ^ vc->vc_decscnm, vc->vc_italic);
vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm, 0) << 8) | ' ';
- vc->vc_scrl_erase_char = (build_attr(vc, vc->vc_def_color, 1, false, false, false, false) << 8) | ' ';
+ vc->vc_scrl_erase_char = (build_attr(vc, vc->vc_def_color, 1, false, false, vc->vc_decscnm, false) << 8) | ' ';
}
/* Note: inverting the screen twice should revert to the original state */
@@ -909,7 +909,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
if (vc->vc_tty) {
struct winsize ws, *cws = &vc->vc_tty->winsize;
- unsigned long flags;
+ struct pid *pgrp = NULL;
memset(&ws, 0, sizeof(ws));
ws.ws_row = vc->vc_rows;
@@ -917,11 +917,14 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
ws.ws_ypixel = vc->vc_scan_lines;
mutex_lock(&vc->vc_tty->termios_mutex);
- spin_lock_irqsave(&vc->vc_tty->ctrl_lock, flags);
- if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) &&
- vc->vc_tty->pgrp)
+ spin_lock_irq(&vc->vc_tty->ctrl_lock);
+ if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col))
+ pgrp = get_pid(vc->vc_tty->pgrp);
+ spin_unlock_irq(&vc->vc_tty->ctrl_lock);
+ if (pgrp) {
kill_pgrp(vc->vc_tty->pgrp, SIGWINCH, 1);
- spin_unlock_irqrestore(&vc->vc_tty->ctrl_lock, flags);
+ put_pid(pgrp);
+ }
*cws = ws;
mutex_unlock(&vc->vc_tty->termios_mutex);
}
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 7fce038fa57e..4e07d1f43a43 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -625,7 +625,7 @@ static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy,
unsigned int freq = 0;
unsigned int ret;
- if (!policy->governor->store_setspeed)
+ if (!policy->governor || !policy->governor->store_setspeed)
return -EINVAL;
ret = sscanf(buf, "%u", &freq);
@@ -639,7 +639,7 @@ static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy,
static ssize_t show_scaling_setspeed(struct cpufreq_policy *policy, char *buf)
{
- if (!policy->governor->show_setspeed)
+ if (!policy->governor || !policy->governor->show_setspeed)
return sprintf(buf, "<unsupported>\n");
return policy->governor->show_setspeed(policy, buf);
@@ -928,13 +928,13 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
policy->user_policy.policy = policy->policy;
policy->user_policy.governor = policy->governor;
- unlock_policy_rwsem_write(cpu);
-
if (ret) {
dprintk("setting policy failed\n");
goto err_out_unregister;
}
+ unlock_policy_rwsem_write(cpu);
+
kobject_uevent(&policy->kobj, KOBJ_ADD);
module_put(cpufreq_driver->owner);
dprintk("initialization complete\n");
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index ae6cd60d5c14..b64c6bc445e3 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -2,6 +2,11 @@
* linux/drivers/cpufreq/freq_table.c
*
* Copyright (C) 2002 - 2003 Dominik Brodowski
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
*/
#include <linux/kernel.h>
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index 065732ddf40c..d49361bfe670 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -20,7 +20,6 @@
#include <linux/of_platform.h>
#include <linux/of_device.h>
-#include <asm/mpc85xx.h>
#include "edac_module.h"
#include "edac_core.h"
#include "mpc85xx_edac.h"
@@ -43,8 +42,6 @@ static u32 orig_pci_err_en;
static u32 orig_l2_err_disable;
static u32 orig_hid1;
-static const char *mpc85xx_ctl_name = "MPC85xx";
-
/************************ MC SYSFS parts ***********************************/
static ssize_t mpc85xx_mc_inject_data_hi_show(struct mem_ctl_info *mci,
diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c
index 744011989044..9e4f59dc7f1e 100644
--- a/drivers/firmware/edd.c
+++ b/drivers/firmware/edd.c
@@ -753,7 +753,7 @@ edd_init(void)
if (!edd_num_devices()) {
printk(KERN_INFO "EDD information not available.\n");
- return 1;
+ return -ENODEV;
}
edd_kset = kset_create_and_add("edd", NULL, firmware_kobj);
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 7f138c6195ff..beaf6b3a37dc 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -127,7 +127,7 @@ int __init gpiochip_reserve(int start, int ngpio)
unsigned long flags;
int i;
- if (!gpio_is_valid(start) || !gpio_is_valid(start + ngpio))
+ if (!gpio_is_valid(start) || !gpio_is_valid(start + ngpio - 1))
return -EINVAL;
spin_lock_irqsave(&gpio_lock, flags);
@@ -170,7 +170,7 @@ int gpiochip_add(struct gpio_chip *chip)
unsigned id;
int base = chip->base;
- if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio))
+ if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio - 1))
&& base >= 0) {
status = -EINVAL;
goto fail;
@@ -207,7 +207,7 @@ fail:
/* failures here can mean systems won't boot... */
if (status)
pr_err("gpiochip_add: gpios %d..%d (%s) not registered\n",
- chip->base, chip->base + chip->ngpio,
+ chip->base, chip->base + chip->ngpio - 1,
chip->label ? : "generic");
return status;
}
diff --git a/drivers/gpio/mcp23s08.c b/drivers/gpio/mcp23s08.c
index 7fb5b9d009d4..7f92fdd5f0e2 100644
--- a/drivers/gpio/mcp23s08.c
+++ b/drivers/gpio/mcp23s08.c
@@ -168,7 +168,7 @@ static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip)
{
struct mcp23s08 *mcp;
char bank;
- unsigned t;
+ int t;
unsigned mask;
mcp = container_of(chip, struct mcp23s08, chip);
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
index 93f916720b13..7e40e8a55edf 100644
--- a/drivers/gpio/pca953x.c
+++ b/drivers/gpio/pca953x.c
@@ -30,6 +30,7 @@ static const struct i2c_device_id pca953x_id[] = {
{ "pca9537", 4, },
{ "pca9538", 8, },
{ "pca9539", 16, },
+ { "pca9554", 8, },
{ "pca9555", 16, },
{ "pca9557", 8, },
/* REVISIT several pca955x parts should work here too */
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 4dc76bc45c9d..00ff53348491 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -330,6 +330,20 @@ config SENSORS_CORETEMP
sensor inside your CPU. Supported all are all known variants
of Intel Core family.
+config SENSORS_IBMAEM
+ tristate "IBM Active Energy Manager temperature/power sensors and control"
+ select IPMI_SI
+ depends on IPMI_HANDLER
+ help
+ If you say yes here you get support for the temperature and
+ power sensors and capping hardware in various IBM System X
+ servers that support Active Energy Manager. This includes
+ the x3350, x3550, x3650, x3655, x3755, x3850 M2, x3950 M2,
+ and certain HS2x/LS2x/QS2x blades.
+
+ This driver can also be built as a module. If so, the module
+ will be called ibmaem.
+
config SENSORS_IBMPEX
tristate "IBM PowerExecutive temperature/power sensors"
select IPMI_SI
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 3bdb05a5cbd7..d098677e08de 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o
+obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o
obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o
obj-$(CONFIG_SENSORS_IT87) += it87.o
obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
index bab5fd2e4dfd..26df06f840eb 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/hwmon/hdaps.c
@@ -515,12 +515,14 @@ static struct dmi_system_id __initdata hdaps_whitelist[] = {
HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R50"),
HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R51"),
HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R52"),
+ HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad R61i"),
HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T41p"),
HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T41"),
HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T42p"),
HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T42"),
HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T43"),
HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T60"),
+ HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61"),
HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X40"),
HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X41"),
HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X60"),
diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c
index 6ac5c6f53585..f9e2ed621f7b 100644
--- a/drivers/hwmon/i5k_amb.c
+++ b/drivers/hwmon/i5k_amb.c
@@ -111,6 +111,7 @@ struct i5k_amb_data {
void __iomem *amb_mmio;
struct i5k_device_attribute *attrs;
unsigned int num_attrs;
+ unsigned long chipset_id;
};
static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
@@ -382,7 +383,8 @@ err:
return res;
}
-static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data)
+static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data,
+ unsigned long devid)
{
struct pci_dev *pcidev;
u32 val32;
@@ -390,7 +392,7 @@ static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data)
/* Find AMB register memory space */
pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_5000_ERR,
+ devid,
NULL);
if (!pcidev)
return -ENODEV;
@@ -409,6 +411,8 @@ static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data)
goto out;
}
+ data->chipset_id = devid;
+
res = 0;
out:
pci_dev_put(pcidev);
@@ -441,10 +445,30 @@ out:
return res;
}
+static unsigned long i5k_channel_pci_id(struct i5k_amb_data *data,
+ unsigned long channel)
+{
+ switch (data->chipset_id) {
+ case PCI_DEVICE_ID_INTEL_5000_ERR:
+ return PCI_DEVICE_ID_INTEL_5000_FBD0 + channel;
+ case PCI_DEVICE_ID_INTEL_5400_ERR:
+ return PCI_DEVICE_ID_INTEL_5400_FBD0 + channel;
+ default:
+ BUG();
+ }
+}
+
+static unsigned long chipset_ids[] = {
+ PCI_DEVICE_ID_INTEL_5000_ERR,
+ PCI_DEVICE_ID_INTEL_5400_ERR,
+ 0
+};
+
static int __devinit i5k_amb_probe(struct platform_device *pdev)
{
struct i5k_amb_data *data;
struct resource *reso;
+ int i;
int res = -ENODEV;
data = kzalloc(sizeof(*data), GFP_KERNEL);
@@ -452,19 +476,24 @@ static int __devinit i5k_amb_probe(struct platform_device *pdev)
return -ENOMEM;
/* Figure out where the AMB registers live */
- res = i5k_find_amb_registers(data);
+ i = 0;
+ do {
+ res = i5k_find_amb_registers(data, chipset_ids[i]);
+ i++;
+ } while (res && chipset_ids[i]);
+
if (res)
goto err;
/* Copy the DIMM presence map for the first two channels */
res = i5k_channel_probe(&data->amb_present[0],
- PCI_DEVICE_ID_INTEL_5000_FBD0);
+ i5k_channel_pci_id(data, 0));
if (res)
goto err;
/* Copy the DIMM presence map for the optional second two channels */
i5k_channel_probe(&data->amb_present[2],
- PCI_DEVICE_ID_INTEL_5000_FBD1);
+ i5k_channel_pci_id(data, 1));
/* Set up resource regions */
reso = request_mem_region(data->amb_base, data->amb_len, DRVNAME);
diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c
new file mode 100644
index 000000000000..c9416e657487
--- /dev/null
+++ b/drivers/hwmon/ibmaem.c
@@ -0,0 +1,1111 @@
+/*
+ * A hwmon driver for the IBM Active Energy Manager temperature/power sensors
+ * and capping functionality.
+ * Copyright (C) 2008 IBM
+ *
+ * Author: Darrick J. Wong <djwong@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/ipmi.h>
+#include <linux/module.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/jiffies.h>
+#include <linux/mutex.h>
+#include <linux/kdev_t.h>
+#include <linux/spinlock.h>
+#include <linux/idr.h>
+#include <linux/sched.h>
+#include <linux/platform_device.h>
+#include <linux/math64.h>
+#include <linux/time.h>
+
+#define REFRESH_INTERVAL (HZ)
+#define IPMI_TIMEOUT (30 * HZ)
+#define DRVNAME "aem"
+
+#define AEM_NETFN 0x2E
+
+#define AEM_FIND_FW_CMD 0x80
+#define AEM_ELEMENT_CMD 0x81
+#define AEM_FW_INSTANCE_CMD 0x82
+
+#define AEM_READ_ELEMENT_CFG 0x80
+#define AEM_READ_BUFFER 0x81
+#define AEM_READ_REGISTER 0x82
+#define AEM_WRITE_REGISTER 0x83
+#define AEM_SET_REG_MASK 0x84
+#define AEM_CLEAR_REG_MASK 0x85
+#define AEM_READ_ELEMENT_CFG2 0x86
+
+#define AEM_CONTROL_ELEMENT 0
+#define AEM_ENERGY_ELEMENT 1
+#define AEM_CLOCK_ELEMENT 4
+#define AEM_POWER_CAP_ELEMENT 7
+#define AEM_EXHAUST_ELEMENT 9
+#define AEM_POWER_ELEMENT 10
+
+#define AEM_MODULE_TYPE_ID 0x0001
+
+#define AEM2_NUM_ENERGY_REGS 2
+#define AEM2_NUM_PCAP_REGS 6
+#define AEM2_NUM_TEMP_REGS 2
+#define AEM2_NUM_SENSORS 14
+
+#define AEM1_NUM_ENERGY_REGS 1
+#define AEM1_NUM_SENSORS 3
+
+/* AEM 2.x has more energy registers */
+#define AEM_NUM_ENERGY_REGS AEM2_NUM_ENERGY_REGS
+/* AEM 2.x needs more sensor files */
+#define AEM_NUM_SENSORS AEM2_NUM_SENSORS
+
+#define POWER_CAP 0
+#define POWER_CAP_MAX_HOTPLUG 1
+#define POWER_CAP_MAX 2
+#define POWER_CAP_MIN_WARNING 3
+#define POWER_CAP_MIN 4
+#define POWER_AUX 5
+
+#define AEM_DEFAULT_POWER_INTERVAL 1000
+#define AEM_MIN_POWER_INTERVAL 200
+#define UJ_PER_MJ 1000L
+
+static DEFINE_IDR(aem_idr);
+static DEFINE_SPINLOCK(aem_idr_lock);
+
+static struct device_driver aem_driver = {
+ .name = DRVNAME,
+ .bus = &platform_bus_type,
+};
+
+struct aem_ipmi_data {
+ struct completion read_complete;
+ struct ipmi_addr address;
+ ipmi_user_t user;
+ int interface;
+
+ struct kernel_ipmi_msg tx_message;
+ long tx_msgid;
+
+ void *rx_msg_data;
+ unsigned short rx_msg_len;
+ unsigned char rx_result;
+ int rx_recv_type;
+
+ struct device *bmc_device;
+};
+
+struct aem_ro_sensor_template {
+ char *label;
+ ssize_t (*show)(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf);
+ int index;
+};
+
+struct aem_rw_sensor_template {
+ char *label;
+ ssize_t (*show)(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf);
+ ssize_t (*set)(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count);
+ int index;
+};
+
+struct aem_data {
+ struct list_head list;
+
+ struct device *hwmon_dev;
+ struct platform_device *pdev;
+ struct mutex lock;
+ char valid;
+ unsigned long last_updated; /* In jiffies */
+ u8 ver_major;
+ u8 ver_minor;
+ u8 module_handle;
+ int id;
+ struct aem_ipmi_data ipmi;
+
+ /* Function to update sensors */
+ void (*update)(struct aem_data *data);
+
+ /*
+ * AEM 1.x sensors:
+ * Available sensors:
+ * Energy meter
+ * Power meter
+ *
+ * AEM 2.x sensors:
+ * Two energy meters
+ * Two power meters
+ * Two temperature sensors
+ * Six power cap registers
+ */
+
+ /* sysfs attrs */
+ struct sensor_device_attribute sensors[AEM_NUM_SENSORS];
+
+ /* energy use in mJ */
+ u64 energy[AEM_NUM_ENERGY_REGS];
+
+ /* power sampling interval in ms */
+ unsigned long power_period[AEM_NUM_ENERGY_REGS];
+
+ /* Everything past here is for AEM2 only */
+
+ /* power caps in dW */
+ u16 pcap[AEM2_NUM_PCAP_REGS];
+
+ /* exhaust temperature in C */
+ u8 temp[AEM2_NUM_TEMP_REGS];
+};
+
+/* Data structures returned by the AEM firmware */
+struct aem_iana_id {
+ u8 bytes[3];
+};
+static struct aem_iana_id system_x_id = {
+ .bytes = {0x4D, 0x4F, 0x00}
+};
+
+/* These are used to find AEM1 instances */
+struct aem_find_firmware_req {
+ struct aem_iana_id id;
+ u8 rsvd;
+ __be16 index;
+ __be16 module_type_id;
+} __packed;
+
+struct aem_find_firmware_resp {
+ struct aem_iana_id id;
+ u8 num_instances;
+} __packed;
+
+/* These are used to find AEM2 instances */
+struct aem_find_instance_req {
+ struct aem_iana_id id;
+ u8 instance_number;
+ __be16 module_type_id;
+} __packed;
+
+struct aem_find_instance_resp {
+ struct aem_iana_id id;
+ u8 num_instances;
+ u8 major;
+ u8 minor;
+ u8 module_handle;
+ u16 record_id;
+} __packed;
+
+/* These are used to query sensors */
+struct aem_read_sensor_req {
+ struct aem_iana_id id;
+ u8 module_handle;
+ u8 element;
+ u8 subcommand;
+ u8 reg;
+ u8 rx_buf_size;
+} __packed;
+
+struct aem_read_sensor_resp {
+ struct aem_iana_id id;
+ u8 bytes[0];
+} __packed;
+
+/* Data structures to talk to the IPMI layer */
+struct aem_driver_data {
+ struct list_head aem_devices;
+ struct ipmi_smi_watcher bmc_events;
+ struct ipmi_user_hndl ipmi_hndlrs;
+};
+
+static void aem_register_bmc(int iface, struct device *dev);
+static void aem_bmc_gone(int iface);
+static void aem_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data);
+
+static void aem_remove_sensors(struct aem_data *data);
+static int aem_init_aem1(struct aem_ipmi_data *probe);
+static int aem_init_aem2(struct aem_ipmi_data *probe);
+static int aem1_find_sensors(struct aem_data *data);
+static int aem2_find_sensors(struct aem_data *data);
+static void update_aem1_sensors(struct aem_data *data);
+static void update_aem2_sensors(struct aem_data *data);
+
+static struct aem_driver_data driver_data = {
+ .aem_devices = LIST_HEAD_INIT(driver_data.aem_devices),
+ .bmc_events = {
+ .owner = THIS_MODULE,
+ .new_smi = aem_register_bmc,
+ .smi_gone = aem_bmc_gone,
+ },
+ .ipmi_hndlrs = {
+ .ipmi_recv_hndl = aem_msg_handler,
+ },
+};
+
+/* Functions to talk to the IPMI layer */
+
+/* Initialize IPMI address, message buffers and user data */
+static int aem_init_ipmi_data(struct aem_ipmi_data *data, int iface,
+ struct device *bmc)
+{
+ int err;
+
+ init_completion(&data->read_complete);
+ data->bmc_device = bmc;
+
+ /* Initialize IPMI address */
+ data->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+ data->address.channel = IPMI_BMC_CHANNEL;
+ data->address.data[0] = 0;
+ data->interface = iface;
+
+ /* Initialize message buffers */
+ data->tx_msgid = 0;
+ data->tx_message.netfn = AEM_NETFN;
+
+ /* Create IPMI messaging interface user */
+ err = ipmi_create_user(data->interface, &driver_data.ipmi_hndlrs,
+ data, &data->user);
+ if (err < 0) {
+ dev_err(bmc, "Unable to register user with IPMI "
+ "interface %d\n", data->interface);
+ return -EACCES;
+ }
+
+ return 0;
+}
+
+/* Send an IPMI command */
+static int aem_send_message(struct aem_ipmi_data *data)
+{
+ int err;
+
+ err = ipmi_validate_addr(&data->address, sizeof(data->address));
+ if (err)
+ goto out;
+
+ data->tx_msgid++;
+ err = ipmi_request_settime(data->user, &data->address, data->tx_msgid,
+ &data->tx_message, data, 0, 0, 0);
+ if (err)
+ goto out1;
+
+ return 0;
+out1:
+ dev_err(data->bmc_device, "request_settime=%x\n", err);
+ return err;
+out:
+ dev_err(data->bmc_device, "validate_addr=%x\n", err);
+ return err;
+}
+
+/* Dispatch IPMI messages to callers */
+static void aem_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
+{
+ unsigned short rx_len;
+ struct aem_ipmi_data *data = user_msg_data;
+
+ if (msg->msgid != data->tx_msgid) {
+ dev_err(data->bmc_device, "Mismatch between received msgid "
+ "(%02x) and transmitted msgid (%02x)!\n",
+ (int)msg->msgid,
+ (int)data->tx_msgid);
+ ipmi_free_recv_msg(msg);
+ return;
+ }
+
+ data->rx_recv_type = msg->recv_type;
+ if (msg->msg.data_len > 0)
+ data->rx_result = msg->msg.data[0];
+ else
+ data->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE;
+
+ if (msg->msg.data_len > 1) {
+ rx_len = msg->msg.data_len - 1;
+ if (data->rx_msg_len < rx_len)
+ rx_len = data->rx_msg_len;
+ data->rx_msg_len = rx_len;
+ memcpy(data->rx_msg_data, msg->msg.data + 1, data->rx_msg_len);
+ } else
+ data->rx_msg_len = 0;
+
+ ipmi_free_recv_msg(msg);
+ complete(&data->read_complete);
+}
+
+/* ID functions */
+
+/* Obtain an id */
+static int aem_idr_get(int *id)
+{
+ int i, err;
+
+again:
+ if (unlikely(!idr_pre_get(&aem_idr, GFP_KERNEL)))
+ return -ENOMEM;
+
+ spin_lock(&aem_idr_lock);
+ err = idr_get_new(&aem_idr, NULL, &i);
+ spin_unlock(&aem_idr_lock);
+
+ if (unlikely(err == -EAGAIN))
+ goto again;
+ else if (unlikely(err))
+ return err;
+
+ *id = i & MAX_ID_MASK;
+ return 0;
+}
+
+/* Release an object ID */
+static void aem_idr_put(int id)
+{
+ spin_lock(&aem_idr_lock);
+ idr_remove(&aem_idr, id);
+ spin_unlock(&aem_idr_lock);
+}
+
+/* Sensor support functions */
+
+/* Read a sensor value */
+static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg,
+ void *buf, size_t size)
+{
+ int rs_size, res;
+ struct aem_read_sensor_req rs_req;
+ struct aem_read_sensor_resp *rs_resp;
+ struct aem_ipmi_data *ipmi = &data->ipmi;
+
+ /* AEM registers are 1, 2, 4 or 8 bytes */
+ switch (size) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ rs_req.id = system_x_id;
+ rs_req.module_handle = data->module_handle;
+ rs_req.element = elt;
+ rs_req.subcommand = AEM_READ_REGISTER;
+ rs_req.reg = reg;
+ rs_req.rx_buf_size = size;
+
+ ipmi->tx_message.cmd = AEM_ELEMENT_CMD;
+ ipmi->tx_message.data = (char *)&rs_req;
+ ipmi->tx_message.data_len = sizeof(rs_req);
+
+ rs_size = sizeof(*rs_resp) + size;
+ rs_resp = kzalloc(rs_size, GFP_KERNEL);
+ if (!rs_resp)
+ return -ENOMEM;
+
+ ipmi->rx_msg_data = rs_resp;
+ ipmi->rx_msg_len = rs_size;
+
+ aem_send_message(ipmi);
+
+ res = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT);
+ if (!res)
+ return -ETIMEDOUT;
+
+ if (ipmi->rx_result || ipmi->rx_msg_len != rs_size ||
+ memcmp(&rs_resp->id, &system_x_id, sizeof(system_x_id))) {
+ kfree(rs_resp);
+ return -ENOENT;
+ }
+
+ switch (size) {
+ case 1: {
+ u8 *x = buf;
+ *x = rs_resp->bytes[0];
+ break;
+ }
+ case 2: {
+ u16 *x = buf;
+ *x = be16_to_cpup((__be16 *)rs_resp->bytes);
+ break;
+ }
+ case 4: {
+ u32 *x = buf;
+ *x = be32_to_cpup((__be32 *)rs_resp->bytes);
+ break;
+ }
+ case 8: {
+ u64 *x = buf;
+ *x = be64_to_cpup((__be64 *)rs_resp->bytes);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/* Update AEM energy registers */
+static void update_aem_energy(struct aem_data *data)
+{
+ aem_read_sensor(data, AEM_ENERGY_ELEMENT, 0, &data->energy[0], 8);
+ if (data->ver_major < 2)
+ return;
+ aem_read_sensor(data, AEM_ENERGY_ELEMENT, 1, &data->energy[1], 8);
+}
+
+/* Update all AEM1 sensors */
+static void update_aem1_sensors(struct aem_data *data)
+{
+ mutex_lock(&data->lock);
+ if (time_before(jiffies, data->last_updated + REFRESH_INTERVAL) &&
+ data->valid)
+ goto out;
+
+ update_aem_energy(data);
+out:
+ mutex_unlock(&data->lock);
+}
+
+/* Update all AEM2 sensors */
+static void update_aem2_sensors(struct aem_data *data)
+{
+ int i;
+
+ mutex_lock(&data->lock);
+ if (time_before(jiffies, data->last_updated + REFRESH_INTERVAL) &&
+ data->valid)
+ goto out;
+
+ update_aem_energy(data);
+ aem_read_sensor(data, AEM_EXHAUST_ELEMENT, 0, &data->temp[0], 1);
+ aem_read_sensor(data, AEM_EXHAUST_ELEMENT, 1, &data->temp[1], 1);
+
+ for (i = POWER_CAP; i <= POWER_AUX; i++)
+ aem_read_sensor(data, AEM_POWER_CAP_ELEMENT, i,
+ &data->pcap[i], 2);
+out:
+ mutex_unlock(&data->lock);
+}
+
+/* Delete an AEM instance */
+static void aem_delete(struct aem_data *data)
+{
+ list_del(&data->list);
+ aem_remove_sensors(data);
+ hwmon_device_unregister(data->hwmon_dev);
+ ipmi_destroy_user(data->ipmi.user);
+ dev_set_drvdata(&data->pdev->dev, NULL);
+ platform_device_unregister(data->pdev);
+ aem_idr_put(data->id);
+ kfree(data);
+}
+
+/* Probe functions for AEM1 devices */
+
+/* Retrieve version and module handle for an AEM1 instance */
+static int aem_find_aem1_count(struct aem_ipmi_data *data)
+{
+ int res;
+ struct aem_find_firmware_req ff_req;
+ struct aem_find_firmware_resp ff_resp;
+
+ ff_req.id = system_x_id;
+ ff_req.index = 0;
+ ff_req.module_type_id = cpu_to_be16(AEM_MODULE_TYPE_ID);
+
+ data->tx_message.cmd = AEM_FIND_FW_CMD;
+ data->tx_message.data = (char *)&ff_req;
+ data->tx_message.data_len = sizeof(ff_req);
+
+ data->rx_msg_data = &ff_resp;
+ data->rx_msg_len = sizeof(ff_resp);
+
+ aem_send_message(data);
+
+ res = wait_for_completion_timeout(&data->read_complete, IPMI_TIMEOUT);
+ if (!res)
+ return -ETIMEDOUT;
+
+ if (data->rx_result || data->rx_msg_len != sizeof(ff_resp) ||
+ memcmp(&ff_resp.id, &system_x_id, sizeof(system_x_id)))
+ return -ENOENT;
+
+ return ff_resp.num_instances;
+}
+
+/* Find and initialize one AEM1 instance */
+static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle)
+{
+ struct aem_data *data;
+ int i;
+ int res = -ENOMEM;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return res;
+ mutex_init(&data->lock);
+
+ /* Copy instance data */
+ data->ver_major = 1;
+ data->ver_minor = 0;
+ data->module_handle = module_handle;
+ for (i = 0; i < AEM1_NUM_ENERGY_REGS; i++)
+ data->power_period[i] = AEM_DEFAULT_POWER_INTERVAL;
+
+ /* Create sub-device for this fw instance */
+ if (aem_idr_get(&data->id))
+ goto id_err;
+
+ data->pdev = platform_device_alloc(DRVNAME, data->id);
+ if (!data->pdev)
+ goto dev_err;
+ data->pdev->dev.driver = &aem_driver;
+
+ res = platform_device_add(data->pdev);
+ if (res)
+ goto ipmi_err;
+
+ dev_set_drvdata(&data->pdev->dev, data);
+
+ /* Set up IPMI interface */
+ if (aem_init_ipmi_data(&data->ipmi, probe->interface,
+ probe->bmc_device))
+ goto ipmi_err;
+
+ /* Register with hwmon */
+ data->hwmon_dev = hwmon_device_register(&data->pdev->dev);
+
+ if (IS_ERR(data->hwmon_dev)) {
+ dev_err(&data->pdev->dev, "Unable to register hwmon "
+ "device for IPMI interface %d\n",
+ probe->interface);
+ goto hwmon_reg_err;
+ }
+
+ data->update = update_aem1_sensors;
+
+ /* Find sensors */
+ if (aem1_find_sensors(data))
+ goto sensor_err;
+
+ /* Add to our list of AEM devices */
+ list_add_tail(&data->list, &driver_data.aem_devices);
+
+ dev_info(data->ipmi.bmc_device, "Found AEM v%d.%d at 0x%X\n",
+ data->ver_major, data->ver_minor,
+ data->module_handle);
+ return 0;
+
+sensor_err:
+ hwmon_device_unregister(data->hwmon_dev);
+hwmon_reg_err:
+ ipmi_destroy_user(data->ipmi.user);
+ipmi_err:
+ dev_set_drvdata(&data->pdev->dev, NULL);
+ platform_device_unregister(data->pdev);
+dev_err:
+ aem_idr_put(data->id);
+id_err:
+ kfree(data);
+
+ return res;
+}
+
+/* Find and initialize all AEM1 instances */
+static int aem_init_aem1(struct aem_ipmi_data *probe)
+{
+ int num, i, err;
+
+ num = aem_find_aem1_count(probe);
+ for (i = 0; i < num; i++) {
+ err = aem_init_aem1_inst(probe, i);
+ if (err) {
+ dev_err(probe->bmc_device,
+ "Error %d initializing AEM1 0x%X\n",
+ err, i);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+/* Probe functions for AEM2 devices */
+
+/* Retrieve version and module handle for an AEM2 instance */
+static int aem_find_aem2(struct aem_ipmi_data *data,
+ struct aem_find_instance_resp *fi_resp,
+ int instance_num)
+{
+ int res;
+ struct aem_find_instance_req fi_req;
+
+ fi_req.id = system_x_id;
+ fi_req.instance_number = instance_num;
+ fi_req.module_type_id = cpu_to_be16(AEM_MODULE_TYPE_ID);
+
+ data->tx_message.cmd = AEM_FW_INSTANCE_CMD;
+ data->tx_message.data = (char *)&fi_req;
+ data->tx_message.data_len = sizeof(fi_req);
+
+ data->rx_msg_data = fi_resp;
+ data->rx_msg_len = sizeof(*fi_resp);
+
+ aem_send_message(data);
+
+ res = wait_for_completion_timeout(&data->read_complete, IPMI_TIMEOUT);
+ if (!res)
+ return -ETIMEDOUT;
+
+ if (data->rx_result || data->rx_msg_len != sizeof(*fi_resp) ||
+ memcmp(&fi_resp->id, &system_x_id, sizeof(system_x_id)))
+ return -ENOENT;
+
+ return 0;
+}
+
+/* Find and initialize one AEM2 instance */
+static int aem_init_aem2_inst(struct aem_ipmi_data *probe,
+ struct aem_find_instance_resp *fi_resp)
+{
+ struct aem_data *data;
+ int i;
+ int res = -ENOMEM;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return res;
+ mutex_init(&data->lock);
+
+ /* Copy instance data */
+ data->ver_major = fi_resp->major;
+ data->ver_minor = fi_resp->minor;
+ data->module_handle = fi_resp->module_handle;
+ for (i = 0; i < AEM2_NUM_ENERGY_REGS; i++)
+ data->power_period[i] = AEM_DEFAULT_POWER_INTERVAL;
+
+ /* Create sub-device for this fw instance */
+ if (aem_idr_get(&data->id))
+ goto id_err;
+
+ data->pdev = platform_device_alloc(DRVNAME, data->id);
+ if (!data->pdev)
+ goto dev_err;
+ data->pdev->dev.driver = &aem_driver;
+
+ res = platform_device_add(data->pdev);
+ if (res)
+ goto ipmi_err;
+
+ dev_set_drvdata(&data->pdev->dev, data);
+
+ /* Set up IPMI interface */
+ if (aem_init_ipmi_data(&data->ipmi, probe->interface,
+ probe->bmc_device))
+ goto ipmi_err;
+
+ /* Register with hwmon */
+ data->hwmon_dev = hwmon_device_register(&data->pdev->dev);
+
+ if (IS_ERR(data->hwmon_dev)) {
+ dev_err(&data->pdev->dev, "Unable to register hwmon "
+ "device for IPMI interface %d\n",
+ probe->interface);
+ goto hwmon_reg_err;
+ }
+
+ data->update = update_aem2_sensors;
+
+ /* Find sensors */
+ if (aem2_find_sensors(data))
+ goto sensor_err;
+
+ /* Add to our list of AEM devices */
+ list_add_tail(&data->list, &driver_data.aem_devices);
+
+ dev_info(data->ipmi.bmc_device, "Found AEM v%d.%d at 0x%X\n",
+ data->ver_major, data->ver_minor,
+ data->module_handle);
+ return 0;
+
+sensor_err:
+ hwmon_device_unregister(data->hwmon_dev);
+hwmon_reg_err:
+ ipmi_destroy_user(data->ipmi.user);
+ipmi_err:
+ dev_set_drvdata(&data->pdev->dev, NULL);
+ platform_device_unregister(data->pdev);
+dev_err:
+ aem_idr_put(data->id);
+id_err:
+ kfree(data);
+
+ return res;
+}
+
+/* Find and initialize all AEM2 instances */
+static int aem_init_aem2(struct aem_ipmi_data *probe)
+{
+ struct aem_find_instance_resp fi_resp;
+ int err;
+ int i = 0;
+
+ while (!aem_find_aem2(probe, &fi_resp, i)) {
+ if (fi_resp.major != 2) {
+ dev_err(probe->bmc_device, "Unknown AEM v%d; please "
+ "report this to the maintainer.\n",
+ fi_resp.major);
+ i++;
+ continue;
+ }
+ err = aem_init_aem2_inst(probe, &fi_resp);
+ if (err) {
+ dev_err(probe->bmc_device,
+ "Error %d initializing AEM2 0x%X\n",
+ err, fi_resp.module_handle);
+ return err;
+ }
+ i++;
+ }
+
+ return 0;
+}
+
+/* Probe a BMC for AEM firmware instances */
+static void aem_register_bmc(int iface, struct device *dev)
+{
+ struct aem_ipmi_data probe;
+
+ if (aem_init_ipmi_data(&probe, iface, dev))
+ return;
+
+ /* Ignore probe errors; they won't cause problems */
+ aem_init_aem1(&probe);
+ aem_init_aem2(&probe);
+
+ ipmi_destroy_user(probe.user);
+}
+
+/* Handle BMC deletion */
+static void aem_bmc_gone(int iface)
+{
+ struct aem_data *p1, *next1;
+
+ list_for_each_entry_safe(p1, next1, &driver_data.aem_devices, list)
+ if (p1->ipmi.interface == iface)
+ aem_delete(p1);
+}
+
+/* sysfs support functions */
+
+/* AEM device name */
+static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct aem_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s%d\n", DRVNAME, data->ver_major);
+}
+static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
+
+/* AEM device version */
+static ssize_t show_version(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct aem_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d.%d\n", data->ver_major, data->ver_minor);
+}
+static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, 0);
+
+/* Display power use */
+static ssize_t aem_show_power(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct aem_data *data = dev_get_drvdata(dev);
+ u64 before, after, delta, time;
+ signed long leftover;
+ struct timespec b, a;
+
+ mutex_lock(&data->lock);
+ update_aem_energy(data);
+ getnstimeofday(&b);
+ before = data->energy[attr->index];
+
+ leftover = schedule_timeout_interruptible(
+ msecs_to_jiffies(data->power_period[attr->index])
+ );
+ if (leftover) {
+ mutex_unlock(&data->lock);
+ return 0;
+ }
+
+ update_aem_energy(data);
+ getnstimeofday(&a);
+ after = data->energy[attr->index];
+ mutex_unlock(&data->lock);
+
+ time = timespec_to_ns(&a) - timespec_to_ns(&b);
+ delta = (after - before) * UJ_PER_MJ;
+
+ return sprintf(buf, "%llu\n",
+ (unsigned long long)div64_u64(delta * NSEC_PER_SEC, time));
+}
+
+/* Display energy use */
+static ssize_t aem_show_energy(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct aem_data *a = dev_get_drvdata(dev);
+ a->update(a);
+
+ return sprintf(buf, "%llu\n",
+ (unsigned long long)a->energy[attr->index] * 1000);
+}
+
+/* Display power interval registers */
+static ssize_t aem_show_power_period(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct aem_data *a = dev_get_drvdata(dev);
+ a->update(a);
+
+ return sprintf(buf, "%lu\n", a->power_period[attr->index]);
+}
+
+/* Set power interval registers */
+static ssize_t aem_set_power_period(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct aem_data *a = dev_get_drvdata(dev);
+ unsigned long temp;
+ int res;
+
+ res = strict_strtoul(buf, 10, &temp);
+ if (res)
+ return res;
+
+ if (temp < AEM_MIN_POWER_INTERVAL)
+ return -EINVAL;
+
+ mutex_lock(&a->lock);
+ a->power_period[attr->index] = temp;
+ mutex_unlock(&a->lock);
+
+ return count;
+}
+
+/* Discover sensors on an AEM device */
+static int aem_register_sensors(struct aem_data *data,
+ struct aem_ro_sensor_template *ro,
+ struct aem_rw_sensor_template *rw)
+{
+ struct device *dev = &data->pdev->dev;
+ struct sensor_device_attribute *sensors = data->sensors;
+ int err;
+
+ /* Set up read-only sensors */
+ while (ro->label) {
+ sensors->dev_attr.attr.name = ro->label;
+ sensors->dev_attr.attr.mode = S_IRUGO;
+ sensors->dev_attr.show = ro->show;
+ sensors->index = ro->index;
+
+ err = device_create_file(dev, &sensors->dev_attr);
+ if (err) {
+ sensors->dev_attr.attr.name = NULL;
+ goto error;
+ }
+ sensors++;
+ ro++;
+ }
+
+ /* Set up read-write sensors */
+ while (rw->label) {
+ sensors->dev_attr.attr.name = rw->label;
+ sensors->dev_attr.attr.mode = S_IRUGO | S_IWUSR;
+ sensors->dev_attr.show = rw->show;
+ sensors->dev_attr.store = rw->set;
+ sensors->index = rw->index;
+
+ err = device_create_file(dev, &sensors->dev_attr);
+ if (err) {
+ sensors->dev_attr.attr.name = NULL;
+ goto error;
+ }
+ sensors++;
+ rw++;
+ }
+
+ err = device_create_file(dev, &sensor_dev_attr_name.dev_attr);
+ if (err)
+ goto error;
+ err = device_create_file(dev, &sensor_dev_attr_version.dev_attr);
+ return err;
+
+error:
+ aem_remove_sensors(data);
+ return err;
+}
+
+/* sysfs support functions for AEM2 sensors */
+
+/* Display temperature use */
+static ssize_t aem2_show_temp(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct aem_data *a = dev_get_drvdata(dev);
+ a->update(a);
+
+ return sprintf(buf, "%u\n", a->temp[attr->index] * 1000);
+}
+
+/* Display power-capping registers */
+static ssize_t aem2_show_pcap_value(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct aem_data *a = dev_get_drvdata(dev);
+ a->update(a);
+
+ return sprintf(buf, "%u\n", a->pcap[attr->index] * 100000);
+}
+
+/* Remove sensors attached to an AEM device */
+static void aem_remove_sensors(struct aem_data *data)
+{
+ int i;
+
+ for (i = 0; i < AEM_NUM_SENSORS; i++) {
+ if (!data->sensors[i].dev_attr.attr.name)
+ continue;
+ device_remove_file(&data->pdev->dev,
+ &data->sensors[i].dev_attr);
+ }
+
+ device_remove_file(&data->pdev->dev,
+ &sensor_dev_attr_name.dev_attr);
+ device_remove_file(&data->pdev->dev,
+ &sensor_dev_attr_version.dev_attr);
+}
+
+/* Sensor probe functions */
+
+/* Description of AEM1 sensors */
+static struct aem_ro_sensor_template aem1_ro_sensors[] = {
+{"energy1_input", aem_show_energy, 0},
+{"power1_average", aem_show_power, 0},
+{NULL, NULL, 0},
+};
+
+static struct aem_rw_sensor_template aem1_rw_sensors[] = {
+{"power1_average_interval", aem_show_power_period, aem_set_power_period, 0},
+{NULL, NULL, NULL, 0},
+};
+
+/* Description of AEM2 sensors */
+static struct aem_ro_sensor_template aem2_ro_sensors[] = {
+{"energy1_input", aem_show_energy, 0},
+{"energy2_input", aem_show_energy, 1},
+{"power1_average", aem_show_power, 0},
+{"power2_average", aem_show_power, 1},
+{"temp1_input", aem2_show_temp, 0},
+{"temp2_input", aem2_show_temp, 1},
+
+{"power4_average", aem2_show_pcap_value, POWER_CAP_MAX_HOTPLUG},
+{"power5_average", aem2_show_pcap_value, POWER_CAP_MAX},
+{"power6_average", aem2_show_pcap_value, POWER_CAP_MIN_WARNING},
+{"power7_average", aem2_show_pcap_value, POWER_CAP_MIN},
+
+{"power3_average", aem2_show_pcap_value, POWER_AUX},
+{"power_cap", aem2_show_pcap_value, POWER_CAP},
+{NULL, NULL, 0},
+};
+
+static struct aem_rw_sensor_template aem2_rw_sensors[] = {
+{"power1_average_interval", aem_show_power_period, aem_set_power_period, 0},
+{"power2_average_interval", aem_show_power_period, aem_set_power_period, 1},
+{NULL, NULL, NULL, 0},
+};
+
+/* Set up AEM1 sensor attrs */
+static int aem1_find_sensors(struct aem_data *data)
+{
+ return aem_register_sensors(data, aem1_ro_sensors, aem1_rw_sensors);
+}
+
+/* Set up AEM2 sensor attrs */
+static int aem2_find_sensors(struct aem_data *data)
+{
+ return aem_register_sensors(data, aem2_ro_sensors, aem2_rw_sensors);
+}
+
+/* Module init/exit routines */
+
+static int __init aem_init(void)
+{
+ int res;
+
+ res = driver_register(&aem_driver);
+ if (res) {
+ printk(KERN_ERR "Can't register aem driver\n");
+ return res;
+ }
+
+ res = ipmi_smi_watcher_register(&driver_data.bmc_events);
+ if (res)
+ goto ipmi_reg_err;
+ return 0;
+
+ipmi_reg_err:
+ driver_unregister(&aem_driver);
+ return res;
+
+}
+
+static void __exit aem_exit(void)
+{
+ struct aem_data *p1, *next1;
+
+ ipmi_smi_watcher_unregister(&driver_data.bmc_events);
+ driver_unregister(&aem_driver);
+ list_for_each_entry_safe(p1, next1, &driver_data.aem_devices, list)
+ aem_delete(p1);
+}
+
+MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>");
+MODULE_DESCRIPTION("IBM Active Energy Manager power/temp sensor driver");
+MODULE_LICENSE("GPL");
+
+module_init(aem_init);
+module_exit(aem_exit);
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index fbe16d5250a4..1adf2efd3cb3 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -747,7 +747,9 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
break;
case IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED:
kmem_cache_free(ib_mad_cache, mad_priv);
- break;
+ kfree(local);
+ ret = 1;
+ goto out;
case IB_MAD_RESULT_SUCCESS:
/* Treat like an incoming receive MAD */
port_priv = ib_get_mad_port(mad_agent_priv->agent.device,
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
index 79dbe5beae52..992613799228 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
@@ -229,7 +229,7 @@ int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
struct ib_send_wr **bad_wr)
{
int err = 0;
- u8 t3_wr_flit_cnt;
+ u8 uninitialized_var(t3_wr_flit_cnt);
enum t3_wr_opcode t3_wr_opcode = 0;
enum t3_wr_flags t3_wr_flags;
struct iwch_qp *qhp;
diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
index bbe0436f4f75..f093b0033daf 100644
--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -421,8 +421,10 @@ int ehca_post_send(struct ib_qp *qp,
int ret = 0;
unsigned long flags;
- if (unlikely(my_qp->state != IB_QPS_RTS)) {
- ehca_err(qp->device, "QP not in RTS state qpn=%x", qp->qp_num);
+ /* Reject WR if QP is in RESET, INIT or RTR state */
+ if (unlikely(my_qp->state < IB_QPS_RTS)) {
+ ehca_err(qp->device, "Invalid QP state qp_state=%d qpn=%x",
+ my_qp->state, qp->qp_num);
return -EINVAL;
}
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
index 59a8b254b97f..0bd8bcb184a1 100644
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -232,6 +232,11 @@ struct ipath_sdma_desc {
#define IPATH_SDMA_TXREQ_S_ABORTED 2
#define IPATH_SDMA_TXREQ_S_SHUTDOWN 3
+#define IPATH_SDMA_STATUS_SCORE_BOARD_DRAIN_IN_PROG (1ull << 63)
+#define IPATH_SDMA_STATUS_ABORT_IN_PROG (1ull << 62)
+#define IPATH_SDMA_STATUS_INTERNAL_SDMA_ENABLE (1ull << 61)
+#define IPATH_SDMA_STATUS_SCB_EMPTY (1ull << 30)
+
/* max dwords in small buffer packet */
#define IPATH_SMALLBUF_DWORDS (dd->ipath_piosize2k >> 2)
diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c
index 1ff46ae7dd99..5f9315d77a43 100644
--- a/drivers/infiniband/hw/ipath/ipath_mad.c
+++ b/drivers/infiniband/hw/ipath/ipath_mad.c
@@ -1492,6 +1492,10 @@ static int process_subn(struct ib_device *ibdev, int mad_flags,
goto bail;
}
+ case IB_MGMT_METHOD_TRAP:
+ case IB_MGMT_METHOD_REPORT:
+ case IB_MGMT_METHOD_REPORT_RESP:
+ case IB_MGMT_METHOD_TRAP_REPRESS:
case IB_MGMT_METHOD_GET_RESP:
/*
* The ib_mad module will call us to process responses
diff --git a/drivers/infiniband/hw/ipath/ipath_sdma.c b/drivers/infiniband/hw/ipath/ipath_sdma.c
index 3697449c1ba4..eaba03273e4f 100644
--- a/drivers/infiniband/hw/ipath/ipath_sdma.c
+++ b/drivers/infiniband/hw/ipath/ipath_sdma.c
@@ -263,14 +263,10 @@ static void sdma_abort_task(unsigned long opaque)
hwstatus = ipath_read_kreg64(dd,
dd->ipath_kregs->kr_senddmastatus);
- if (/* ScoreBoardDrainInProg */
- test_bit(63, &hwstatus) ||
- /* AbortInProg */
- test_bit(62, &hwstatus) ||
- /* InternalSDmaEnable */
- test_bit(61, &hwstatus) ||
- /* ScbEmpty */
- !test_bit(30, &hwstatus)) {
+ if ((hwstatus & (IPATH_SDMA_STATUS_SCORE_BOARD_DRAIN_IN_PROG |
+ IPATH_SDMA_STATUS_ABORT_IN_PROG |
+ IPATH_SDMA_STATUS_INTERNAL_SDMA_ENABLE)) ||
+ !(hwstatus & IPATH_SDMA_STATUS_SCB_EMPTY)) {
if (dd->ipath_sdma_reset_wait > 0) {
/* not done shutting down sdma */
--dd->ipath_sdma_reset_wait;
@@ -345,7 +341,7 @@ resched:
* state change
*/
if (jiffies > dd->ipath_sdma_abort_jiffies) {
- ipath_dbg("looping with status 0x%016llx\n",
+ ipath_dbg("looping with status 0x%08lx\n",
dd->ipath_sdma_status);
dd->ipath_sdma_abort_jiffies = jiffies + 5 * HZ;
}
@@ -615,7 +611,7 @@ void ipath_restart_sdma(struct ipath_devdata *dd)
}
spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
if (!needed) {
- ipath_dbg("invalid attempt to restart SDMA, status 0x%016llx\n",
+ ipath_dbg("invalid attempt to restart SDMA, status 0x%08lx\n",
dd->ipath_sdma_status);
goto bail;
}
diff --git a/drivers/infiniband/hw/ipath/ipath_uc.c b/drivers/infiniband/hw/ipath/ipath_uc.c
index 7fd18e833907..0596ec16fcbd 100644
--- a/drivers/infiniband/hw/ipath/ipath_uc.c
+++ b/drivers/infiniband/hw/ipath/ipath_uc.c
@@ -407,12 +407,11 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
dev->n_pkt_drops++;
goto done;
}
- /* XXX Need to free SGEs */
+ wc.opcode = IB_WC_RECV;
last_imm:
ipath_copy_sge(&qp->r_sge, data, tlen);
wc.wr_id = qp->r_wr_id;
wc.status = IB_WC_SUCCESS;
- wc.opcode = IB_WC_RECV;
wc.qp = &qp->ibqp;
wc.src_qp = qp->remote_qpn;
wc.slid = qp->remote_ah_attr.dlid;
@@ -514,6 +513,7 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
goto done;
}
wc.byte_len = qp->r_len;
+ wc.opcode = IB_WC_RECV_RDMA_WITH_IMM;
goto last_imm;
case OP(RDMA_WRITE_LAST):
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
index e0ec540042bf..7779165b2c2c 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.c
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
@@ -1494,7 +1494,8 @@ static int ipath_query_device(struct ib_device *ibdev,
props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR |
IB_DEVICE_BAD_QKEY_CNTR | IB_DEVICE_SHUTDOWN_PORT |
- IB_DEVICE_SYS_IMAGE_GUID;
+ IB_DEVICE_SYS_IMAGE_GUID | IB_DEVICE_RC_RNR_NAK_GEN |
+ IB_DEVICE_PORT_ACTIVE_EVENT | IB_DEVICE_SRQ_RESIZE;
props->page_size_cap = PAGE_SIZE;
props->vendor_id = dev->dd->ipath_vendorid;
props->vendor_part_id = dev->dd->ipath_deviceid;
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 8e02ecfec188..a80df22deae8 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -333,6 +333,9 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
cap->max_inline_data + sizeof (struct mlx4_wqe_inline_seg)) +
send_wqe_overhead(type, qp->flags);
+ if (s > dev->dev->caps.max_sq_desc_sz)
+ return -EINVAL;
+
/*
* Hermon supports shrinking WQEs, such that a single work
* request can include multiple units of 1 << wqe_shift. This
@@ -372,9 +375,6 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
qp->sq.wqe_shift = ilog2(roundup_pow_of_two(s));
for (;;) {
- if (1 << qp->sq.wqe_shift > dev->dev->caps.max_sq_desc_sz)
- return -EINVAL;
-
qp->sq_max_wqes_per_wr = DIV_ROUND_UP(s, 1U << qp->sq.wqe_shift);
/*
@@ -395,7 +395,8 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
++qp->sq.wqe_shift;
}
- qp->sq.max_gs = ((qp->sq_max_wqes_per_wr << qp->sq.wqe_shift) -
+ qp->sq.max_gs = (min(dev->dev->caps.max_sq_desc_sz,
+ (qp->sq_max_wqes_per_wr << qp->sq.wqe_shift)) -
send_wqe_overhead(type, qp->flags)) /
sizeof (struct mlx4_wqe_data_seg);
@@ -411,7 +412,9 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
cap->max_send_wr = qp->sq.max_post =
(qp->sq.wqe_cnt - qp->sq_spare_wqes) / qp->sq_max_wqes_per_wr;
- cap->max_send_sge = qp->sq.max_gs;
+ cap->max_send_sge = min(qp->sq.max_gs,
+ min(dev->dev->caps.max_sq_sg,
+ dev->dev->caps.max_rq_sg));
/* We don't support inline sends for kernel QPs (yet) */
cap->max_inline_data = 0;
@@ -1457,7 +1460,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
unsigned ind;
int uninitialized_var(stamp);
int uninitialized_var(size);
- unsigned seglen;
+ unsigned uninitialized_var(seglen);
int i;
spin_lock_irqsave(&qp->sq.lock, flags);
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 9ebadd6e0cfb..200cf13fc9bb 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -45,6 +45,7 @@
#include "mthca_cmd.h"
#include "mthca_profile.h"
#include "mthca_memfree.h"
+#include "mthca_wqe.h"
MODULE_AUTHOR("Roland Dreier");
MODULE_DESCRIPTION("Mellanox InfiniBand HCA low-level driver");
@@ -200,7 +201,18 @@ static int mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim *dev_lim)
mdev->limits.gid_table_len = dev_lim->max_gids;
mdev->limits.pkey_table_len = dev_lim->max_pkeys;
mdev->limits.local_ca_ack_delay = dev_lim->local_ca_ack_delay;
- mdev->limits.max_sg = dev_lim->max_sg;
+ /*
+ * Need to allow for worst case send WQE overhead and check
+ * whether max_desc_sz imposes a lower limit than max_sg; UD
+ * send has the biggest overhead.
+ */
+ mdev->limits.max_sg = min_t(int, dev_lim->max_sg,
+ (dev_lim->max_desc_sz -
+ sizeof (struct mthca_next_seg) -
+ (mthca_is_memfree(mdev) ?
+ sizeof (struct mthca_arbel_ud_seg) :
+ sizeof (struct mthca_tavor_ud_seg))) /
+ sizeof (struct mthca_data_seg));
mdev->limits.max_wqes = dev_lim->max_qp_sz;
mdev->limits.max_qp_init_rdma = dev_lim->max_requester_per_qp;
mdev->limits.reserved_qps = dev_lim->reserved_qps;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index d00a2c174aee..3f663fb852c1 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -194,7 +194,13 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
/* Set the cached Q_Key before we attach if it's the broadcast group */
if (!memcmp(mcast->mcmember.mgid.raw, priv->dev->broadcast + 4,
sizeof (union ib_gid))) {
+ spin_lock_irq(&priv->lock);
+ if (!priv->broadcast) {
+ spin_unlock_irq(&priv->lock);
+ return -EAGAIN;
+ }
priv->qkey = be32_to_cpu(priv->broadcast->mcmember.qkey);
+ spin_unlock_irq(&priv->lock);
priv->tx_wr.wr.ud.remote_qkey = priv->qkey;
}
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 4a95adc4cc78..af58a6f1e898 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -807,6 +807,8 @@ static int atkbd_activate(struct atkbd *atkbd)
static void atkbd_cleanup(struct serio *serio)
{
struct atkbd *atkbd = serio_get_drvdata(serio);
+
+ atkbd_disable(atkbd);
ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_BAT);
}
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index 3dea0c5077a9..45767e73f071 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -136,6 +136,9 @@ static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad)
set_bit(code, input_dev->keybit);
}
+ for (i = 0; i < pdata->direct_key_num; i++)
+ set_bit(pdata->direct_key_map[i], input_dev->keybit);
+
keypad->rotary_up_key[0] = pdata->rotary0_up_key;
keypad->rotary_up_key[1] = pdata->rotary1_up_key;
keypad->rotary_down_key[0] = pdata->rotary0_down_key;
@@ -143,17 +146,21 @@ static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad)
keypad->rotary_rel_code[0] = pdata->rotary0_rel_code;
keypad->rotary_rel_code[1] = pdata->rotary1_rel_code;
- if (pdata->rotary0_up_key && pdata->rotary0_down_key) {
- set_bit(pdata->rotary0_up_key, input_dev->keybit);
- set_bit(pdata->rotary0_down_key, input_dev->keybit);
- } else
- set_bit(pdata->rotary0_rel_code, input_dev->relbit);
-
- if (pdata->rotary1_up_key && pdata->rotary1_down_key) {
- set_bit(pdata->rotary1_up_key, input_dev->keybit);
- set_bit(pdata->rotary1_down_key, input_dev->keybit);
- } else
- set_bit(pdata->rotary1_rel_code, input_dev->relbit);
+ if (pdata->enable_rotary0) {
+ if (pdata->rotary0_up_key && pdata->rotary0_down_key) {
+ set_bit(pdata->rotary0_up_key, input_dev->keybit);
+ set_bit(pdata->rotary0_down_key, input_dev->keybit);
+ } else
+ set_bit(pdata->rotary0_rel_code, input_dev->relbit);
+ }
+
+ if (pdata->enable_rotary1) {
+ if (pdata->rotary1_up_key && pdata->rotary1_down_key) {
+ set_bit(pdata->rotary1_up_key, input_dev->keybit);
+ set_bit(pdata->rotary1_down_key, input_dev->keybit);
+ } else
+ set_bit(pdata->rotary1_rel_code, input_dev->relbit);
+ }
}
static inline unsigned int lookup_matrix_keycode(
@@ -484,8 +491,13 @@ static int __devinit pxa27x_keypad_probe(struct platform_device *pdev)
keypad->input_dev = input_dev;
input_set_drvdata(input_dev, keypad);
- input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
- BIT_MASK(EV_REL);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
+ if ((keypad->pdata->enable_rotary0 &&
+ keypad->pdata->rotary0_rel_code) ||
+ (keypad->pdata->enable_rotary1 &&
+ keypad->pdata->rotary1_rel_code)) {
+ input_dev->evbit[0] |= BIT_MASK(EV_REL);
+ }
pxa27x_keypad_build_keycode(keypad);
platform_set_drvdata(pdev, keypad);
diff --git a/drivers/input/misc/apanel.c b/drivers/input/misc/apanel.c
index 9531d8c7444f..d82f7f727f7a 100644
--- a/drivers/input/misc/apanel.c
+++ b/drivers/input/misc/apanel.c
@@ -20,7 +20,6 @@
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/io.h>
-#include <linux/module.h>
#include <linux/input-polldev.h>
#include <linux/i2c.h>
#include <linux/workqueue.h>
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 5ece9f56babc..9aafa96cb746 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -331,6 +331,13 @@ static struct dmi_system_id __initdata i8042_dmi_dritek_table[] = {
},
},
{
+ .ident = "Acer TravelMate 660",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 660"),
+ },
+ },
+ {
.ident = "Acer TravelMate 2490",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 65a74cfc187b..592ff55b62d0 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -885,6 +885,20 @@ static long i8042_panic_blink(long count)
#undef DELAY
+#ifdef CONFIG_X86
+static void i8042_dritek_enable(void)
+{
+ char param = 0x90;
+ int error;
+
+ error = i8042_command(&param, 0x1059);
+ if (error)
+ printk(KERN_WARNING
+ "Failed to enable DRITEK extension: %d\n",
+ error);
+}
+#endif
+
#ifdef CONFIG_PM
/*
* Here we try to restore the original BIOS settings. We only want to
@@ -942,6 +956,12 @@ static int i8042_resume(struct platform_device *dev)
return -EIO;
}
+
+#ifdef CONFIG_X86
+ if (i8042_dritek)
+ i8042_dritek_enable();
+#endif
+
if (i8042_mux_present) {
if (i8042_set_mux_mode(1, NULL) || i8042_enable_mux_ports())
printk(KERN_WARNING
@@ -1160,6 +1180,11 @@ static int __devinit i8042_probe(struct platform_device *dev)
if (error)
return error;
+#ifdef CONFIG_X86
+ if (i8042_dritek)
+ i8042_dritek_enable();
+#endif
+
if (!i8042_noaux) {
error = i8042_setup_aux();
if (error && error != -ENODEV && error != -EBUSY)
@@ -1171,14 +1196,6 @@ static int __devinit i8042_probe(struct platform_device *dev)
if (error)
goto out_fail;
}
-#ifdef CONFIG_X86
- if (i8042_dritek) {
- char param = 0x90;
- error = i8042_command(&param, 0x1059);
- if (error)
- goto out_fail;
- }
-#endif
/*
* Ok, everything is ready, let's register all serio ports
*/
diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c
index c5a8661a1baa..1e748e46d12e 100644
--- a/drivers/input/tablet/gtco.c
+++ b/drivers/input/tablet/gtco.c
@@ -830,7 +830,7 @@ static int gtco_probe(struct usb_interface *usbinterface,
struct gtco *gtco;
struct input_dev *input_dev;
struct hid_descriptor *hid_desc;
- char *report = NULL;
+ char *report;
int result = 0, retry;
int error;
struct usb_endpoint_descriptor *endpoint;
@@ -916,12 +916,16 @@ static int gtco_probe(struct usb_interface *usbinterface,
le16_to_cpu(hid_desc->wDescriptorLength),
5000); /* 5 secs */
- if (result == le16_to_cpu(hid_desc->wDescriptorLength))
+ dbg("usb_control_msg result: %d", result);
+ if (result == le16_to_cpu(hid_desc->wDescriptorLength)) {
+ parse_hid_report_descriptor(gtco, report, result);
break;
+ }
}
+ kfree(report);
+
/* If we didn't get the report, fail */
- dbg("usb_control_msg result: :%d", result);
if (result != le16_to_cpu(hid_desc->wDescriptorLength)) {
err("Failed to get HID Report Descriptor of size: %d",
hid_desc->wDescriptorLength);
@@ -929,12 +933,6 @@ static int gtco_probe(struct usb_interface *usbinterface,
goto err_free_urb;
}
- /* Now we parse the report */
- parse_hid_report_descriptor(gtco, report, result);
-
- /* Now we delete it */
- kfree(report);
-
/* Create a device file node */
usb_make_path(gtco->usbdev, gtco->usbpath, sizeof(gtco->usbpath));
strlcat(gtco->usbpath, "/input0", sizeof(gtco->usbpath));
@@ -988,7 +986,6 @@ static int gtco_probe(struct usb_interface *usbinterface,
usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE,
gtco->buffer, gtco->buf_dma);
err_free_devs:
- kfree(report);
input_free_device(input_dev);
kfree(gtco);
return error;
diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c
index 01278bd7e65c..838458792ea0 100644
--- a/drivers/input/touchscreen/wm9713.c
+++ b/drivers/input/touchscreen/wm9713.c
@@ -85,6 +85,15 @@ module_param(delay, int, 0);
MODULE_PARM_DESC(delay, "Set adc sample delay.");
/*
+ * Set five_wire = 1 to use a 5 wire touchscreen.
+ *
+ * NOTE: Five wire mode does not allow for readback of pressure.
+ */
+static int five_wire;
+module_param(five_wire, int, 0);
+MODULE_PARM_DESC(five_wire, "Set to '1' to use 5-wire touchscreen.");
+
+/*
* Set adc mask function.
*
* Sources of glitch noise, such as signals driving an LCD display, may feed
@@ -162,6 +171,19 @@ static void wm9713_phy_init(struct wm97xx *wm)
64000 / rpu);
}
+ /* Five wire panel? */
+ if (five_wire) {
+ dig3 |= WM9713_45W;
+ dev_info(wm->dev, "setting 5-wire touchscreen mode.");
+
+ if (pil) {
+ dev_warn(wm->dev,
+ "Pressure measurement not supported in 5 "
+ "wire mode, disabling\n");
+ pil = 0;
+ }
+ }
+
/* touchpanel pressure */
if (pil == 2) {
dig3 |= WM9712_PIL;
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
index e9c7ea46b6e3..cdc24ad314e0 100644
--- a/drivers/input/touchscreen/wm97xx-core.c
+++ b/drivers/input/touchscreen/wm97xx-core.c
@@ -608,6 +608,17 @@ static int wm97xx_probe(struct device *dev)
goto alloc_err;
}
+ /* set up physical characteristics */
+ wm->codec->phy_init(wm);
+
+ /* load gpio cache */
+ wm->gpio[0] = wm97xx_reg_read(wm, AC97_GPIO_CFG);
+ wm->gpio[1] = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
+ wm->gpio[2] = wm97xx_reg_read(wm, AC97_GPIO_STICKY);
+ wm->gpio[3] = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP);
+ wm->gpio[4] = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
+ wm->gpio[5] = wm97xx_reg_read(wm, AC97_MISC_AFE);
+
wm->input_dev = input_allocate_device();
if (wm->input_dev == NULL) {
ret = -ENOMEM;
@@ -616,6 +627,7 @@ static int wm97xx_probe(struct device *dev)
/* set up touch configuration */
wm->input_dev->name = "wm97xx touchscreen";
+ wm->input_dev->phys = "wm97xx";
wm->input_dev->open = wm97xx_ts_input_open;
wm->input_dev->close = wm97xx_ts_input_close;
set_bit(EV_ABS, wm->input_dev->evbit);
@@ -634,17 +646,6 @@ static int wm97xx_probe(struct device *dev)
if (ret < 0)
goto dev_alloc_err;
- /* set up physical characteristics */
- wm->codec->phy_init(wm);
-
- /* load gpio cache */
- wm->gpio[0] = wm97xx_reg_read(wm, AC97_GPIO_CFG);
- wm->gpio[1] = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
- wm->gpio[2] = wm97xx_reg_read(wm, AC97_GPIO_STICKY);
- wm->gpio[3] = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP);
- wm->gpio[4] = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
- wm->gpio[5] = wm97xx_reg_read(wm, AC97_MISC_AFE);
-
/* register our battery device */
wm->battery_dev = platform_device_alloc("wm97xx-battery", -1);
if (!wm->battery_dev) {
@@ -801,7 +802,7 @@ void wm97xx_unregister_mach_ops(struct wm97xx *wm)
EXPORT_SYMBOL_GPL(wm97xx_unregister_mach_ops);
static struct device_driver wm97xx_driver = {
- .name = "ac97",
+ .name = "wm97xx-ts",
.bus = &ac97_bus_type,
.owner = THIS_MODULE,
.probe = wm97xx_probe,
diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c
index d3999a8e9f88..53f6ad1235db 100644
--- a/drivers/isdn/hysdn/hycapi.c
+++ b/drivers/isdn/hysdn/hycapi.c
@@ -462,11 +462,11 @@ static int hycapi_read_proc(char *page, char **start, off_t off,
default: s = "???"; break;
}
len += sprintf(page+len, "%-16s %s\n", "type", s);
- if ((s = cinfo->version[VER_DRIVER]) != 0)
+ if ((s = cinfo->version[VER_DRIVER]) != NULL)
len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
- if ((s = cinfo->version[VER_CARDTYPE]) != 0)
+ if ((s = cinfo->version[VER_CARDTYPE]) != NULL)
len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
- if ((s = cinfo->version[VER_SERIAL]) != 0)
+ if ((s = cinfo->version[VER_SERIAL]) != NULL)
len += sprintf(page+len, "%-16s %s\n", "ver_serial", s);
len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname);
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
index 8080249957af..1a8de57289eb 100644
--- a/drivers/lguest/lguest_device.c
+++ b/drivers/lguest/lguest_device.c
@@ -20,14 +20,11 @@
/* The pointer to our (page) of device descriptions. */
static void *lguest_devices;
-/* Unique numbering for lguest devices. */
-static unsigned int dev_index;
-
/* For Guests, device memory can be used as normal memory, so we cast away the
* __iomem to quieten sparse. */
static inline void *lguest_map(unsigned long phys_addr, unsigned long pages)
{
- return (__force void *)ioremap(phys_addr, PAGE_SIZE*pages);
+ return (__force void *)ioremap_cache(phys_addr, PAGE_SIZE*pages);
}
static inline void lguest_unmap(void *addr)
@@ -325,8 +322,10 @@ static struct device lguest_root = {
* As Andrew Tridgell says, "Untested code is buggy code".
*
* It's worth reading this carefully: we start with a pointer to the new device
- * descriptor in the "lguest_devices" page. */
-static void add_lguest_device(struct lguest_device_desc *d)
+ * descriptor in the "lguest_devices" page, and the offset into the device
+ * descriptor page so we can uniquely identify it if things go badly wrong. */
+static void add_lguest_device(struct lguest_device_desc *d,
+ unsigned int offset)
{
struct lguest_device *ldev;
@@ -334,18 +333,14 @@ static void add_lguest_device(struct lguest_device_desc *d)
* it. */
ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
if (!ldev) {
- printk(KERN_EMERG "Cannot allocate lguest dev %u\n",
- dev_index++);
+ printk(KERN_EMERG "Cannot allocate lguest dev %u type %u\n",
+ offset, d->type);
return;
}
/* This devices' parent is the lguest/ dir. */
ldev->vdev.dev.parent = &lguest_root;
/* We have a unique device index thanks to the dev_index counter. */
- ldev->vdev.index = dev_index++;
- /* The device type comes straight from the descriptor. There's also a
- * device vendor field in the virtio_device struct, which we leave as
- * 0. */
ldev->vdev.id.device = d->type;
/* We have a simple set of routines for querying the device's
* configuration information and setting its status. */
@@ -357,8 +352,8 @@ static void add_lguest_device(struct lguest_device_desc *d)
* virtio_device and calls device_register(). This makes the bus
* infrastructure look for a matching driver. */
if (register_virtio_device(&ldev->vdev) != 0) {
- printk(KERN_ERR "Failed to register lguest device %u\n",
- ldev->vdev.index);
+ printk(KERN_ERR "Failed to register lguest dev %u type %u\n",
+ offset, d->type);
kfree(ldev);
}
}
@@ -379,7 +374,7 @@ static void scan_devices(void)
break;
printk("Device at %i has size %u\n", i, desc_size(d));
- add_lguest_device(d);
+ add_lguest_device(d, i);
}
}
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index c14dacdacfac..b26927ce889c 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -203,17 +203,6 @@ static void bitmap_checkfree(struct bitmap *bitmap, unsigned long page)
* bitmap file handling - read and write the bitmap file and its superblock
*/
-/* copy the pathname of a file to a buffer */
-char *file_path(struct file *file, char *buf, int count)
-{
- if (!buf)
- return NULL;
-
- buf = d_path(&file->f_path, buf, count);
-
- return IS_ERR(buf) ? NULL : buf;
-}
-
/*
* basic page I/O operations
*/
@@ -721,11 +710,13 @@ static void bitmap_file_kick(struct bitmap *bitmap)
if (bitmap->file) {
path = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (path)
- ptr = file_path(bitmap->file, path, PAGE_SIZE);
+ ptr = d_path(&bitmap->file->f_path, path,
+ PAGE_SIZE);
+
printk(KERN_ALERT
"%s: kicking failed bitmap file %s from array!\n",
- bmname(bitmap), ptr ? ptr : "");
+ bmname(bitmap), IS_ERR(ptr) ? "" : ptr);
kfree(path);
} else
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 83eb78b00137..7cf512a34ccf 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -74,6 +74,8 @@ static DEFINE_SPINLOCK(pers_lock);
static void md_print_devices(void);
+static DECLARE_WAIT_QUEUE_HEAD(resync_wait);
+
#define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); }
/*
@@ -274,6 +276,7 @@ static mddev_t * mddev_find(dev_t unit)
atomic_set(&new->active, 1);
spin_lock_init(&new->write_lock);
init_waitqueue_head(&new->sb_wait);
+ init_waitqueue_head(&new->recovery_wait);
new->reshape_position = MaxSector;
new->resync_max = MaxSector;
new->level = LEVEL_NONE;
@@ -3013,6 +3016,36 @@ degraded_show(mddev_t *mddev, char *page)
static struct md_sysfs_entry md_degraded = __ATTR_RO(degraded);
static ssize_t
+sync_force_parallel_show(mddev_t *mddev, char *page)
+{
+ return sprintf(page, "%d\n", mddev->parallel_resync);
+}
+
+static ssize_t
+sync_force_parallel_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ long n;
+
+ if (strict_strtol(buf, 10, &n))
+ return -EINVAL;
+
+ if (n != 0 && n != 1)
+ return -EINVAL;
+
+ mddev->parallel_resync = n;
+
+ if (mddev->sync_thread)
+ wake_up(&resync_wait);
+
+ return len;
+}
+
+/* force parallel resync, even with shared block devices */
+static struct md_sysfs_entry md_sync_force_parallel =
+__ATTR(sync_force_parallel, S_IRUGO|S_IWUSR,
+ sync_force_parallel_show, sync_force_parallel_store);
+
+static ssize_t
sync_speed_show(mddev_t *mddev, char *page)
{
unsigned long resync, dt, db;
@@ -3187,6 +3220,7 @@ static struct attribute *md_redundancy_attrs[] = {
&md_sync_min.attr,
&md_sync_max.attr,
&md_sync_speed.attr,
+ &md_sync_force_parallel.attr,
&md_sync_completed.attr,
&md_max_sync.attr,
&md_suspend_lo.attr,
@@ -3691,6 +3725,8 @@ static int do_md_stop(mddev_t * mddev, int mode)
module_put(mddev->pers->owner);
mddev->pers = NULL;
+ /* tell userspace to handle 'inactive' */
+ sysfs_notify(&mddev->kobj, NULL, "array_state");
set_capacity(disk, 0);
mddev->changed = 1;
@@ -3987,8 +4023,8 @@ static int get_bitmap_file(mddev_t * mddev, void __user * arg)
if (!buf)
goto out;
- ptr = file_path(mddev->bitmap->file, buf, sizeof(file->pathname));
- if (!ptr)
+ ptr = d_path(&mddev->bitmap->file->f_path, buf, sizeof(file->pathname));
+ if (IS_ERR(ptr))
goto out;
strcpy(file->pathname, ptr);
@@ -5399,7 +5435,7 @@ void md_done_sync(mddev_t *mddev, int blocks, int ok)
atomic_sub(blocks, &mddev->recovery_active);
wake_up(&mddev->recovery_wait);
if (!ok) {
- set_bit(MD_RECOVERY_ERR, &mddev->recovery);
+ set_bit(MD_RECOVERY_INTR, &mddev->recovery);
md_wakeup_thread(mddev->thread);
// stop recovery, signal do_sync ....
}
@@ -5435,8 +5471,11 @@ void md_write_start(mddev_t *mddev, struct bio *bi)
md_wakeup_thread(mddev->thread);
}
spin_unlock_irq(&mddev->write_lock);
+ sysfs_notify(&mddev->kobj, NULL, "array_state");
}
- wait_event(mddev->sb_wait, mddev->flags==0);
+ wait_event(mddev->sb_wait,
+ !test_bit(MD_CHANGE_CLEAN, &mddev->flags) &&
+ !test_bit(MD_CHANGE_PENDING, &mddev->flags));
}
void md_write_end(mddev_t *mddev)
@@ -5471,13 +5510,17 @@ void md_allow_write(mddev_t *mddev)
mddev->safemode = 1;
spin_unlock_irq(&mddev->write_lock);
md_update_sb(mddev, 0);
+
+ sysfs_notify(&mddev->kobj, NULL, "array_state");
+ /* wait for the dirty state to be recorded in the metadata */
+ wait_event(mddev->sb_wait,
+ !test_bit(MD_CHANGE_CLEAN, &mddev->flags) &&
+ !test_bit(MD_CHANGE_PENDING, &mddev->flags));
} else
spin_unlock_irq(&mddev->write_lock);
}
EXPORT_SYMBOL_GPL(md_allow_write);
-static DECLARE_WAIT_QUEUE_HEAD(resync_wait);
-
#define SYNC_MARKS 10
#define SYNC_MARK_STEP (3*HZ)
void md_do_sync(mddev_t *mddev)
@@ -5541,8 +5584,9 @@ void md_do_sync(mddev_t *mddev)
for_each_mddev(mddev2, tmp) {
if (mddev2 == mddev)
continue;
- if (mddev2->curr_resync &&
- match_mddev_units(mddev,mddev2)) {
+ if (!mddev->parallel_resync
+ && mddev2->curr_resync
+ && match_mddev_units(mddev, mddev2)) {
DEFINE_WAIT(wq);
if (mddev < mddev2 && mddev->curr_resync == 2) {
/* arbitrarily yield */
@@ -5622,7 +5666,6 @@ void md_do_sync(mddev_t *mddev)
window/2,(unsigned long long) max_sectors/2);
atomic_set(&mddev->recovery_active, 0);
- init_waitqueue_head(&mddev->recovery_wait);
last_check = 0;
if (j>2) {
@@ -5647,7 +5690,7 @@ void md_do_sync(mddev_t *mddev)
sectors = mddev->pers->sync_request(mddev, j, &skipped,
currspeed < speed_min(mddev));
if (sectors == 0) {
- set_bit(MD_RECOVERY_ERR, &mddev->recovery);
+ set_bit(MD_RECOVERY_INTR, &mddev->recovery);
goto out;
}
@@ -5670,8 +5713,7 @@ void md_do_sync(mddev_t *mddev)
last_check = io_sectors;
- if (test_bit(MD_RECOVERY_INTR, &mddev->recovery) ||
- test_bit(MD_RECOVERY_ERR, &mddev->recovery))
+ if (test_bit(MD_RECOVERY_INTR, &mddev->recovery))
break;
repeat:
@@ -5725,8 +5767,7 @@ void md_do_sync(mddev_t *mddev)
/* tell personality that we are finished */
mddev->pers->sync_request(mddev, max_sectors, &skipped, 1);
- if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) &&
- !test_bit(MD_RECOVERY_CHECK, &mddev->recovery) &&
+ if (!test_bit(MD_RECOVERY_CHECK, &mddev->recovery) &&
mddev->curr_resync > 2) {
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
@@ -5795,7 +5836,10 @@ static int remove_and_add_spares(mddev_t *mddev)
}
if (mddev->degraded) {
- rdev_for_each(rdev, rtmp, mddev)
+ rdev_for_each(rdev, rtmp, mddev) {
+ if (rdev->raid_disk >= 0 &&
+ !test_bit(In_sync, &rdev->flags))
+ spares++;
if (rdev->raid_disk < 0
&& !test_bit(Faulty, &rdev->flags)) {
rdev->recovery_offset = 0;
@@ -5813,6 +5857,7 @@ static int remove_and_add_spares(mddev_t *mddev)
} else
break;
}
+ }
}
return spares;
}
@@ -5826,7 +5871,7 @@ static int remove_and_add_spares(mddev_t *mddev)
* to do that as needed.
* When it is determined that resync is needed, we set MD_RECOVERY_RUNNING in
* "->recovery" and create a thread at ->sync_thread.
- * When the thread finishes it sets MD_RECOVERY_DONE (and might set MD_RECOVERY_ERR)
+ * When the thread finishes it sets MD_RECOVERY_DONE
* and wakeups up this thread which will reap the thread and finish up.
* This thread also removes any faulty devices (with nr_pending == 0).
*
@@ -5901,8 +5946,7 @@ void md_check_recovery(mddev_t *mddev)
/* resync has finished, collect result */
md_unregister_thread(mddev->sync_thread);
mddev->sync_thread = NULL;
- if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) &&
- !test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
+ if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
/* success...*/
/* activate any spares */
mddev->pers->spare_active(mddev);
@@ -5926,7 +5970,6 @@ void md_check_recovery(mddev_t *mddev)
* might be left set
*/
clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
- clear_bit(MD_RECOVERY_ERR, &mddev->recovery);
clear_bit(MD_RECOVERY_INTR, &mddev->recovery);
clear_bit(MD_RECOVERY_DONE, &mddev->recovery);
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 4f4d1f383842..e968116e0de9 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -327,7 +327,8 @@ static int multipath_remove_disk(mddev_t *mddev, int number)
if (rdev) {
if (test_bit(In_sync, &rdev->flags) ||
atomic_read(&rdev->nr_pending)) {
- printk(KERN_ERR "hot-remove-disk, slot %d is identified" " but is still operational!\n", number);
+ printk(KERN_ERR "hot-remove-disk, slot %d is identified"
+ " but is still operational!\n", number);
err = -EBUSY;
goto abort;
}
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index ac409b7d83f5..c610b947218a 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -773,7 +773,7 @@ static int make_request(struct request_queue *q, struct bio * bio)
r1bio_t *r1_bio;
struct bio *read_bio;
int i, targets = 0, disks;
- struct bitmap *bitmap = mddev->bitmap;
+ struct bitmap *bitmap;
unsigned long flags;
struct bio_list bl;
struct page **behind_pages = NULL;
@@ -802,6 +802,8 @@ static int make_request(struct request_queue *q, struct bio * bio)
wait_barrier(conf);
+ bitmap = mddev->bitmap;
+
disk_stat_inc(mddev->gendisk, ios[rw]);
disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio));
@@ -1025,7 +1027,7 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
/*
* if recovery is running, make sure it aborts.
*/
- set_bit(MD_RECOVERY_ERR, &mddev->recovery);
+ set_bit(MD_RECOVERY_INTR, &mddev->recovery);
} else
set_bit(Faulty, &rdev->flags);
set_bit(MD_CHANGE_DEVS, &mddev->flags);
@@ -1146,6 +1148,14 @@ static int raid1_remove_disk(mddev_t *mddev, int number)
err = -EBUSY;
goto abort;
}
+ /* Only remove non-faulty devices is recovery
+ * is not possible.
+ */
+ if (!test_bit(Faulty, &rdev->flags) &&
+ mddev->degraded < conf->raid_disks) {
+ err = -EBUSY;
+ goto abort;
+ }
p->rdev = NULL;
synchronize_rcu();
if (atomic_read(&rdev->nr_pending)) {
@@ -1282,6 +1292,7 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
rdev_dec_pending(conf->mirrors[i].rdev, mddev);
} else {
/* fixup the bio for reuse */
+ int size;
sbio->bi_vcnt = vcnt;
sbio->bi_size = r1_bio->sectors << 9;
sbio->bi_idx = 0;
@@ -1295,10 +1306,20 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
sbio->bi_sector = r1_bio->sector +
conf->mirrors[i].rdev->data_offset;
sbio->bi_bdev = conf->mirrors[i].rdev->bdev;
- for (j = 0; j < vcnt ; j++)
- memcpy(page_address(sbio->bi_io_vec[j].bv_page),
+ size = sbio->bi_size;
+ for (j = 0; j < vcnt ; j++) {
+ struct bio_vec *bi;
+ bi = &sbio->bi_io_vec[j];
+ bi->bv_offset = 0;
+ if (size > PAGE_SIZE)
+ bi->bv_len = PAGE_SIZE;
+ else
+ bi->bv_len = size;
+ size -= PAGE_SIZE;
+ memcpy(page_address(bi->bv_page),
page_address(pbio->bi_io_vec[j].bv_page),
PAGE_SIZE);
+ }
}
}
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 8536ede1e712..1de17da34a95 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1020,7 +1020,7 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
/*
* if recovery is running, make sure it aborts.
*/
- set_bit(MD_RECOVERY_ERR, &mddev->recovery);
+ set_bit(MD_RECOVERY_INTR, &mddev->recovery);
}
set_bit(Faulty, &rdev->flags);
set_bit(MD_CHANGE_DEVS, &mddev->flags);
@@ -1171,6 +1171,14 @@ static int raid10_remove_disk(mddev_t *mddev, int number)
err = -EBUSY;
goto abort;
}
+ /* Only remove faulty devices in recovery
+ * is not possible.
+ */
+ if (!test_bit(Faulty, &rdev->flags) &&
+ enough(conf)) {
+ err = -EBUSY;
+ goto abort;
+ }
p->rdev = NULL;
synchronize_rcu();
if (atomic_read(&rdev->nr_pending)) {
@@ -1237,6 +1245,7 @@ static void end_sync_write(struct bio *bio, int error)
if (!uptodate)
md_error(mddev, conf->mirrors[d].rdev);
+
update_head_pos(i, r10_bio);
while (atomic_dec_and_test(&r10_bio->remaining)) {
@@ -1844,7 +1853,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
if (rb2)
atomic_dec(&rb2->remaining);
r10_bio = rb2;
- if (!test_and_set_bit(MD_RECOVERY_ERR, &mddev->recovery))
+ if (!test_and_set_bit(MD_RECOVERY_INTR,
+ &mddev->recovery))
printk(KERN_INFO "raid10: %s: insufficient working devices for recovery.\n",
mdname(mddev));
break;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 93fde48c0f42..c37e256b1176 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -94,6 +94,8 @@
#define __inline__
#endif
+#define printk_rl(args...) ((void) (printk_ratelimit() && printk(args)))
+
#if !RAID6_USE_EMPTY_ZERO_PAGE
/* In .bss so it's zeroed */
const char raid6_empty_zero_page[PAGE_SIZE] __attribute__((aligned(256)));
@@ -1143,10 +1145,12 @@ static void raid5_end_read_request(struct bio * bi, int error)
set_bit(R5_UPTODATE, &sh->dev[i].flags);
if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
rdev = conf->disks[i].rdev;
- printk(KERN_INFO "raid5:%s: read error corrected (%lu sectors at %llu on %s)\n",
- mdname(conf->mddev), STRIPE_SECTORS,
- (unsigned long long)(sh->sector + rdev->data_offset),
- bdevname(rdev->bdev, b));
+ printk_rl(KERN_INFO "raid5:%s: read error corrected"
+ " (%lu sectors at %llu on %s)\n",
+ mdname(conf->mddev), STRIPE_SECTORS,
+ (unsigned long long)(sh->sector
+ + rdev->data_offset),
+ bdevname(rdev->bdev, b));
clear_bit(R5_ReadError, &sh->dev[i].flags);
clear_bit(R5_ReWrite, &sh->dev[i].flags);
}
@@ -1160,16 +1164,22 @@ static void raid5_end_read_request(struct bio * bi, int error)
clear_bit(R5_UPTODATE, &sh->dev[i].flags);
atomic_inc(&rdev->read_errors);
if (conf->mddev->degraded)
- printk(KERN_WARNING "raid5:%s: read error not correctable (sector %llu on %s).\n",
- mdname(conf->mddev),
- (unsigned long long)(sh->sector + rdev->data_offset),
- bdn);
+ printk_rl(KERN_WARNING
+ "raid5:%s: read error not correctable "
+ "(sector %llu on %s).\n",
+ mdname(conf->mddev),
+ (unsigned long long)(sh->sector
+ + rdev->data_offset),
+ bdn);
else if (test_bit(R5_ReWrite, &sh->dev[i].flags))
/* Oh, no!!! */
- printk(KERN_WARNING "raid5:%s: read error NOT corrected!! (sector %llu on %s).\n",
- mdname(conf->mddev),
- (unsigned long long)(sh->sector + rdev->data_offset),
- bdn);
+ printk_rl(KERN_WARNING
+ "raid5:%s: read error NOT corrected!! "
+ "(sector %llu on %s).\n",
+ mdname(conf->mddev),
+ (unsigned long long)(sh->sector
+ + rdev->data_offset),
+ bdn);
else if (atomic_read(&rdev->read_errors)
> conf->max_nr_stripes)
printk(KERN_WARNING
@@ -1258,7 +1268,7 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
/*
* if recovery was running, make sure it aborts.
*/
- set_bit(MD_RECOVERY_ERR, &mddev->recovery);
+ set_bit(MD_RECOVERY_INTR, &mddev->recovery);
}
set_bit(Faulty, &rdev->flags);
printk (KERN_ALERT
@@ -1992,6 +2002,7 @@ static int __handle_issuing_new_read_requests5(struct stripe_head *sh,
* have quiesced.
*/
if ((s->uptodate == disks - 1) &&
+ (s->failed && disk_idx == s->failed_num) &&
!test_bit(STRIPE_OP_CHECK, &sh->ops.pending)) {
set_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
set_bit(R5_Wantcompute, &dev->flags);
@@ -2077,7 +2088,9 @@ static void handle_issuing_new_read_requests6(struct stripe_head *sh,
/* we would like to get this block, possibly
* by computing it, but we might not be able to
*/
- if (s->uptodate == disks-1) {
+ if ((s->uptodate == disks - 1) &&
+ (s->failed && (i == r6s->failed_num[0] ||
+ i == r6s->failed_num[1]))) {
pr_debug("Computing stripe %llu block %d\n",
(unsigned long long)sh->sector, i);
compute_block_1(sh, i, 0);
@@ -2635,6 +2648,7 @@ static void handle_stripe5(struct stripe_head *sh)
struct r5dev *dev;
unsigned long pending = 0;
mdk_rdev_t *blocked_rdev = NULL;
+ int prexor;
memset(&s, 0, sizeof(s));
pr_debug("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d "
@@ -2764,9 +2778,11 @@ static void handle_stripe5(struct stripe_head *sh)
/* leave prexor set until postxor is done, allows us to distinguish
* a rmw from a rcw during biodrain
*/
+ prexor = 0;
if (test_bit(STRIPE_OP_PREXOR, &sh->ops.complete) &&
test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete)) {
+ prexor = 1;
clear_bit(STRIPE_OP_PREXOR, &sh->ops.complete);
clear_bit(STRIPE_OP_PREXOR, &sh->ops.ack);
clear_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
@@ -2800,6 +2816,8 @@ static void handle_stripe5(struct stripe_head *sh)
if (!test_and_set_bit(
STRIPE_OP_IO, &sh->ops.pending))
sh->ops.count++;
+ if (prexor)
+ continue;
if (!test_bit(R5_Insync, &dev->flags) ||
(i == sh->pd_idx && s.failed == 0))
set_bit(STRIPE_INSYNC, &sh->state);
@@ -4564,6 +4582,14 @@ static int raid5_remove_disk(mddev_t *mddev, int number)
err = -EBUSY;
goto abort;
}
+ /* Only remove non-faulty devices if recovery
+ * isn't possible.
+ */
+ if (!test_bit(Faulty, &rdev->flags) &&
+ mddev->degraded <= conf->max_degraded) {
+ err = -EBUSY;
+ goto abort;
+ }
p->rdev = NULL;
synchronize_rcu();
if (atomic_read(&rdev->nr_pending)) {
diff --git a/drivers/media/Makefile b/drivers/media/Makefile
index cc11c4c0e7e7..09a829d8a7e7 100644
--- a/drivers/media/Makefile
+++ b/drivers/media/Makefile
@@ -2,12 +2,7 @@
# Makefile for the kernel multimedia device drivers.
#
-obj-y := common/
-
-obj-$(CONFIG_VIDEO_MEDIA) += common/
-
-# Since hybrid devices are here, should be compiled if DVB and/or V4L
-obj-$(CONFIG_VIDEO_MEDIA) += video/
+obj-y += common/ video/
obj-$(CONFIG_VIDEO_DEV) += radio/
obj-$(CONFIG_DVB_CORE) += dvb/
diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig
index d6206540476b..85482960d012 100644
--- a/drivers/media/common/tuners/Kconfig
+++ b/drivers/media/common/tuners/Kconfig
@@ -21,6 +21,7 @@ config MEDIA_TUNER
tristate
default VIDEO_MEDIA && I2C
depends on VIDEO_MEDIA && I2C
+ select FW_LOADER if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG
select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG
select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMIZE
diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c
index 5d05b5390f66..0dc2bef9f6a3 100644
--- a/drivers/media/common/tuners/mxl5005s.c
+++ b/drivers/media/common/tuners/mxl5005s.c
@@ -101,7 +101,7 @@ enum {
MXL_QAM,
MXL_ANALOG_CABLE,
MXL_ANALOG_OTA
-} tuner_modu_type;
+};
/* MXL5005 Tuner Register Struct */
struct TunerReg {
@@ -194,7 +194,7 @@ enum {
RFSYN_DIVM, /* 88 */
DN_BYPASS_AGC_I2C /* 89 */
#endif
-} MXL5005_ControlName;
+};
/*
* The following context is source code provided by MaxLinear.
diff --git a/drivers/media/common/tuners/tda18271-common.c b/drivers/media/common/tuners/tda18271-common.c
index 42b5f5d4bfe6..f1894fec32b9 100644
--- a/drivers/media/common/tuners/tda18271-common.c
+++ b/drivers/media/common/tuners/tda18271-common.c
@@ -648,11 +648,11 @@ int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq)
unsigned char *regs = priv->tda18271_regs;
u8 val;
- tda18271_lookup_map(fe, RF_CAL, freq, &val);
+ int ret = tda18271_lookup_map(fe, RF_CAL, freq, &val);
regs[R_EB14] = val;
- return 0;
+ return ret;
}
/*
diff --git a/drivers/media/common/tuners/tda827x.c b/drivers/media/common/tuners/tda827x.c
index d30d2c9094d9..8555d9cf9051 100644
--- a/drivers/media/common/tuners/tda827x.c
+++ b/drivers/media/common/tuners/tda827x.c
@@ -418,13 +418,13 @@ static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
unsigned char buf[] = {0x22, 0x01};
int arg;
int gp_func;
- struct i2c_msg msg = { .addr = priv->cfg->switch_addr, .flags = 0,
- .buf = buf, .len = sizeof(buf) };
+ struct i2c_msg msg = { .flags = 0, .buf = buf, .len = sizeof(buf) };
if (NULL == priv->cfg) {
dprintk("tda827x_config not defined, cannot set LNA gain!\n");
return;
}
+ msg.addr = priv->cfg->switch_addr;
if (priv->cfg->config) {
if (high)
dprintk("setting LNA to high gain\n");
diff --git a/drivers/media/common/tuners/tea5761.c b/drivers/media/common/tuners/tea5761.c
index b93cdef9ac73..b23dadeecd05 100644
--- a/drivers/media/common/tuners/tea5761.c
+++ b/drivers/media/common/tuners/tea5761.c
@@ -295,7 +295,7 @@ struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
{
struct tea5761_priv *priv = NULL;
- if (tea5761_autodetection(i2c_adap, i2c_addr) == EINVAL)
+ if (tea5761_autodetection(i2c_adap, i2c_addr) != 0)
return NULL;
priv = kzalloc(sizeof(struct tea5761_priv), GFP_KERNEL);
diff --git a/drivers/media/common/tuners/tuner-i2c.h b/drivers/media/common/tuners/tuner-i2c.h
index 3ad6c8e0b04c..cb1c7141f0c6 100644
--- a/drivers/media/common/tuners/tuner-i2c.h
+++ b/drivers/media/common/tuners/tuner-i2c.h
@@ -170,4 +170,12 @@ __fail: \
__ret; \
})
+#define hybrid_tuner_report_instance_count(state) \
+({ \
+ int __ret = 0; \
+ if (state) \
+ __ret = state->i2c_props.count; \
+ __ret; \
+})
+
#endif /* __TUNER_I2C_H__ */
diff --git a/drivers/media/common/tuners/tuner-simple.c b/drivers/media/common/tuners/tuner-simple.c
index be8d903171b7..266c255cf0d8 100644
--- a/drivers/media/common/tuners/tuner-simple.c
+++ b/drivers/media/common/tuners/tuner-simple.c
@@ -1018,8 +1018,10 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
fe->ops.i2c_gate_ctrl(fe, 1);
if (1 != i2c_transfer(i2c_adap, &msg, 1))
- tuner_warn("unable to probe %s, proceeding anyway.",
- tuners[type].name);
+ printk(KERN_WARNING "tuner-simple %d-%04x: "
+ "unable to probe %s, proceeding anyway.",
+ i2c_adapter_id(i2c_adap), i2c_addr,
+ tuners[type].name);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c
index 9e9003cffc7f..0cbde17bfbb7 100644
--- a/drivers/media/common/tuners/tuner-xc2028.c
+++ b/drivers/media/common/tuners/tuner-xc2028.c
@@ -46,7 +46,7 @@ module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0);
MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the "
"default firmware name\n");
-static LIST_HEAD(xc2028_list);
+static LIST_HEAD(hybrid_tuner_instance_list);
static DEFINE_MUTEX(xc2028_list_mutex);
/* struct for storing firmware table */
@@ -68,12 +68,11 @@ struct firmware_properties {
};
struct xc2028_data {
- struct list_head xc2028_list;
+ struct list_head hybrid_tuner_instance_list;
struct tuner_i2c_props i2c_props;
int (*tuner_callback) (void *dev,
int command, int arg);
void *video_dev;
- int count;
__u32 frequency;
struct firmware_description *firm;
@@ -1072,20 +1071,19 @@ static int xc2028_dvb_release(struct dvb_frontend *fe)
mutex_lock(&xc2028_list_mutex);
- priv->count--;
-
- if (!priv->count) {
- list_del(&priv->xc2028_list);
-
+ /* only perform final cleanup if this is the last instance */
+ if (hybrid_tuner_report_instance_count(priv) == 1) {
kfree(priv->ctrl.fname);
-
free_firmware(priv);
- kfree(priv);
- fe->tuner_priv = NULL;
}
+ if (priv)
+ hybrid_tuner_release_state(priv);
+
mutex_unlock(&xc2028_list_mutex);
+ fe->tuner_priv = NULL;
+
return 0;
}
@@ -1150,7 +1148,7 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
struct xc2028_config *cfg)
{
struct xc2028_data *priv;
- void *video_dev;
+ int instance;
if (debug)
printk(KERN_DEBUG "xc2028: Xcv2028/3028 init called!\n");
@@ -1163,48 +1161,40 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
return NULL;
}
- video_dev = cfg->i2c_adap->algo_data;
-
- if (debug)
- printk(KERN_DEBUG "xc2028: video_dev =%p\n", video_dev);
-
mutex_lock(&xc2028_list_mutex);
- list_for_each_entry(priv, &xc2028_list, xc2028_list) {
- if (&priv->i2c_props.adap->dev == &cfg->i2c_adap->dev) {
- video_dev = NULL;
- if (debug)
- printk(KERN_DEBUG "xc2028: reusing device\n");
-
- break;
- }
- }
-
- if (video_dev) {
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (priv == NULL) {
- mutex_unlock(&xc2028_list_mutex);
- return NULL;
- }
-
- priv->i2c_props.addr = cfg->i2c_addr;
- priv->i2c_props.adap = cfg->i2c_adap;
- priv->i2c_props.name = "xc2028";
-
- priv->video_dev = video_dev;
+ instance = hybrid_tuner_request_state(struct xc2028_data, priv,
+ hybrid_tuner_instance_list,
+ cfg->i2c_adap, cfg->i2c_addr,
+ "xc2028");
+ switch (instance) {
+ case 0:
+ /* memory allocation failure */
+ goto fail;
+ break;
+ case 1:
+ /* new tuner instance */
priv->tuner_callback = cfg->callback;
priv->ctrl.max_len = 13;
mutex_init(&priv->lock);
- list_add_tail(&priv->xc2028_list, &xc2028_list);
- }
-
- fe->tuner_priv = priv;
- priv->count++;
+ /* analog side (tuner-core) uses i2c_adap->algo_data.
+ * digital side is not guaranteed to have algo_data defined.
+ *
+ * digital side will always have fe->dvb defined.
+ * analog side (tuner-core) doesn't (yet) define fe->dvb.
+ */
+ priv->video_dev = ((fe->dvb) && (fe->dvb->priv)) ?
+ fe->dvb->priv : cfg->i2c_adap->algo_data;
- if (debug)
- printk(KERN_DEBUG "xc2028: usage count is %i\n", priv->count);
+ fe->tuner_priv = priv;
+ break;
+ case 2:
+ /* existing tuner instance */
+ fe->tuner_priv = priv;
+ break;
+ }
memcpy(&fe->ops.tuner_ops, &xc2028_dvb_tuner_ops,
sizeof(xc2028_dvb_tuner_ops));
@@ -1217,6 +1207,11 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
mutex_unlock(&xc2028_list_mutex);
return fe;
+fail:
+ mutex_unlock(&xc2028_list_mutex);
+
+ xc2028_dvb_release(fe);
+ return NULL;
}
EXPORT_SYMBOL(xc2028_attach);
diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c
index 449fb5c3d0b1..ae0d76a5d51d 100644
--- a/drivers/media/dvb/b2c2/flexcop-usb.c
+++ b/drivers/media/dvb/b2c2/flexcop-usb.c
@@ -379,7 +379,7 @@ static void flexcop_usb_transfer_exit(struct flexcop_usb *fc_usb)
static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb)
{
- u16 frame_size = fc_usb->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize;
+ u16 frame_size = le16_to_cpu(fc_usb->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize);
int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO * frame_size,i,j,ret;
int buffer_offset = 0;
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index f5010e8671b8..a824f3719f81 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -82,22 +82,22 @@ enum cinergyt2_ep1_cmd {
struct dvbt_set_parameters_msg {
uint8_t cmd;
- uint32_t freq;
+ __le32 freq;
uint8_t bandwidth;
- uint16_t tps;
+ __le16 tps;
uint8_t flags;
} __attribute__((packed));
struct dvbt_get_status_msg {
- uint32_t freq;
+ __le32 freq;
uint8_t bandwidth;
- uint16_t tps;
+ __le16 tps;
uint8_t flags;
- uint16_t gain;
+ __le16 gain;
uint8_t snr;
- uint32_t viterbi_error_rate;
- uint32_t rs_error_rate;
- uint32_t uncorrected_block_count;
+ __le32 viterbi_error_rate;
+ __le32 rs_error_rate;
+ __le32 uncorrected_block_count;
uint8_t lock_bits;
uint8_t prev_lock_bits;
} __attribute__((packed));
@@ -136,6 +136,7 @@ struct cinergyt2 {
wait_queue_head_t poll_wq;
int pending_fe_events;
int disconnect_pending;
+ unsigned int uncorrected_block_count;
atomic_t inuse;
void *streambuf;
@@ -147,7 +148,7 @@ struct cinergyt2 {
char phys[64];
struct delayed_work rc_query_work;
int rc_input_event;
- u32 rc_last_code;
+ __le32 rc_last_code;
unsigned long last_event_jiffies;
#endif
};
@@ -160,7 +161,7 @@ enum {
struct cinergyt2_rc_event {
char type;
- uint32_t value;
+ __le32 value;
} __attribute__((packed));
static const uint32_t rc_keys[] = {
@@ -619,8 +620,11 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file,
{
uint32_t unc_count;
- unc_count = stat->uncorrected_block_count;
- stat->uncorrected_block_count = 0;
+ if (mutex_lock_interruptible(&cinergyt2->sem))
+ return -ERESTARTSYS;
+ unc_count = cinergyt2->uncorrected_block_count;
+ cinergyt2->uncorrected_block_count = 0;
+ mutex_unlock(&cinergyt2->sem);
/* UNC are already converted to host byte order... */
return put_user(unc_count,(__u32 __user *) arg);
@@ -769,7 +773,7 @@ static void cinergyt2_query_rc (struct work_struct *work)
input_sync(cinergyt2->rc_input_dev);
cinergyt2->rc_input_event = KEY_MAX;
}
- cinergyt2->rc_last_code = ~0;
+ cinergyt2->rc_last_code = cpu_to_le32(~0);
}
goto out;
}
@@ -780,7 +784,7 @@ static void cinergyt2_query_rc (struct work_struct *work)
n, le32_to_cpu(rc_events[n].value), rc_events[n].type);
if (rc_events[n].type == CINERGYT2_RC_EVENT_TYPE_NEC &&
- rc_events[n].value == ~0) {
+ rc_events[n].value == cpu_to_le32(~0)) {
/* keyrepeat bit -> just repeat last rc_input_event */
} else {
cinergyt2->rc_input_event = KEY_MAX;
@@ -795,7 +799,7 @@ static void cinergyt2_query_rc (struct work_struct *work)
if (cinergyt2->rc_input_event != KEY_MAX) {
if (rc_events[n].value == cinergyt2->rc_last_code &&
- cinergyt2->rc_last_code != ~0) {
+ cinergyt2->rc_last_code != cpu_to_le32(~0)) {
/* emit a key-up so the double event is recognized */
dprintk(1, "rc_input_event=%d UP\n", cinergyt2->rc_input_event);
input_report_key(cinergyt2->rc_input_dev,
@@ -829,7 +833,7 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
usb_make_path(cinergyt2->udev, cinergyt2->phys, sizeof(cinergyt2->phys));
strlcat(cinergyt2->phys, "/input0", sizeof(cinergyt2->phys));
cinergyt2->rc_input_event = KEY_MAX;
- cinergyt2->rc_last_code = ~0;
+ cinergyt2->rc_last_code = cpu_to_le32(~0);
INIT_DELAYED_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc);
input_dev->name = DRIVER_NAME " remote control";
@@ -840,8 +844,8 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
input_dev->keycodesize = 0;
input_dev->keycodemax = 0;
input_dev->id.bustype = BUS_USB;
- input_dev->id.vendor = cinergyt2->udev->descriptor.idVendor;
- input_dev->id.product = cinergyt2->udev->descriptor.idProduct;
+ input_dev->id.vendor = le16_to_cpu(cinergyt2->udev->descriptor.idVendor);
+ input_dev->id.product = le16_to_cpu(cinergyt2->udev->descriptor.idProduct);
input_dev->id.version = 1;
input_dev->dev.parent = &cinergyt2->udev->dev;
@@ -889,18 +893,16 @@ static void cinergyt2_query (struct work_struct *work)
char cmd [] = { CINERGYT2_EP1_GET_TUNER_STATUS };
struct dvbt_get_status_msg *s = &cinergyt2->status;
uint8_t lock_bits;
- uint32_t unc;
if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
return;
- unc = s->uncorrected_block_count;
lock_bits = s->lock_bits;
cinergyt2_command(cinergyt2, cmd, sizeof(cmd), (char *) s, sizeof(*s));
- unc += le32_to_cpu(s->uncorrected_block_count);
- s->uncorrected_block_count = unc;
+ cinergyt2->uncorrected_block_count +=
+ le32_to_cpu(s->uncorrected_block_count);
if (lock_bits != s->lock_bits) {
wake_up_interruptible(&cinergyt2->poll_wq);
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 56d871cfd7fc..c2334aef4143 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -168,7 +168,7 @@ struct dvb_net_priv {
* stolen from eth.c out of the linux kernel, hacked for dvb-device
* by Michael Holzt <kju@debian.org>
*/
-static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb,
+static __be16 dvb_net_eth_type_trans(struct sk_buff *skb,
struct net_device *dev)
{
struct ethhdr *eth;
@@ -277,10 +277,10 @@ static int handle_one_ule_extension( struct dvb_net_priv *p )
if(ext_len >= 0) {
p->ule_next_hdr += ext_len;
if (!p->ule_bridged) {
- p->ule_sndu_type = ntohs(*(unsigned short *)p->ule_next_hdr);
+ p->ule_sndu_type = ntohs(*(__be16 *)p->ule_next_hdr);
p->ule_next_hdr += 2;
} else {
- p->ule_sndu_type = ntohs(*(unsigned short *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)));
+ p->ule_sndu_type = ntohs(*(__be16 *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)));
/* This assures the extension handling loop will terminate. */
}
}
@@ -294,7 +294,7 @@ static int handle_one_ule_extension( struct dvb_net_priv *p )
if (ule_optional_ext_handlers[htype])
(void)ule_optional_ext_handlers[htype]( p );
p->ule_next_hdr += ext_len;
- p->ule_sndu_type = ntohs( *(unsigned short *)(p->ule_next_hdr-2) );
+ p->ule_sndu_type = ntohs( *(__be16 *)(p->ule_next_hdr-2) );
/*
* note: the length of the next header type is included in the
* length of THIS optional extension header
@@ -594,8 +594,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
/* Check for complete payload. */
if (priv->ule_sndu_remain <= 0) {
/* Check CRC32, we've got it in our skb already. */
- unsigned short ulen = htons(priv->ule_sndu_len);
- unsigned short utype = htons(priv->ule_sndu_type);
+ __be16 ulen = htons(priv->ule_sndu_len);
+ __be16 utype = htons(priv->ule_sndu_type);
const u8 *tail;
struct kvec iov[3] = {
{ &ulen, sizeof ulen },
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index cf4584e48b6d..f00a0eb40420 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -1,6 +1,6 @@
config DVB_USB
tristate "Support for various USB DVB devices"
- depends on DVB_CORE && USB && I2C
+ depends on DVB_CORE && USB && I2C && INPUT
depends on HOTPLUG # due to FW_LOADER
select FW_LOADER
help
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index 346223856f59..c4d40fe01d57 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -111,8 +111,8 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
struct i2c_adapter *tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1);
s8 a;
int if1=1220;
- if (adap->dev->udev->descriptor.idVendor == USB_VID_HAUPPAUGE &&
- adap->dev->udev->descriptor.idProduct == USB_PID_HAUPPAUGE_NOVA_T_500_2) {
+ if (adap->dev->udev->descriptor.idVendor == cpu_to_le16(USB_VID_HAUPPAUGE) &&
+ adap->dev->udev->descriptor.idProduct == cpu_to_le16(USB_PID_HAUPPAUGE_NOVA_T_500_2)) {
if (!eeprom_read(prim_i2c,0x59 + adap->id,&a)) if1=1220+a;
}
return dvb_attach(mt2060_attach,adap->fe, tun_i2c,&bristol_mt2060_config[adap->id],
@@ -402,8 +402,8 @@ static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap)
{
struct usb_device_descriptor *desc = &adap->dev->udev->descriptor;
- if (desc->idVendor == USB_VID_PINNACLE &&
- desc->idProduct == USB_PID_PINNACLE_EXPRESSCARD_320CX)
+ if (desc->idVendor == cpu_to_le16(USB_VID_PINNACLE) &&
+ desc->idProduct == cpu_to_le16(USB_PID_PINNACLE_EXPRESSCARD_320CX))
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
else
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
@@ -845,8 +845,8 @@ static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap)
struct i2c_adapter *tun_i2c;
s8 a;
int if1=1220;
- if (adap->dev->udev->descriptor.idVendor == USB_VID_HAUPPAUGE &&
- adap->dev->udev->descriptor.idProduct == USB_PID_HAUPPAUGE_NOVA_T_STICK) {
+ if (adap->dev->udev->descriptor.idVendor == cpu_to_le16(USB_VID_HAUPPAUGE) &&
+ adap->dev->udev->descriptor.idProduct == cpu_to_le16(USB_PID_HAUPPAUGE_NOVA_T_STICK)) {
if (!eeprom_read(prim_i2c,0x58,&a)) if1=1220+a;
}
if (st->is_dib7000pc)
@@ -990,11 +990,12 @@ static struct dib7000p_config dib7070p_dib7000p_config = {
/* STK7070P */
static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
{
- if (adap->dev->udev->descriptor.idVendor == USB_VID_PINNACLE &&
- adap->dev->udev->descriptor.idProduct == USB_PID_PINNACLE_PCTV72E)
- dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
+ struct usb_device_descriptor *p = &adap->dev->udev->descriptor;
+ if (p->idVendor == cpu_to_le16(USB_VID_PINNACLE) &&
+ p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E))
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
else
- dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
msleep(10);
dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
index e1112e39fb63..733a7ff7b207 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
@@ -127,7 +127,7 @@ int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx,
if ((*pos + hx->len + 4) >= fw->size)
return -EINVAL;
- hx->addr = le16_to_cpu( *((u16 *) &b[1]) );
+ hx->addr = b[1] | (b[2] << 8);
hx->type = b[3];
if (hx->type == 0x04) {
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c
index 9a942afaf0af..2653120673b7 100644
--- a/drivers/media/dvb/dvb-usb/gp8psk.c
+++ b/drivers/media/dvb/dvb-usb/gp8psk.c
@@ -146,24 +146,24 @@ static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
if (! (status & bm8pskFW_Loaded)) /* BCM4500 firmware loaded */
if(gp8psk_load_bcm4500fw(d))
- return EINVAL;
+ return -EINVAL;
if (! (status & bmIntersilOn)) /* LNB Power */
if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0,
&buf, 1))
- return EINVAL;
+ return -EINVAL;
/* Set DVB mode to 1 */
if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
if (gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0))
- return EINVAL;
+ return -EINVAL;
/* Abort possible TS (if previous tune crashed) */
if (gp8psk_usb_out_op(d, ARM_TRANSFER, 0, 0, NULL, 0))
- return EINVAL;
+ return -EINVAL;
} else {
/* Turn off LNB power */
if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1))
- return EINVAL;
+ return -EINVAL;
/* Turn off 8psk power */
if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
return -EINVAL;
diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c
index a12e6f784fda..54626a0dbf68 100644
--- a/drivers/media/dvb/dvb-usb/m920x.c
+++ b/drivers/media/dvb/dvb-usb/m920x.c
@@ -16,6 +16,7 @@
#include "qt1010.h"
#include "tda1004x.h"
#include "tda827x.h"
+#include <asm/unaligned.h>
/* debug */
static int dvb_usb_m920x_debug;
@@ -347,13 +348,13 @@ static int m920x_firmware_download(struct usb_device *udev, const struct firmwar
for (pass = 0; pass < 2; pass++) {
for (i = 0; i + (sizeof(u16) * 3) < fw->size;) {
- value = le16_to_cpu(*(u16 *)(fw->data + i));
+ value = get_unaligned_le16(fw->data + i);
i += sizeof(u16);
- index = le16_to_cpu(*(u16 *)(fw->data + i));
+ index = get_unaligned_le16(fw->data + i);
i += sizeof(u16);
- size = le16_to_cpu(*(u16 *)(fw->data + i));
+ size = get_unaligned_le16(fw->data + i);
i += sizeof(u16);
if (pass == 1) {
diff --git a/drivers/media/dvb/frontends/dib0070.h b/drivers/media/dvb/frontends/dib0070.h
index 786e37d33889..3eedfdf505bc 100644
--- a/drivers/media/dvb/frontends/dib0070.h
+++ b/drivers/media/dvb/frontends/dib0070.h
@@ -37,7 +37,20 @@ struct dib0070_config {
u8 flip_chip;
};
-extern struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg);
+#if defined(CONFIG_DVB_TUNER_DIB0070) || (defined(CONFIG_DVB_TUNER_DIB0070_MODULE) && defined(MODULE))
+extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct dib0070_config *cfg);
+#else
+static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct dib0070_config *cfg)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif
+
extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, uint8_t open);
extern u16 dib0070_wbd_offset(struct dvb_frontend *);
diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h
index 081bd81f3da2..07c4d12ed5b7 100644
--- a/drivers/media/dvb/frontends/dib7000p.h
+++ b/drivers/media/dvb/frontends/dib7000p.h
@@ -37,7 +37,20 @@ struct dib7000p_config {
#define DEFAULT_DIB7000P_I2C_ADDRESS 18
-extern struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
+#if defined(CONFIG_DVB_DIB7000P) || (defined(CONFIG_DVB_DIB7000P_MODULE) && defined(MODULE))
+extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap,
+ u8 i2c_addr,
+ struct dib7000p_config *cfg);
+#else
+static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap,
+ u8 i2c_addr,
+ struct dib7000p_config *cfg)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif
+
extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c
index c7b5785f81f2..5ed32544de39 100644
--- a/drivers/media/dvb/frontends/or51132.c
+++ b/drivers/media/dvb/frontends/or51132.c
@@ -126,7 +126,7 @@ static int or51132_readreg(struct or51132_state *state, u8 reg)
reg, err);
return -EREMOTEIO;
}
- return le16_to_cpup((u16*)buf);
+ return buf[0] | (buf[1] << 8);
}
static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
@@ -140,9 +140,9 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware
dprintk("Firmware is %Zd bytes\n",fw->size);
/* Get size of firmware A and B */
- firmwareAsize = le32_to_cpu(*((u32*)fw->data));
+ firmwareAsize = le32_to_cpu(*((__le32*)fw->data));
dprintk("FirmwareA is %i bytes\n",firmwareAsize);
- firmwareBsize = le32_to_cpu(*((u32*)(fw->data+4)));
+ firmwareBsize = le32_to_cpu(*((__le32*)(fw->data+4)));
dprintk("FirmwareB is %i bytes\n",firmwareBsize);
/* Upload firmware */
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 747e7f1a6267..f05d43d8b5cf 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -51,6 +51,7 @@
#include <linux/crc32.h>
#include <linux/i2c.h>
#include <linux/kthread.h>
+#include <asm/unaligned.h>
#include <asm/system.h>
@@ -1461,9 +1462,9 @@ static int check_firmware(struct av7110* av7110)
ptr += 4;
/* check dpram file */
- crc = ntohl(*(u32*) ptr);
+ crc = get_unaligned_be32(ptr);
ptr += 4;
- len = ntohl(*(u32*) ptr);
+ len = get_unaligned_be32(ptr);
ptr += 4;
if (len >= 512) {
printk("dvb-ttpci: dpram file is way too big.\n");
@@ -1478,9 +1479,9 @@ static int check_firmware(struct av7110* av7110)
ptr += len;
/* check root file */
- crc = ntohl(*(u32*) ptr);
+ crc = get_unaligned_be32(ptr);
ptr += 4;
- len = ntohl(*(u32*) ptr);
+ len = get_unaligned_be32(ptr);
ptr += 4;
if (len <= 200000 || len >= 300000 ||
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
index 3e6b650fbb81..ec55a968f204 100644
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ b/drivers/media/dvb/ttpci/av7110_av.c
@@ -965,8 +965,9 @@ static u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x
static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len, int nonblock)
{
- int i, n;
+ unsigned i, n;
int progressive = 0;
+ int match = 0;
dprintk(2, "av7110:%p, \n", av7110);
@@ -975,12 +976,31 @@ static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len
return -EBUSY;
}
- for (i = 0; i < len - 5; i++) {
- /* get progressive flag from picture extension */
- if (buf[i] == 0x00 && buf[i+1] == 0x00 &&
- buf[i+2] == 0x01 && (unsigned char)buf[i+3] == 0xb5 &&
- (buf[i+4] & 0xf0) == 0x10)
- progressive = buf[i+5] & 0x08;
+ /* search in buf for instances of 00 00 01 b5 1? */
+ for (i = 0; i < len; i++) {
+ unsigned char c;
+ if (get_user(c, buf + i))
+ return -EFAULT;
+ if (match == 5) {
+ progressive = c & 0x08;
+ match = 0;
+ }
+ if (c == 0x00) {
+ match = (match == 1 || match == 2) ? 2 : 1;
+ continue;
+ }
+ switch (match++) {
+ case 2: if (c == 0x01)
+ continue;
+ break;
+ case 3: if (c == 0xb5)
+ continue;
+ break;
+ case 4: if ((c & 0xf0) == 0x10)
+ continue;
+ break;
+ }
+ match = 0;
}
/* setting n always > 1, fixes problems when playing stillframes
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index 732ce4de512e..5d2d81ab2371 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -552,7 +552,7 @@ static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
u16 csum = 0, cc;
int i;
for (i = 0; i < len; i += 2)
- csum ^= le16_to_cpup((u16 *) (muxpack + i));
+ csum ^= le16_to_cpup((__le16 *) (muxpack + i));
if (csum) {
printk("%s: muxpack with incorrect checksum, ignoring\n",
__func__);
diff --git a/drivers/media/dvb/ttusb-dec/Kconfig b/drivers/media/dvb/ttusb-dec/Kconfig
index 0712899e39a4..a23cc0aa17d3 100644
--- a/drivers/media/dvb/ttusb-dec/Kconfig
+++ b/drivers/media/dvb/ttusb-dec/Kconfig
@@ -1,6 +1,6 @@
config DVB_TTUSB_DEC
tristate "Technotrend/Hauppauge USB DEC devices"
- depends on DVB_CORE && USB
+ depends on DVB_CORE && USB && INPUT
depends on HOTPLUG # due to FW_LOADER
select FW_LOADER
select CRC32
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index 42eee04daa5d..fefdc05e84ac 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -343,7 +343,7 @@ static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode,
u8 c[COMMAND_PACKET_SIZE];
int c_length;
int result;
- unsigned int tmp;
+ __be32 tmp;
dprintk("%s\n", __func__);
@@ -398,9 +398,9 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec)
0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff };
- u16 pcr = htons(dec->pid[DMX_PES_PCR]);
- u16 audio = htons(dec->pid[DMX_PES_AUDIO]);
- u16 video = htons(dec->pid[DMX_PES_VIDEO]);
+ __be16 pcr = htons(dec->pid[DMX_PES_PCR]);
+ __be16 audio = htons(dec->pid[DMX_PES_AUDIO]);
+ __be16 video = htons(dec->pid[DMX_PES_VIDEO]);
dprintk("%s\n", __func__);
@@ -435,7 +435,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
case 0x01: { /* VideoStream */
int prebytes = pva[5] & 0x03;
int postbytes = (pva[5] & 0x0c) >> 2;
- u16 v_pes_payload_length;
+ __be16 v_pes_payload_length;
if (output_pva) {
dec->video_filter->feed->cb.ts(pva, length, NULL, 0,
@@ -1006,7 +1006,7 @@ static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00 };
- u16 pid;
+ __be16 pid;
u8 c[COMMAND_PACKET_SIZE];
int c_length;
int result;
@@ -1278,9 +1278,10 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
u8 *firmware = NULL;
size_t firmware_size = 0;
u16 firmware_csum = 0;
- u16 firmware_csum_ns;
- u32 firmware_size_nl;
- u32 crc32_csum, crc32_check, tmp;
+ __be16 firmware_csum_ns;
+ __be32 firmware_size_nl;
+ u32 crc32_csum, crc32_check;
+ __be32 tmp;
const struct firmware *fw_entry = NULL;
dprintk("%s\n", __func__);
@@ -1306,7 +1307,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
valid. */
crc32_csum = crc32(~0L, firmware, 56) ^ ~0L;
memcpy(&tmp, &firmware[56], 4);
- crc32_check = htonl(tmp);
+ crc32_check = ntohl(tmp);
if (crc32_csum != crc32_check) {
printk("%s: crc32 check of DSP code failed (calculated "
"0x%08x != 0x%08x in file), file invalid.\n",
@@ -1627,7 +1628,7 @@ static int ttusb_dec_probe(struct usb_interface *intf,
usb_set_intfdata(intf, (void *)dec);
- switch (le16_to_cpu(id->idProduct)) {
+ switch (id->idProduct) {
case 0x1006:
ttusb_dec_set_model(dec, TTUSB_DEC3000S);
break;
@@ -1652,7 +1653,7 @@ static int ttusb_dec_probe(struct usb_interface *intf,
ttusb_dec_init_dvb(dec);
dec->adapter.priv = dec;
- switch (le16_to_cpu(id->idProduct)) {
+ switch (id->idProduct) {
case 0x1006:
dec->fe = ttusbdecfe_dvbs_attach(&fe_config);
break;
diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
index eb5eaeccd7c4..443af24097f3 100644
--- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
+++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
@@ -86,7 +86,7 @@ static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend* fe, struct dvb_fron
0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0xff };
- u32 freq = htonl(p->frequency / 1000);
+ __be32 freq = htonl(p->frequency / 1000);
memcpy(&b[4], &freq, sizeof (u32));
state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL);
@@ -117,10 +117,10 @@ static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend* fe, struct dvb_fron
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
- u32 freq;
- u32 sym_rate;
- u32 band;
- u32 lnb_voltage;
+ __be32 freq;
+ __be32 sym_rate;
+ __be32 band;
+ __be32 lnb_voltage;
freq = htonl(p->frequency +
(state->hi_band ? LOF_HI : LOF_LO));
diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig
index def10d086373..52b2491581a8 100644
--- a/drivers/media/video/au0828/Kconfig
+++ b/drivers/media/video/au0828/Kconfig
@@ -1,7 +1,7 @@
config VIDEO_AU0828
tristate "Auvitek AU0828 support"
- depends on VIDEO_DEV && I2C && INPUT && DVB_CORE && USB
+ depends on I2C && INPUT && DVB_CORE && USB
select I2C_ALGOBIT
select VIDEO_TVEEPROM
select DVB_AU8522 if !DVB_FE_CUSTOMIZE
diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c
index c86a5f17eca8..c6d470590380 100644
--- a/drivers/media/video/au0828/au0828-dvb.c
+++ b/drivers/media/video/au0828/au0828-dvb.c
@@ -353,12 +353,6 @@ int au0828_dvb_register(struct au0828_dev *dev)
return -1;
}
- /* Put the analog decoder in standby to keep it quiet */
- au0828_call_i2c_clients(dev, TUNER_SET_STANDBY, NULL);
-
- if (dvb->frontend->ops.analog_ops.standby)
- dvb->frontend->ops.analog_ops.standby(dvb->frontend);
-
/* register everything */
ret = dvb_register(dev);
if (ret < 0) {
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c
index f20a01cfc73e..8ef0424c26c4 100644
--- a/drivers/media/video/bt8xx/bttv-cards.c
+++ b/drivers/media/video/bt8xx/bttv-cards.c
@@ -34,6 +34,7 @@
#include <linux/firmware.h>
#include <net/checksum.h>
+#include <asm/unaligned.h>
#include <asm/io.h>
#include "bttvp.h"
@@ -3858,7 +3859,7 @@ static void __devinit osprey_eeprom(struct bttv *btv, const u8 ee[256])
ee += i;
/* found a valid descriptor */
- type = be16_to_cpup((u16*)(ee+4));
+ type = get_unaligned_be16((__be16 *)(ee+4));
switch(type) {
/* 848 based */
@@ -3918,7 +3919,7 @@ static void __devinit osprey_eeprom(struct bttv *btv, const u8 ee[256])
btv->c.nr, type);
break;
}
- serial = be32_to_cpup((u32*)(ee+6));
+ serial = get_unaligned_be32((__be32 *)(ee+6));
}
printk(KERN_INFO "bttv%d: osprey eeprom: card=%d '%s' serial=%u\n",
diff --git a/drivers/media/video/bt8xx/bttv-risc.c b/drivers/media/video/bt8xx/bttv-risc.c
index e5979f77504c..0af586876e72 100644
--- a/drivers/media/video/bt8xx/bttv-risc.c
+++ b/drivers/media/video/bt8xx/bttv-risc.c
@@ -48,7 +48,7 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
{
u32 instructions,line,todo;
struct scatterlist *sg;
- u32 *rp;
+ __le32 *rp;
int rc;
/* estimate risc mem: worst case is one write per page border +
@@ -128,7 +128,8 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
unsigned int cpadding)
{
unsigned int instructions,line,todo,ylen,chroma;
- u32 *rp,ri;
+ __le32 *rp;
+ u32 ri;
struct scatterlist *ysg;
struct scatterlist *usg;
struct scatterlist *vsg;
@@ -244,7 +245,8 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
{
int dwords,rc,line,maxy,start,end,skip,nskips;
struct btcx_skiplist *skips;
- u32 *rp,ri,ra;
+ __le32 *rp;
+ u32 ri,ra;
u32 addr;
/* skip list for window clipping */
diff --git a/drivers/media/video/btcx-risc.c b/drivers/media/video/btcx-risc.c
index ce0840ccd594..f42701f82e7f 100644
--- a/drivers/media/video/btcx-risc.c
+++ b/drivers/media/video/btcx-risc.c
@@ -63,7 +63,7 @@ int btcx_riscmem_alloc(struct pci_dev *pci,
struct btcx_riscmem *risc,
unsigned int size)
{
- u32 *cpu;
+ __le32 *cpu;
dma_addr_t dma;
if (NULL != risc->cpu && risc->size < size)
diff --git a/drivers/media/video/btcx-risc.h b/drivers/media/video/btcx-risc.h
index 503e6c6d7b69..861bc8112824 100644
--- a/drivers/media/video/btcx-risc.h
+++ b/drivers/media/video/btcx-risc.h
@@ -2,8 +2,8 @@
*/
struct btcx_riscmem {
unsigned int size;
- u32 *cpu;
- u32 *jmp;
+ __le32 *cpu;
+ __le32 *jmp;
dma_addr_t dma;
};
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c
index 66864904c99b..9a26751615c6 100644
--- a/drivers/media/video/cx18/cx18-av-core.c
+++ b/drivers/media/video/cx18/cx18-av-core.c
@@ -182,14 +182,16 @@ static void input_change(struct cx18 *cx)
if (std == V4L2_STD_NTSC_M_JP) {
/* Japan uses EIAJ audio standard */
cx18_av_write(cx, 0x808, 0xf7);
+ cx18_av_write(cx, 0x80b, 0x02);
} else if (std == V4L2_STD_NTSC_M_KR) {
/* South Korea uses A2 audio standard */
cx18_av_write(cx, 0x808, 0xf8);
+ cx18_av_write(cx, 0x80b, 0x03);
} else {
/* Others use the BTSC audio standard */
cx18_av_write(cx, 0x808, 0xf6);
+ cx18_av_write(cx, 0x80b, 0x01);
}
- cx18_av_write(cx, 0x80b, 0x00);
} else if (std & V4L2_STD_PAL) {
/* Follow tuner change procedure for PAL */
cx18_av_write(cx, 0x808, 0xff);
@@ -741,8 +743,8 @@ static void log_audio_status(struct cx18 *cx)
{
struct cx18_av_state *state = &cx->av_state;
u8 download_ctl = cx18_av_read(cx, 0x803);
- u8 mod_det_stat0 = cx18_av_read(cx, 0x805);
- u8 mod_det_stat1 = cx18_av_read(cx, 0x804);
+ u8 mod_det_stat0 = cx18_av_read(cx, 0x804);
+ u8 mod_det_stat1 = cx18_av_read(cx, 0x805);
u8 audio_config = cx18_av_read(cx, 0x808);
u8 pref_mode = cx18_av_read(cx, 0x809);
u8 afc0 = cx18_av_read(cx, 0x80b);
@@ -760,12 +762,12 @@ static void log_audio_status(struct cx18 *cx)
case 0x12: p = "dual with SAP"; break;
case 0x14: p = "tri with SAP"; break;
case 0xfe: p = "forced mode"; break;
- default: p = "not defined";
+ default: p = "not defined"; break;
}
CX18_INFO("Detected audio mode: %s\n", p);
switch (mod_det_stat1) {
- case 0x00: p = "BTSC"; break;
+ case 0x00: p = "not defined"; break;
case 0x01: p = "EIAJ"; break;
case 0x02: p = "A2-M"; break;
case 0x03: p = "A2-BG"; break;
@@ -779,8 +781,13 @@ static void log_audio_status(struct cx18 *cx)
case 0x0b: p = "NICAM-I"; break;
case 0x0c: p = "NICAM-L"; break;
case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break;
+ case 0x0e: p = "IF FM Radio"; break;
+ case 0x0f: p = "BTSC"; break;
+ case 0x10: p = "detected chrominance"; break;
+ case 0xfd: p = "unknown audio standard"; break;
+ case 0xfe: p = "forced audio standard"; break;
case 0xff: p = "no detected audio standard"; break;
- default: p = "not defined";
+ default: p = "not defined"; break;
}
CX18_INFO("Detected audio standard: %s\n", p);
CX18_INFO("Audio muted: %s\n",
@@ -789,22 +796,23 @@ static void log_audio_status(struct cx18 *cx)
(download_ctl & 0x10) ? "running" : "stopped");
switch (audio_config >> 4) {
- case 0x00: p = "BTSC"; break;
- case 0x01: p = "EIAJ"; break;
- case 0x02: p = "A2-M"; break;
- case 0x03: p = "A2-BG"; break;
- case 0x04: p = "A2-DK1"; break;
- case 0x05: p = "A2-DK2"; break;
- case 0x06: p = "A2-DK3"; break;
- case 0x07: p = "A1 (6.0 MHz FM Mono)"; break;
- case 0x08: p = "AM-L"; break;
- case 0x09: p = "NICAM-BG"; break;
- case 0x0a: p = "NICAM-DK"; break;
- case 0x0b: p = "NICAM-I"; break;
- case 0x0c: p = "NICAM-L"; break;
- case 0x0d: p = "FM radio"; break;
+ case 0x00: p = "undefined"; break;
+ case 0x01: p = "BTSC"; break;
+ case 0x02: p = "EIAJ"; break;
+ case 0x03: p = "A2-M"; break;
+ case 0x04: p = "A2-BG"; break;
+ case 0x05: p = "A2-DK1"; break;
+ case 0x06: p = "A2-DK2"; break;
+ case 0x07: p = "A2-DK3"; break;
+ case 0x08: p = "A1 (6.0 MHz FM Mono)"; break;
+ case 0x09: p = "AM-L"; break;
+ case 0x0a: p = "NICAM-BG"; break;
+ case 0x0b: p = "NICAM-DK"; break;
+ case 0x0c: p = "NICAM-I"; break;
+ case 0x0d: p = "NICAM-L"; break;
+ case 0x0e: p = "FM radio"; break;
case 0x0f: p = "automatic detection"; break;
- default: p = "undefined";
+ default: p = "undefined"; break;
}
CX18_INFO("Configured audio standard: %s\n", p);
@@ -815,12 +823,9 @@ static void log_audio_status(struct cx18 *cx)
case 0x02: p = "MONO3 (STEREO forced MONO)"; break;
case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break;
case 0x04: p = "STEREO"; break;
- case 0x05: p = "DUAL1 (AB)"; break;
- case 0x06: p = "DUAL2 (AC) (FM)"; break;
- case 0x07: p = "DUAL3 (BC) (FM)"; break;
- case 0x08: p = "DUAL4 (AC) (AM)"; break;
- case 0x09: p = "DUAL5 (BC) (AM)"; break;
- case 0x0a: p = "SAP"; break;
+ case 0x05: p = "DUAL1 (AC)"; break;
+ case 0x06: p = "DUAL2 (BC)"; break;
+ case 0x07: p = "DUAL3 (AB)"; break;
default: p = "undefined";
}
CX18_INFO("Configured audio mode: %s\n", p);
@@ -835,9 +840,11 @@ static void log_audio_status(struct cx18 *cx)
case 0x06: p = "BTSC"; break;
case 0x07: p = "EIAJ"; break;
case 0x08: p = "A2-M"; break;
- case 0x09: p = "FM Radio"; break;
+ case 0x09: p = "FM Radio (4.5 MHz)"; break;
+ case 0x0a: p = "FM Radio (5.5 MHz)"; break;
+ case 0x0b: p = "S-Video"; break;
case 0x0f: p = "automatic standard and mode detection"; break;
- default: p = "undefined";
+ default: p = "undefined"; break;
}
CX18_INFO("Configured audio system: %s\n", p);
}
@@ -857,22 +864,24 @@ static void log_audio_status(struct cx18 *cx)
case 5: p = "language AC"; break;
case 6: p = "language BC"; break;
case 7: p = "language AB"; break;
- default: p = "undefined";
+ default: p = "undefined"; break;
}
CX18_INFO("Preferred audio mode: %s\n", p);
if ((audio_config & 0xf) == 0xf) {
- switch ((afc0 >> 2) & 0x1) {
+ switch ((afc0 >> 3) & 0x1) {
case 0: p = "system DK"; break;
case 1: p = "system L"; break;
}
CX18_INFO("Selected 65 MHz format: %s\n", p);
- switch (afc0 & 0x3) {
- case 0: p = "BTSC"; break;
- case 1: p = "EIAJ"; break;
- case 2: p = "A2-M"; break;
- default: p = "undefined";
+ switch (afc0 & 0x7) {
+ case 0: p = "Chroma"; break;
+ case 1: p = "BTSC"; break;
+ case 2: p = "EIAJ"; break;
+ case 3: p = "A2-M"; break;
+ case 4: p = "autodetect"; break;
+ default: p = "undefined"; break;
}
CX18_INFO("Selected 45 MHz format: %s\n", p);
}
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c
index 553adbf2cd44..baccd079243d 100644
--- a/drivers/media/video/cx18/cx18-cards.c
+++ b/drivers/media/video/cx18/cx18-cards.c
@@ -126,7 +126,7 @@ static const struct cx18_card cx18_card_hvr1600_samsung = {
/* ------------------------------------------------------------------------- */
-/* Compro VideoMate H900: not working at the moment! */
+/* Compro VideoMate H900: note that this card is analog only! */
static const struct cx18_card_pci_info cx18_pci_h900[] = {
{ PCI_DEVICE_ID_CX23418, CX18_PCI_ID_COMPRO, 0xe100 },
@@ -136,7 +136,7 @@ static const struct cx18_card_pci_info cx18_pci_h900[] = {
static const struct cx18_card cx18_card_h900 = {
.type = CX18_CARD_COMPRO_H900,
.name = "Compro VideoMate H900",
- .comment = "DVB & VBI are not yet supported\n",
+ .comment = "VBI is not yet supported\n",
.v4l2_capabilities = CX18_CAP_ENCODER,
.hw_audio_ctrl = CX18_HW_CX23418,
.hw_all = CX18_HW_TUNER,
diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c
index 2bdac5ebbb0d..87cf41021665 100644
--- a/drivers/media/video/cx18/cx18-controls.c
+++ b/drivers/media/video/cx18/cx18-controls.c
@@ -159,7 +159,7 @@ static int cx18_setup_vbi_fmt(struct cx18 *cx, enum v4l2_mpeg_stream_vbi_fmt fmt
{
if (!(cx->v4l2_cap & V4L2_CAP_SLICED_VBI_CAPTURE))
return -EINVAL;
- if (atomic_read(&cx->capturing) > 0)
+ if (atomic_read(&cx->ana_capturing) > 0)
return -EBUSY;
/* First try to allocate sliced VBI buffers if needed. */
@@ -235,7 +235,7 @@ int cx18_control_ioctls(struct cx18 *cx, unsigned int cmd, void *arg)
CX18_DEBUG_IOCTL("VIDIOC_S_EXT_CTRLS\n");
if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
struct cx2341x_mpeg_params p = cx->params;
- int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->capturing), arg, cmd);
+ int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->ana_capturing), arg, cmd);
if (err)
return err;
@@ -295,7 +295,7 @@ int cx18_control_ioctls(struct cx18 *cx, unsigned int cmd, void *arg)
CX18_DEBUG_IOCTL("VIDIOC_TRY_EXT_CTRLS\n");
if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG)
return cx2341x_ext_ctrls(&cx->params,
- atomic_read(&cx->capturing), arg, cmd);
+ atomic_read(&cx->ana_capturing), arg, cmd);
return -EINVAL;
}
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index 0dd4e0529970..2b810bb2a4c7 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -670,7 +670,7 @@ static int __devinit cx18_probe(struct pci_dev *dev,
cx18_init_power(cx, 1);
cx18_init_memory(cx);
- cx->scb = (struct cx18_scb *)(cx->enc_mem + SCB_OFFSET);
+ cx->scb = (struct cx18_scb __iomem *)(cx->enc_mem + SCB_OFFSET);
cx18_init_scb(cx);
cx18_gpio_init(cx);
@@ -751,17 +751,6 @@ static int __devinit cx18_probe(struct pci_dev *dev,
if (cx->options.radio > 0)
cx->v4l2_cap |= V4L2_CAP_RADIO;
- retval = cx18_streams_setup(cx);
- if (retval) {
- CX18_ERR("Error %d setting up streams\n", retval);
- goto free_irq;
- }
- retval = cx18_streams_register(cx);
- if (retval) {
- CX18_ERR("Error %d registering devices\n", retval);
- goto free_streams;
- }
-
if (cx->options.tuner > -1) {
struct tuner_setup setup;
@@ -788,7 +777,16 @@ static int __devinit cx18_probe(struct pci_dev *dev,
are not. */
cx->tuner_std = cx->std;
- cx18_init_on_first_open(cx);
+ retval = cx18_streams_setup(cx);
+ if (retval) {
+ CX18_ERR("Error %d setting up streams\n", retval);
+ goto free_irq;
+ }
+ retval = cx18_streams_register(cx);
+ if (retval) {
+ CX18_ERR("Error %d registering devices\n", retval);
+ goto free_streams;
+ }
CX18_INFO("Initialized card #%d: %s\n", cx->num, cx->card_name);
@@ -889,7 +887,7 @@ static void cx18_remove(struct pci_dev *pci_dev)
/* Stop all captures */
CX18_DEBUG_INFO("Stopping all streams\n");
- if (atomic_read(&cx->capturing) > 0)
+ if (atomic_read(&cx->tot_capturing) > 0)
cx18_stop_all_captures(cx);
/* Interrupts */
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index a2a6c58d12fe..de14ab59a206 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -358,7 +358,7 @@ struct cx18 {
u32 v4l2_cap; /* V4L2 capabilities of card */
u32 hw_flags; /* Hardware description of the board */
unsigned mdl_offset;
- struct cx18_scb *scb; /* pointer to SCB */
+ struct cx18_scb __iomem *scb; /* pointer to SCB */
struct cx18_av_state av_state;
@@ -380,7 +380,8 @@ struct cx18 {
int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */
struct cx18_stream streams[CX18_MAX_STREAMS]; /* Stream data */
unsigned long i_flags; /* global cx18 flags */
- atomic_t capturing; /* count number of active capture streams */
+ atomic_t ana_capturing; /* count number of active analog capture streams */
+ atomic_t tot_capturing; /* total count number of active capture streams */
spinlock_t lock; /* lock access to this struct */
int search_pack_header;
@@ -423,6 +424,10 @@ struct cx18 {
struct mutex i2c_bus_lock[2];
struct i2c_client *i2c_clients[I2C_CLIENTS_MAX];
+ /* gpio */
+ u32 gpio_dir;
+ u32 gpio_val;
+
/* v4l2 and User settings */
/* codec settings */
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
index 0b3141db174b..1e537fe04a23 100644
--- a/drivers/media/video/cx18/cx18-fileops.c
+++ b/drivers/media/video/cx18/cx18-fileops.c
@@ -318,7 +318,7 @@ static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf,
size_t tot_written = 0;
int single_frame = 0;
- if (atomic_read(&cx->capturing) == 0 && s->id == -1) {
+ if (atomic_read(&cx->ana_capturing) == 0 && s->id == -1) {
/* shouldn't happen */
CX18_DEBUG_WARN("Stream %s not initialized before read\n",
s->name);
@@ -361,7 +361,8 @@ static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf,
cx18_enqueue(s, buf, &s->q_free);
cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5,
s->handle,
- (void *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem,
+ (void __iomem *)&cx->scb->cpu_mdl[buf->id] -
+ cx->enc_mem,
1, buf->id, s->buf_size);
} else
cx18_enqueue(s, buf, &s->q_io);
@@ -581,7 +582,7 @@ int cx18_v4l2_close(struct inode *inode, struct file *filp)
cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std);
/* Select correct audio input (i.e. TV tuner or Line in) */
cx18_audio_set_io(cx);
- if (atomic_read(&cx->capturing) > 0) {
+ if (atomic_read(&cx->ana_capturing) > 0) {
/* Undo video mute */
cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
cx->params.video_mute |
@@ -627,7 +628,7 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
}
if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
- if (atomic_read(&cx->capturing) > 0) {
+ if (atomic_read(&cx->ana_capturing) > 0) {
/* switching to radio while capture is
in progress is not polite */
cx18_release_stream(s);
@@ -694,7 +695,7 @@ int cx18_v4l2_open(struct inode *inode, struct file *filp)
void cx18_mute(struct cx18 *cx)
{
- if (atomic_read(&cx->capturing))
+ if (atomic_read(&cx->ana_capturing))
cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
cx18_find_handle(cx), 1);
CX18_DEBUG_INFO("Mute\n");
@@ -702,7 +703,7 @@ void cx18_mute(struct cx18 *cx)
void cx18_unmute(struct cx18 *cx)
{
- if (atomic_read(&cx->capturing)) {
+ if (atomic_read(&cx->ana_capturing)) {
cx18_msleep_timeout(100, 0);
cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2,
cx18_find_handle(cx), 12);
diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c
index bb8bc86086d0..ceb63653c926 100644
--- a/drivers/media/video/cx18/cx18-gpio.c
+++ b/drivers/media/video/cx18/cx18-gpio.c
@@ -35,9 +35,6 @@
#define CX18_REG_GPIO_OUT2 0xc78104
#define CX18_REG_GPIO_DIR2 0xc7810c
-static u32 gpio_dir;
-static u32 gpio_val;
-
/*
* HVR-1600 GPIO pins, courtesy of Hauppauge:
*
@@ -49,24 +46,29 @@ static u32 gpio_val;
static void gpio_write(struct cx18 *cx)
{
- write_reg((gpio_dir & 0xffff) << 16, CX18_REG_GPIO_DIR1);
- write_reg(((gpio_dir & 0xffff) << 16) | (gpio_val & 0xffff),
+ u32 dir = cx->gpio_dir;
+ u32 val = cx->gpio_val;
+
+ write_reg((dir & 0xffff) << 16, CX18_REG_GPIO_DIR1);
+ write_reg(((dir & 0xffff) << 16) | (val & 0xffff),
CX18_REG_GPIO_OUT1);
- write_reg(gpio_dir & 0xffff0000, CX18_REG_GPIO_DIR2);
- write_reg((gpio_dir & 0xffff0000) | ((gpio_val & 0xffff0000) >> 16),
+ write_reg(dir & 0xffff0000, CX18_REG_GPIO_DIR2);
+ write_reg((dir & 0xffff0000) | ((val & 0xffff0000) >> 16),
CX18_REG_GPIO_OUT2);
}
void cx18_gpio_init(struct cx18 *cx)
{
- gpio_dir = cx->card->gpio_init.direction;
- gpio_val = cx->card->gpio_init.initial_value;
+ cx->gpio_dir = cx->card->gpio_init.direction;
+ cx->gpio_val = cx->card->gpio_init.initial_value;
- if (gpio_dir == 0)
- return;
+ if (cx->card->tuners[0].tuner == TUNER_XC2028) {
+ cx->gpio_dir |= 1 << cx->card->xceive_pin;
+ cx->gpio_val |= 1 << cx->card->xceive_pin;
+ }
- gpio_dir |= 1 << cx->card->xceive_pin;
- gpio_val |= 1 << cx->card->xceive_pin;
+ if (cx->gpio_dir == 0)
+ return;
CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n",
read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_DIR2),
@@ -86,13 +88,12 @@ int cx18_reset_tuner_gpio(void *dev, int cmd, int value)
return 0;
CX18_DEBUG_INFO("Resetting tuner\n");
- gpio_dir |= 1 << cx->card->xceive_pin;
- gpio_val &= ~(1 << cx->card->xceive_pin);
+ cx->gpio_val &= ~(1 << cx->card->xceive_pin);
gpio_write(cx);
schedule_timeout_interruptible(msecs_to_jiffies(1));
- gpio_val |= 1 << cx->card->xceive_pin;
+ cx->gpio_val |= 1 << cx->card->xceive_pin;
gpio_write(cx);
schedule_timeout_interruptible(msecs_to_jiffies(1));
return 0;
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
index dbdcb86ec5aa..4151f1e5493f 100644
--- a/drivers/media/video/cx18/cx18-ioctl.c
+++ b/drivers/media/video/cx18/cx18-ioctl.c
@@ -247,7 +247,7 @@ static int cx18_try_or_set_fmt(struct cx18 *cx, int streamtype,
if (!set_fmt || (cx->params.width == w && cx->params.height == h))
return 0;
- if (atomic_read(&cx->capturing) > 0)
+ if (atomic_read(&cx->ana_capturing) > 0)
return -EBUSY;
cx->params.width = w;
@@ -264,7 +264,7 @@ static int cx18_try_or_set_fmt(struct cx18 *cx, int streamtype,
if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
if (set_fmt && streamtype == CX18_ENC_STREAM_TYPE_VBI &&
cx->vbi.sliced_in->service_set &&
- atomic_read(&cx->capturing) > 0)
+ atomic_read(&cx->ana_capturing) > 0)
return -EBUSY;
if (set_fmt) {
cx->vbi.sliced_in->service_set = 0;
@@ -293,7 +293,7 @@ static int cx18_try_or_set_fmt(struct cx18 *cx, int streamtype,
return 0;
if (set == 0)
return -EINVAL;
- if (atomic_read(&cx->capturing) > 0 && cx->vbi.sliced_in->service_set == 0)
+ if (atomic_read(&cx->ana_capturing) > 0 && cx->vbi.sliced_in->service_set == 0)
return -EBUSY;
cx18_av_cmd(cx, VIDIOC_S_FMT, fmt);
memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in));
@@ -581,7 +581,7 @@ int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd, void *arg
break;
if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ||
- atomic_read(&cx->capturing) > 0) {
+ atomic_read(&cx->ana_capturing) > 0) {
/* Switching standard would turn off the radio or mess
with already running streams, prevent that by
returning EBUSY. */
@@ -677,7 +677,7 @@ int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd, void *arg
enc->flags = 0;
if (try)
return 0;
- if (!atomic_read(&cx->capturing))
+ if (!atomic_read(&cx->ana_capturing))
return -EPERM;
if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
return 0;
@@ -689,7 +689,7 @@ int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd, void *arg
enc->flags = 0;
if (try)
return 0;
- if (!atomic_read(&cx->capturing))
+ if (!atomic_read(&cx->ana_capturing))
return -EPERM;
if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
return 0;
diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c
index 6e14f8bda559..25114a5cbd57 100644
--- a/drivers/media/video/cx18/cx18-irq.c
+++ b/drivers/media/video/cx18/cx18-irq.c
@@ -75,7 +75,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb)
cx18_buf_sync_for_device(s, buf);
cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
- (void *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem,
+ (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem,
1, buf->id, s->buf_size);
} else
set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags);
@@ -161,13 +161,15 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id)
*/
if (sw2) {
- if (sw2 & (cx->scb->cpu2hpu_irq_ack | cx->scb->cpu2epu_irq_ack))
+ if (sw2 & (readl(&cx->scb->cpu2hpu_irq_ack) |
+ readl(&cx->scb->cpu2epu_irq_ack)))
wake_up(&cx->mb_cpu_waitq);
- if (sw2 & (cx->scb->apu2hpu_irq_ack | cx->scb->apu2epu_irq_ack))
+ if (sw2 & (readl(&cx->scb->apu2hpu_irq_ack) |
+ readl(&cx->scb->apu2epu_irq_ack)))
wake_up(&cx->mb_apu_waitq);
- if (sw2 & cx->scb->epu2hpu_irq_ack)
+ if (sw2 & readl(&cx->scb->epu2hpu_irq_ack))
wake_up(&cx->mb_epu_waitq);
- if (sw2 & cx->scb->hpu2epu_irq_ack)
+ if (sw2 & readl(&cx->scb->hpu2epu_irq_ack))
wake_up(&cx->mb_hpu_waitq);
}
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c
index 0c5f328bca54..2a5ccef9185b 100644
--- a/drivers/media/video/cx18/cx18-mailbox.c
+++ b/drivers/media/video/cx18/cx18-mailbox.c
@@ -94,10 +94,10 @@ static const struct cx18_api_info *find_api_info(u32 cmd)
return NULL;
}
-static struct cx18_mailbox *cx18_mb_is_complete(struct cx18 *cx, int rpu,
+static struct cx18_mailbox __iomem *cx18_mb_is_complete(struct cx18 *cx, int rpu,
u32 *state, u32 *irq, u32 *req)
{
- struct cx18_mailbox *mb = NULL;
+ struct cx18_mailbox __iomem *mb = NULL;
int wait_count = 0;
u32 ack;
@@ -142,7 +142,7 @@ static struct cx18_mailbox *cx18_mb_is_complete(struct cx18 *cx, int rpu,
long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb)
{
const struct cx18_api_info *info = find_api_info(mb->cmd);
- struct cx18_mailbox *ack_mb;
+ struct cx18_mailbox __iomem *ack_mb;
u32 ack_irq;
u8 rpu = CPU;
@@ -182,7 +182,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
{
const struct cx18_api_info *info = find_api_info(cmd);
u32 state = 0, irq = 0, req, oldreq, err;
- struct cx18_mailbox *mb;
+ struct cx18_mailbox __iomem *mb;
wait_queue_head_t *waitq;
int timeout = 100;
int cnt = 0;
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index 4ca9d847f1b1..1b921a336092 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -36,12 +36,13 @@
#define CX18_DSP0_INTERRUPT_MASK 0xd0004C
static struct file_operations cx18_v4l2_enc_fops = {
- .owner = THIS_MODULE,
- .read = cx18_v4l2_read,
- .open = cx18_v4l2_open,
- .ioctl = cx18_v4l2_ioctl,
- .release = cx18_v4l2_close,
- .poll = cx18_v4l2_enc_poll,
+ .owner = THIS_MODULE,
+ .read = cx18_v4l2_read,
+ .open = cx18_v4l2_open,
+ .ioctl = cx18_v4l2_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
+ .release = cx18_v4l2_close,
+ .poll = cx18_v4l2_enc_poll,
};
/* offset from 0 to register ts v4l2 minors on */
@@ -443,7 +444,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
s->handle = data[0];
cx18_vapi(cx, CX18_CPU_SET_CHANNEL_TYPE, 2, s->handle, captype);
- if (atomic_read(&cx->capturing) == 0 && !ts) {
+ if (atomic_read(&cx->ana_capturing) == 0 && !ts) {
/* Stuff from Windows, we don't know what it is */
cx18_vapi(cx, CX18_CPU_SET_VER_CROP_LINE, 2, s->handle, 0);
cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 3, 1);
@@ -466,14 +467,14 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
cx2341x_update(cx, cx18_api_func, NULL, &cx->params);
}
- if (atomic_read(&cx->capturing) == 0) {
+ if (atomic_read(&cx->tot_capturing) == 0) {
clear_bit(CX18_F_I_EOS, &cx->i_flags);
write_reg(7, CX18_DSP0_INTERRUPT_MASK);
}
cx18_vapi(cx, CX18_CPU_DE_SET_MDL_ACK, 3, s->handle,
- (void *)&cx->scb->cpu_mdl_ack[s->type][0] - cx->enc_mem,
- (void *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem);
+ (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][0] - cx->enc_mem,
+ (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem);
list_for_each(p, &s->q_free.list) {
struct cx18_buffer *buf = list_entry(p, struct cx18_buffer, list);
@@ -481,8 +482,8 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
writel(buf->dma_handle, &cx->scb->cpu_mdl[buf->id].paddr);
writel(s->buf_size, &cx->scb->cpu_mdl[buf->id].length);
cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
- (void *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, 1,
- buf->id, s->buf_size);
+ (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem,
+ 1, buf->id, s->buf_size);
}
/* begin_capture */
if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) {
@@ -492,7 +493,9 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
}
/* you're live! sit back and await interrupts :) */
- atomic_inc(&cx->capturing);
+ if (!ts)
+ atomic_inc(&cx->ana_capturing);
+ atomic_inc(&cx->tot_capturing);
return 0;
}
@@ -523,7 +526,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
CX18_DEBUG_INFO("Stop Capture\n");
- if (atomic_read(&cx->capturing) == 0)
+ if (atomic_read(&cx->tot_capturing) == 0)
return 0;
if (s->type == CX18_ENC_STREAM_TYPE_MPG)
@@ -537,7 +540,9 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n");
}
- atomic_dec(&cx->capturing);
+ if (s->type != CX18_ENC_STREAM_TYPE_TS)
+ atomic_dec(&cx->ana_capturing);
+ atomic_dec(&cx->tot_capturing);
/* Clear capture and no-read bits */
clear_bit(CX18_F_S_STREAMING, &s->s_flags);
@@ -545,7 +550,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
s->handle = 0xffffffff;
- if (atomic_read(&cx->capturing) > 0)
+ if (atomic_read(&cx->tot_capturing) > 0)
return 0;
write_reg(5, CX18_DSP0_INTERRUPT_MASK);
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
index f24abcd06dea..c4cc2f3b8876 100644
--- a/drivers/media/video/cx23885/cx23885-core.c
+++ b/drivers/media/video/cx23885/cx23885-core.c
@@ -823,7 +823,7 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev)
iounmap(dev->lmmio);
}
-static u32* cx23885_risc_field(u32 *rp, struct scatterlist *sglist,
+static __le32* cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
unsigned int offset, u32 sync_line,
unsigned int bpl, unsigned int padding,
unsigned int lines)
@@ -883,7 +883,7 @@ int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
unsigned int padding, unsigned int lines)
{
u32 instructions, fields;
- u32 *rp;
+ __le32 *rp;
int rc;
fields = 0;
@@ -924,7 +924,7 @@ static int cx23885_risc_databuffer(struct pci_dev *pci,
unsigned int lines)
{
u32 instructions;
- u32 *rp;
+ __le32 *rp;
int rc;
/* estimate risc mem: worst case is one write per page border +
@@ -951,7 +951,7 @@ static int cx23885_risc_databuffer(struct pci_dev *pci,
int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
u32 reg, u32 mask, u32 value)
{
- u32 *rp;
+ __le32 *rp;
int rc;
if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index aeba26dc0a37..fa6d398e97b9 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -1493,10 +1493,16 @@ static const struct cx88_board cx88_boards[] = {
},
},
[CX88_BOARD_POWERCOLOR_REAL_ANGEL] = {
- .name = "PowerColor Real Angel 330",
+ .name = "PowerColor RA330", /* Long names may confuse LIRC. */
.tuner_type = TUNER_XC2028,
.tuner_addr = 0x61,
.input = { {
+ .type = CX88_VMUX_DEBUG,
+ .vmux = 3, /* Due to the way the cx88 driver is written, */
+ .gpio0 = 0x00ff, /* there is no way to deactivate audio pass- */
+ .gpio1 = 0xf39d, /* through without this entry. Furthermore, if */
+ .gpio3 = 0x0000, /* the TV mux entry is first, you get audio */
+ }, { /* from the tuner on boot for a little while. */
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
.gpio0 = 0x00ff,
@@ -2424,8 +2430,9 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl)
switch (core->boardnr) {
case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
- /* Doesn't work with firmware version 2.7 */
- ctl->fname = "xc3028-v25.fw";
+ /* Now works with firmware version 2.7 */
+ if (core->i2c_algo.udelay < 16)
+ core->i2c_algo.udelay = 16;
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
ctl->scode_table = XC3028_FE_ZARLINK456;
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index c4d1aff1fdb4..60eeda3057e9 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -70,7 +70,7 @@ static DEFINE_MUTEX(devlist);
/* @lpi: lines per IRQ, or 0 to not generate irqs. Note: IRQ to be
generated _after_ lpi lines are transferred. */
-static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist,
+static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist,
unsigned int offset, u32 sync_line,
unsigned int bpl, unsigned int padding,
unsigned int lines, unsigned int lpi)
@@ -130,7 +130,7 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
unsigned int bpl, unsigned int padding, unsigned int lines)
{
u32 instructions,fields;
- u32 *rp;
+ __le32 *rp;
int rc;
fields = 0;
@@ -168,7 +168,7 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
unsigned int lines, unsigned int lpi)
{
u32 instructions;
- u32 *rp;
+ __le32 *rp;
int rc;
/* estimate risc mem: worst case is one write per page border +
@@ -193,7 +193,7 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
u32 reg, u32 mask, u32 value)
{
- u32 *rp;
+ __le32 *rp;
int rc;
if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 8996175cc950..fb163ecd9216 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -1166,13 +1166,13 @@ static int vidioc_g_register(struct file *file, void *priv,
reg->val = ret;
} else {
- u64 val = 0;
+ __le64 val = 0;
ret = em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,
reg->reg, (char *)&val, 2);
if (ret < 0)
return ret;
- reg->val = cpu_to_le64((__u64)val);
+ reg->val = le64_to_cpu(val);
}
return 0;
@@ -1183,9 +1183,9 @@ static int vidioc_s_register(struct file *file, void *priv,
{
struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev;
- u64 buf;
+ __le64 buf;
- buf = le64_to_cpu((__u64)reg->val);
+ buf = cpu_to_le64(reg->val);
return em28xx_write_regs(dev, reg->reg, (char *)&buf,
em28xx_reg_len(reg->reg));
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
index ba06e813c58c..9d23b1efd36d 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -259,6 +259,12 @@ struct ivtv_mailbox_data {
/* Scatter-Gather array element, used in DMA transfers */
struct ivtv_sg_element {
+ __le32 src;
+ __le32 dst;
+ __le32 size;
+};
+
+struct ivtv_sg_host_element {
u32 src;
u32 dst;
u32 size;
@@ -349,8 +355,8 @@ struct ivtv_stream {
u16 dma_xfer_cnt;
/* Base Dev SG Array for cx23415/6 */
- struct ivtv_sg_element *sg_pending;
- struct ivtv_sg_element *sg_processing;
+ struct ivtv_sg_host_element *sg_pending;
+ struct ivtv_sg_host_element *sg_processing;
struct ivtv_sg_element *sg_dma;
dma_addr_t sg_handle;
int sg_pending_size;
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index f2fa434b677b..db813e071ce6 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -587,7 +587,7 @@ retry:
since we may get here before the stream has been fully set-up */
if (mode == OUT_YUV && s->q_full.length == 0 && itv->dma_data_req_size) {
while (count >= itv->dma_data_req_size) {
- if (!ivtv_yuv_udma_stream_frame (itv, (void *)user_buf)) {
+ if (!ivtv_yuv_udma_stream_frame (itv, (void __user *)user_buf)) {
bytes_written += itv->dma_data_req_size;
user_buf += itv->dma_data_req_size;
count -= itv->dma_data_req_size;
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c
index d8ba3a4a8761..fba150a6cd23 100644
--- a/drivers/media/video/ivtv/ivtv-irq.c
+++ b/drivers/media/video/ivtv/ivtv-irq.c
@@ -231,14 +231,14 @@ static void dma_post(struct ivtv_stream *s)
struct ivtv_buffer *buf = NULL;
struct list_head *p;
u32 offset;
- u32 *u32buf;
+ __le32 *u32buf;
int x = 0;
IVTV_DEBUG_HI_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA",
s->name, s->dma_offset);
list_for_each(p, &s->q_dma.list) {
buf = list_entry(p, struct ivtv_buffer, list);
- u32buf = (u32 *)buf->buf;
+ u32buf = (__le32 *)buf->buf;
/* Sync Buffer */
ivtv_buf_sync_for_cpu(s, buf);
@@ -444,7 +444,7 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
}
s->dma_xfer_cnt++;
- memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_element) * s->sg_pending_size);
+ memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_host_element) * s->sg_pending_size);
s->sg_processing_size = s->sg_pending_size;
s->sg_pending_size = 0;
s->sg_processed = 0;
@@ -473,7 +473,7 @@ static void ivtv_dma_dec_start(struct ivtv_stream *s)
if (s->q_predma.bytesused)
ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
s->dma_xfer_cnt++;
- memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_element) * s->sg_pending_size);
+ memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_host_element) * s->sg_pending_size);
s->sg_processing_size = s->sg_pending_size;
s->sg_pending_size = 0;
s->sg_processed = 0;
diff --git a/drivers/media/video/ivtv/ivtv-queue.c b/drivers/media/video/ivtv/ivtv-queue.c
index fc8b1eaa333b..71bd13e22e2e 100644
--- a/drivers/media/video/ivtv/ivtv-queue.c
+++ b/drivers/media/video/ivtv/ivtv-queue.c
@@ -193,7 +193,7 @@ void ivtv_flush_queues(struct ivtv_stream *s)
int ivtv_stream_alloc(struct ivtv_stream *s)
{
struct ivtv *itv = s->itv;
- int SGsize = sizeof(struct ivtv_sg_element) * s->buffers;
+ int SGsize = sizeof(struct ivtv_sg_host_element) * s->buffers;
int i;
if (s->buffers == 0)
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index c47c2b945147..c854285a4371 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -44,23 +44,25 @@
#include "ivtv-streams.h"
static const struct file_operations ivtv_v4l2_enc_fops = {
- .owner = THIS_MODULE,
- .read = ivtv_v4l2_read,
- .write = ivtv_v4l2_write,
- .open = ivtv_v4l2_open,
- .ioctl = ivtv_v4l2_ioctl,
- .release = ivtv_v4l2_close,
- .poll = ivtv_v4l2_enc_poll,
+ .owner = THIS_MODULE,
+ .read = ivtv_v4l2_read,
+ .write = ivtv_v4l2_write,
+ .open = ivtv_v4l2_open,
+ .ioctl = ivtv_v4l2_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
+ .release = ivtv_v4l2_close,
+ .poll = ivtv_v4l2_enc_poll,
};
static const struct file_operations ivtv_v4l2_dec_fops = {
- .owner = THIS_MODULE,
- .read = ivtv_v4l2_read,
- .write = ivtv_v4l2_write,
- .open = ivtv_v4l2_open,
- .ioctl = ivtv_v4l2_ioctl,
- .release = ivtv_v4l2_close,
- .poll = ivtv_v4l2_dec_poll,
+ .owner = THIS_MODULE,
+ .read = ivtv_v4l2_read,
+ .write = ivtv_v4l2_write,
+ .open = ivtv_v4l2_open,
+ .ioctl = ivtv_v4l2_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
+ .release = ivtv_v4l2_close,
+ .poll = ivtv_v4l2_dec_poll,
};
#define IVTV_V4L2_DEC_MPG_OFFSET 16 /* offset from 0 to register decoder mpg v4l2 minors on */
diff --git a/drivers/media/video/ivtv/ivtv-version.h b/drivers/media/video/ivtv/ivtv-version.h
index 02c5ab071d1b..442f43f11b73 100644
--- a/drivers/media/video/ivtv/ivtv-version.h
+++ b/drivers/media/video/ivtv/ivtv-version.h
@@ -22,8 +22,8 @@
#define IVTV_DRIVER_NAME "ivtv"
#define IVTV_DRIVER_VERSION_MAJOR 1
-#define IVTV_DRIVER_VERSION_MINOR 2
-#define IVTV_DRIVER_VERSION_PATCHLEVEL 1
+#define IVTV_DRIVER_VERSION_MINOR 3
+#define IVTV_DRIVER_VERSION_PATCHLEVEL 0
#define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL)
#define IVTV_DRIVER_VERSION KERNEL_VERSION(IVTV_DRIVER_VERSION_MAJOR,IVTV_DRIVER_VERSION_MINOR,IVTV_DRIVER_VERSION_PATCHLEVEL)
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c
index a9417f6e4087..3092ff1d00a0 100644
--- a/drivers/media/video/ivtv/ivtv-yuv.c
+++ b/drivers/media/video/ivtv/ivtv-yuv.c
@@ -1116,7 +1116,7 @@ void ivtv_yuv_setup_stream_frame(struct ivtv *itv)
}
/* Attempt to dma a frame from a user buffer */
-int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void *src)
+int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src)
{
struct yuv_playback_info *yi = &itv->yuv_info;
struct ivtv_dma_frame dma_args;
diff --git a/drivers/media/video/ivtv/ivtv-yuv.h b/drivers/media/video/ivtv/ivtv-yuv.h
index 2fe5f1250762..ca5173fbf006 100644
--- a/drivers/media/video/ivtv/ivtv-yuv.h
+++ b/drivers/media/video/ivtv/ivtv-yuv.h
@@ -35,7 +35,7 @@ extern const u32 yuv_offset[IVTV_YUV_BUFFERS];
int ivtv_yuv_filter_check(struct ivtv *itv);
void ivtv_yuv_setup_stream_frame(struct ivtv *itv);
-int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void *src);
+int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src);
void ivtv_yuv_frame_complete(struct ivtv *itv);
int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args);
void ivtv_yuv_close(struct ivtv *itv);
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index 1314522a8130..81431ee41842 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -163,8 +163,7 @@ ts_mmap(struct file *file, struct vm_area_struct * vma)
static int empress_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = file->private_data;
strcpy(cap->driver, "saa7134");
strlcpy(cap->card, saa7134_boards[dev->board].name,
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index 198f0afb812e..0d12ace61665 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -92,6 +92,7 @@ struct tuner {
unsigned int type; /* chip type id */
unsigned int config;
int (*tuner_callback) (void *dev, int command, int arg);
+ const char *name;
};
/* standard i2c insmod options */
@@ -330,13 +331,13 @@ static void tuner_i2c_address_check(struct tuner *t)
tuner_warn("Support for tuners in i2c address range 0x64 thru 0x6f\n");
tuner_warn("will soon be dropped. This message indicates that your\n");
tuner_warn("hardware has a %s tuner at i2c address 0x%02x.\n",
- t->i2c->name, t->i2c->addr);
+ t->name, t->i2c->addr);
tuner_warn("To ensure continued support for your device, please\n");
tuner_warn("send a copy of this message, along with full dmesg\n");
tuner_warn("output to v4l-dvb-maintainer@linuxtv.org\n");
tuner_warn("Please use subject line: \"obsolete tuner i2c address.\"\n");
tuner_warn("driver: %s, addr: 0x%02x, type: %d (%s)\n",
- t->i2c->adapter->name, t->i2c->addr, t->type, t->i2c->name);
+ t->i2c->adapter->name, t->i2c->addr, t->type, t->name);
tuner_warn("====================== WARNING! ======================\n");
}
@@ -470,19 +471,17 @@ static void set_type(struct i2c_client *c, unsigned int type,
if ((NULL == analog_ops->set_params) &&
(fe_tuner_ops->set_analog_params)) {
- strlcpy(t->i2c->name, fe_tuner_ops->info.name,
- sizeof(t->i2c->name));
+ t->name = fe_tuner_ops->info.name;
t->fe.analog_demod_priv = t;
memcpy(analog_ops, &tuner_core_ops,
sizeof(struct analog_demod_ops));
} else {
- strlcpy(t->i2c->name, analog_ops->info.name,
- sizeof(t->i2c->name));
+ t->name = analog_ops->info.name;
}
- tuner_dbg("type set to %s\n", t->i2c->name);
+ tuner_dbg("type set to %s\n", t->name);
if (t->mode_mask == T_UNINITIALIZED)
t->mode_mask = new_mode_mask;
@@ -537,7 +536,7 @@ static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup)
static inline int check_mode(struct tuner *t, char *cmd)
{
if ((1 << t->mode & t->mode_mask) == 0) {
- return EINVAL;
+ return -EINVAL;
}
switch (t->mode) {
@@ -731,11 +730,11 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode,
t->mode = mode;
- if (check_mode(t, cmd) == EINVAL) {
+ if (check_mode(t, cmd) == -EINVAL) {
t->mode = T_STANDBY;
if (analog_ops->standby)
analog_ops->standby(&t->fe);
- return EINVAL;
+ return -EINVAL;
}
return 0;
}
@@ -777,13 +776,13 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
break;
case AUDC_SET_RADIO:
if (set_mode(client, t, V4L2_TUNER_RADIO, "AUDC_SET_RADIO")
- == EINVAL)
+ == -EINVAL)
return 0;
if (t->radio_freq)
set_freq(client, t->radio_freq);
break;
case TUNER_SET_STANDBY:
- if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL)
+ if (check_mode(t, "TUNER_SET_STANDBY") == -EINVAL)
return 0;
t->mode = T_STANDBY;
if (analog_ops->standby)
@@ -791,9 +790,9 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
break;
#ifdef CONFIG_VIDEO_ALLOW_V4L1
case VIDIOCSAUDIO:
- if (check_mode(t, "VIDIOCSAUDIO") == EINVAL)
+ if (check_mode(t, "VIDIOCSAUDIO") == -EINVAL)
return 0;
- if (check_v4l2(t) == EINVAL)
+ if (check_v4l2(t) == -EINVAL)
return 0;
/* Should be implemented, since bttv calls it */
@@ -811,10 +810,10 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
};
struct video_channel *vc = arg;
- if (check_v4l2(t) == EINVAL)
+ if (check_v4l2(t) == -EINVAL)
return 0;
- if (set_mode(client,t,V4L2_TUNER_ANALOG_TV, "VIDIOCSCHAN")==EINVAL)
+ if (set_mode(client,t,V4L2_TUNER_ANALOG_TV, "VIDIOCSCHAN")==-EINVAL)
return 0;
if (vc->norm < ARRAY_SIZE(map))
@@ -828,9 +827,9 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
unsigned long *v = arg;
- if (check_mode(t, "VIDIOCSFREQ") == EINVAL)
+ if (check_mode(t, "VIDIOCSFREQ") == -EINVAL)
return 0;
- if (check_v4l2(t) == EINVAL)
+ if (check_v4l2(t) == -EINVAL)
return 0;
set_freq(client, *v);
@@ -840,9 +839,9 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct video_tuner *vt = arg;
- if (check_mode(t, "VIDIOCGTUNER") == EINVAL)
+ if (check_mode(t, "VIDIOCGTUNER") == -EINVAL)
return 0;
- if (check_v4l2(t) == EINVAL)
+ if (check_v4l2(t) == -EINVAL)
return 0;
if (V4L2_TUNER_RADIO == t->mode) {
@@ -884,9 +883,9 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct video_audio *va = arg;
- if (check_mode(t, "VIDIOCGAUDIO") == EINVAL)
+ if (check_mode(t, "VIDIOCGAUDIO") == -EINVAL)
return 0;
- if (check_v4l2(t) == EINVAL)
+ if (check_v4l2(t) == -EINVAL)
return 0;
if (V4L2_TUNER_RADIO == t->mode) {
@@ -926,7 +925,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
v4l2_std_id *id = arg;
if (set_mode (client, t, V4L2_TUNER_ANALOG_TV, "VIDIOC_S_STD")
- == EINVAL)
+ == -EINVAL)
return 0;
switch_v4l2();
@@ -942,7 +941,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
struct v4l2_frequency *f = arg;
if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY")
- == EINVAL)
+ == -EINVAL)
return 0;
switch_v4l2();
set_freq(client,f->frequency);
@@ -953,7 +952,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct v4l2_frequency *f = arg;
- if (check_mode(t, "VIDIOC_G_FREQUENCY") == EINVAL)
+ if (check_mode(t, "VIDIOC_G_FREQUENCY") == -EINVAL)
return 0;
switch_v4l2();
f->type = t->mode;
@@ -974,7 +973,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct v4l2_tuner *tuner = arg;
- if (check_mode(t, "VIDIOC_G_TUNER") == EINVAL)
+ if (check_mode(t, "VIDIOC_G_TUNER") == -EINVAL)
return 0;
switch_v4l2();
@@ -1021,7 +1020,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct v4l2_tuner *tuner = arg;
- if (check_mode(t, "VIDIOC_S_TUNER") == EINVAL)
+ if (check_mode(t, "VIDIOC_S_TUNER") == -EINVAL)
return 0;
switch_v4l2();
@@ -1115,6 +1114,7 @@ static int tuner_probe(struct i2c_client *client,
if (NULL == t)
return -ENOMEM;
t->i2c = client;
+ t->name = "(tuner unset)";
i2c_set_clientdata(client, t);
t->type = UNSET;
t->audmode = V4L2_TUNER_MODE_STEREO;
@@ -1272,12 +1272,6 @@ static int tuner_remove(struct i2c_client *client)
list_del(&t->list);
kfree(t);
-
- /* The probing code has overwritten the device name, restore it so
- that reloading the driver will work. Ideally the device name
- should not be overwritten in the first place, but for now that
- will do. */
- strlcpy(client->name, "tuner", I2C_NAME_SIZE);
return 0;
}
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c
index 32e536edf09d..3d26a30abe1e 100644
--- a/drivers/media/video/usbvideo/quickcam_messenger.c
+++ b/drivers/media/video/usbvideo/quickcam_messenger.c
@@ -210,7 +210,7 @@ static int qcm_stv_setb(struct usb_device *dev, u16 reg, u8 val)
return ret;
}
-static int qcm_stv_setw(struct usb_device *dev, u16 reg, u16 val)
+static int qcm_stv_setw(struct usb_device *dev, u16 reg, __le16 val)
{
int ret;
diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h
index 81cc3b00a079..46b7ad477ceb 100644
--- a/drivers/media/video/zoran.h
+++ b/drivers/media/video/zoran.h
@@ -285,7 +285,7 @@ struct zoran_mapping {
struct zoran_jpg_buffer {
struct zoran_mapping *map;
- u32 *frag_tab; /* addresses of frag table */
+ __le32 *frag_tab; /* addresses of frag table */
u32 frag_tab_bus; /* same value cached to save time in ISR */
enum zoran_buffer_state state; /* non-zero if corresponding buffer is in use in grab queue */
struct zoran_sync bs; /* DONE: info to return to application */
@@ -450,7 +450,7 @@ struct zoran {
unsigned long jpg_queued_num; /* count of frames queued since grab/play started */
/* zr36057's code buffer table */
- u32 *stat_com; /* stat_com[i] is indexed by dma_head/tail & BUZ_MASK_STAT_COM */
+ __le32 *stat_com; /* stat_com[i] is indexed by dma_head/tail & BUZ_MASK_STAT_COM */
/* (value & BUZ_MASK_FRAME) corresponds to index in pend[] queue */
int jpg_pend[BUZ_MAX_FRAME];
diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c
index 37629ffd34c3..88d369708e4c 100644
--- a/drivers/media/video/zoran_device.c
+++ b/drivers/media/video/zoran_device.c
@@ -1320,7 +1320,7 @@ error_handler (struct zoran *zr,
if (i) {
/* Rotate stat_comm entries to make current entry first */
int j;
- u32 bus_addr[BUZ_NUM_STAT_COM];
+ __le32 bus_addr[BUZ_NUM_STAT_COM];
/* Here we are copying the stat_com array, which
* is already in little endian format, so
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
index 345c77e46837..5394d7a5cfee 100644
--- a/drivers/media/video/zoran_driver.c
+++ b/drivers/media/video/zoran_driver.c
@@ -495,7 +495,7 @@ jpg_fbuffer_alloc (struct file *file)
jpg_fbuffer_free(file);
return -ENOBUFS;
}
- fh->jpg_buffers.buffer[i].frag_tab = (u32 *) mem;
+ fh->jpg_buffers.buffer[i].frag_tab = (__le32 *) mem;
fh->jpg_buffers.buffer[i].frag_tab_bus =
virt_to_bus((void *) mem);
@@ -1167,7 +1167,7 @@ zoran_close_end_session (struct file *file)
/* v4l capture */
if (fh->v4l_buffers.active != ZORAN_FREE) {
- long flags;
+ unsigned long flags;
spin_lock_irqsave(&zr->spinlock, flags);
zr36057_set_memgrab(zr, 0);
@@ -3436,7 +3436,7 @@ zoran_do_ioctl (struct inode *inode,
/* unload capture */
if (zr->v4l_memgrab_active) {
- long flags;
+ unsigned long flags;
spin_lock_irqsave(&zr->spinlock, flags);
zr36057_set_memgrab(zr, 0);
@@ -4375,7 +4375,7 @@ zoran_vm_close (struct vm_area_struct *vma)
mutex_lock(&zr->resource_lock);
if (fh->v4l_buffers.active != ZORAN_FREE) {
- long flags;
+ unsigned long flags;
spin_lock_irqsave(&zr->spinlock, flags);
zr36057_set_memgrab(zr, 0);
@@ -4506,7 +4506,7 @@ zoran_mmap (struct file *file,
if (todo > fraglen)
todo = fraglen;
pos =
- le32_to_cpu((unsigned long) fh->jpg_buffers.
+ le32_to_cpu(fh->jpg_buffers.
buffer[i].frag_tab[2 * j]);
/* should just be pos on i386 */
page = virt_to_phys(bus_to_virt(pos))
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index 3cdd4e962115..1e24ab4ac38c 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -1238,8 +1238,6 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sh->max_id = ioc->pfacts->MaxDevices;
sh->max_lun = max_lun;
- sh->this_id = ioc->pfacts[0].PortSCSIID;
-
/* Required entry.
*/
sh->unique_id = ioc->id;
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 468480771f13..4d492ba232b0 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -3193,8 +3193,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sh->transportt = mptsas_transport_template;
- sh->this_id = ioc->pfacts[0].PortSCSIID;
-
/* Required entry.
*/
sh->unique_id = ioc->id;
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index b109bd8a4d19..c68ef00c2f92 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -2451,12 +2451,6 @@ mptscsih_slave_configure(struct scsi_device *sdev)
ioc->name, sdev->sdtr, sdev->wdtr,
sdev->ppr, sdev->inquiry_len));
- if (sdev->id > sh->max_id) {
- /* error case, should never happen */
- scsi_adjust_queue_depth(sdev, 0, 1);
- goto slave_configure_exit;
- }
-
vdevice->configured_lun = 1;
mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
@@ -2470,8 +2464,6 @@ mptscsih_slave_configure(struct scsi_device *sdev)
ioc->name, vtarget->negoFlags, vtarget->maxOffset,
vtarget->minSyncFactor));
-slave_configure_exit:
-
dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"tagged %d, simple %d, ordered %d\n",
ioc->name,sdev->tagged_supported, sdev->simple_tags,
diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c
index e2e7c05a147b..6d14e8fe1537 100644
--- a/drivers/misc/fujitsu-laptop.c
+++ b/drivers/misc/fujitsu-laptop.c
@@ -352,3 +352,9 @@ MODULE_AUTHOR("Jonathan Woithe");
MODULE_DESCRIPTION("Fujitsu laptop extras support");
MODULE_VERSION(FUJITSU_DRIVER_VERSION);
MODULE_LICENSE("GPL");
+
+static struct pnp_device_id pnp_ids[] = {
+ { .id = "FUJ02bf" },
+ { .id = "" }
+};
+MODULE_DEVICE_TABLE(pnp, pnp_ids);
diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c
index fa394104339c..e4ff50b95a5e 100644
--- a/drivers/misc/kgdbts.c
+++ b/drivers/misc/kgdbts.c
@@ -102,7 +102,6 @@
#include <linux/nmi.h>
#include <linux/delay.h>
#include <linux/kthread.h>
-#include <linux/delay.h>
#define v1printk(a...) do { \
if (verbose) \
@@ -119,7 +118,6 @@
} while (0)
#define MAX_CONFIG_LEN 40
-static const char hexchars[] = "0123456789abcdef";
static struct kgdb_io kgdbts_io_ops;
static char get_buf[BUFMAX];
static int get_buf_cnt;
@@ -131,6 +129,8 @@ static int repeat_test;
static int test_complete;
static int send_ack;
static int final_ack;
+static int force_hwbrks;
+static int hwbreaks_ok;
static int hw_break_val;
static int hw_break_val2;
#if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || defined(CONFIG_SPARC)
@@ -234,12 +234,12 @@ static void break_helper(char *bp_type, char *arg, unsigned long vaddr)
static void sw_break(char *arg)
{
- break_helper("Z0", arg, 0);
+ break_helper(force_hwbrks ? "Z1" : "Z0", arg, 0);
}
static void sw_rem_break(char *arg)
{
- break_helper("z0", arg, 0);
+ break_helper(force_hwbrks ? "z1" : "z0", arg, 0);
}
static void hw_break(char *arg)
@@ -619,8 +619,8 @@ static void fill_get_buf(char *buf)
count++;
}
strcat(get_buf, "#");
- get_buf[count + 2] = hexchars[checksum >> 4];
- get_buf[count + 3] = hexchars[checksum & 0xf];
+ get_buf[count + 2] = hex_asc_hi(checksum);
+ get_buf[count + 3] = hex_asc_lo(checksum);
get_buf[count + 4] = '\0';
v2printk("get%i: %s\n", ts.idx, get_buf);
}
@@ -781,6 +781,8 @@ static void run_breakpoint_test(int is_hw_breakpoint)
return;
eprintk("kgdbts: ERROR %s test failed\n", ts.name);
+ if (is_hw_breakpoint)
+ hwbreaks_ok = 0;
}
static void run_hw_break_test(int is_write_test)
@@ -798,9 +800,11 @@ static void run_hw_break_test(int is_write_test)
kgdb_breakpoint();
hw_break_val_access();
if (is_write_test) {
- if (test_complete == 2)
+ if (test_complete == 2) {
eprintk("kgdbts: ERROR %s broke on access\n",
ts.name);
+ hwbreaks_ok = 0;
+ }
hw_break_val_write();
}
kgdb_breakpoint();
@@ -809,6 +813,7 @@ static void run_hw_break_test(int is_write_test)
return;
eprintk("kgdbts: ERROR %s test failed\n", ts.name);
+ hwbreaks_ok = 0;
}
static void run_nmi_sleep_test(int nmi_sleep)
@@ -912,6 +917,7 @@ static void kgdbts_run_tests(void)
/* All HW break point tests */
if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) {
+ hwbreaks_ok = 1;
v1printk("kgdbts:RUN hw breakpoint test\n");
run_breakpoint_test(1);
v1printk("kgdbts:RUN hw write breakpoint test\n");
@@ -925,6 +931,19 @@ static void kgdbts_run_tests(void)
run_nmi_sleep_test(nmi_sleep);
}
+#ifdef CONFIG_DEBUG_RODATA
+ /* Until there is an api to write to read-only text segments, use
+ * HW breakpoints for the remainder of any tests, else print a
+ * failure message if hw breakpoints do not work.
+ */
+ if (!(arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT && hwbreaks_ok)) {
+ eprintk("kgdbts: HW breakpoints do not work,"
+ "skipping remaining tests\n");
+ return;
+ }
+ force_hwbrks = 1;
+#endif /* CONFIG_DEBUG_RODATA */
+
/* If the do_fork test is run it will be the last test that is
* executed because a kernel thread will be spawned at the very
* end to unregister the debug hooks.
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index 3f28f6eabdbf..a0ce0b2fa03e 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -3821,7 +3821,7 @@ TPACPI_HANDLE(led, ec, "SLED", /* 570 */
#define TPACPI_LED_NUMLEDS 8
static struct tpacpi_led_classdev *tpacpi_leds;
static enum led_status_t tpacpi_led_state_cache[TPACPI_LED_NUMLEDS];
-static const char const *tpacpi_led_names[TPACPI_LED_NUMLEDS] = {
+static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = {
/* there's a limit of 19 chars + NULL before 2.6.26 */
"tpacpi::power",
"tpacpi:orange:batt",
@@ -3860,10 +3860,10 @@ static int led_get_status(unsigned int led)
static int led_set_status(unsigned int led, enum led_status_t ledstatus)
{
/* off, on, blink. Index is led_status_t */
- static const int const led_sled_arg1[] = { 0, 1, 3 };
- static const int const led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */
- static const int const led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */
- static const int const led_led_arg1[] = { 0, 0x80, 0xc0 };
+ static const int led_sled_arg1[] = { 0, 1, 3 };
+ static const int led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */
+ static const int led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */
+ static const int led_led_arg1[] = { 0, 0x80, 0xc0 };
int rc = 0;
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 91ded3e82401..f9ad960d7c1a 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -46,7 +46,7 @@
#define MMC_SHIFT 3
#define MMC_NUM_MINORS (256 >> MMC_SHIFT)
-static unsigned long dev_use[MMC_NUM_MINORS/(8*sizeof(unsigned long))];
+static DECLARE_BITMAP(dev_use, MMC_NUM_MINORS);
/*
* There is one mmc_blk_data per slot.
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 25efd331ef28..b402269301f6 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -346,8 +346,10 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
mutex_lock(&flash->lock);
/* Wait until finished previous write command. */
- if (wait_till_ready(flash))
+ if (wait_till_ready(flash)) {
+ mutex_unlock(&flash->lock);
return 1;
+ }
write_enable(flash);
diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c
index 59d8fb49270a..effaf7cdefab 100644
--- a/drivers/mtd/maps/ck804xrom.c
+++ b/drivers/mtd/maps/ck804xrom.c
@@ -331,15 +331,15 @@ static void __devexit ck804xrom_remove_one (struct pci_dev *pdev)
}
static struct pci_device_id ck804xrom_pci_tbl[] = {
- { PCI_VENDOR_ID_NVIDIA, 0x0051, PCI_ANY_ID, PCI_ANY_ID, DEV_CK804 },
- { PCI_VENDOR_ID_NVIDIA, 0x0360, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
- { PCI_VENDOR_ID_NVIDIA, 0x0361, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
- { PCI_VENDOR_ID_NVIDIA, 0x0362, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
- { PCI_VENDOR_ID_NVIDIA, 0x0363, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
- { PCI_VENDOR_ID_NVIDIA, 0x0364, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
- { PCI_VENDOR_ID_NVIDIA, 0x0365, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
- { PCI_VENDOR_ID_NVIDIA, 0x0366, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
- { PCI_VENDOR_ID_NVIDIA, 0x0367, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
+ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0051), .driver_data = DEV_CK804 },
+ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0360), .driver_data = DEV_MCP55 },
+ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0361), .driver_data = DEV_MCP55 },
+ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0362), .driver_data = DEV_MCP55 },
+ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0363), .driver_data = DEV_MCP55 },
+ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0364), .driver_data = DEV_MCP55 },
+ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0365), .driver_data = DEV_MCP55 },
+ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0366), .driver_data = DEV_MCP55 },
+ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0367), .driver_data = DEV_MCP55 },
{ 0, }
};
diff --git a/drivers/mtd/maps/omap_nor.c b/drivers/mtd/maps/omap_nor.c
index 240b0e2d095d..c12d8056bebd 100644
--- a/drivers/mtd/maps/omap_nor.c
+++ b/drivers/mtd/maps/omap_nor.c
@@ -110,7 +110,7 @@ static int __init omapflash_probe(struct platform_device *pdev)
err = parse_mtd_partitions(info->mtd, part_probes, &info->parts, 0);
if (err > 0)
add_mtd_partitions(info->mtd, info->parts, err);
- else if (err < 0 && pdata->parts)
+ else if (err <= 0 && pdata->parts)
add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts);
else
#endif
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index fceb468ccdec..fe2bc7e42119 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -1216,7 +1216,7 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
clk_enable(info->clk);
- return pxa3xx_nand_config_flash(info);
+ return pxa3xx_nand_config_flash(info, info->flash_info);
}
#else
#define pxa3xx_nand_suspend NULL
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
index 3d44d040a47d..ad81ab8e95e2 100644
--- a/drivers/mtd/onenand/generic.c
+++ b/drivers/mtd/onenand/generic.c
@@ -76,7 +76,7 @@ static int __devinit generic_onenand_probe(struct device *dev)
err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
if (err > 0)
add_mtd_partitions(&info->mtd, info->parts, err);
- else if (err < 0 && pdata->parts)
+ else if (err <= 0 && pdata->parts)
add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts);
else
#endif
diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c
index 47474903263c..c5030f94f04e 100644
--- a/drivers/mtd/redboot.c
+++ b/drivers/mtd/redboot.c
@@ -295,5 +295,5 @@ module_init(redboot_parser_init);
module_exit(redboot_parser_exit);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Red Hat, Inc. - David Woodhouse <dwmw2@cambridge.redhat.com>");
+MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
MODULE_DESCRIPTION("Parsing code for RedBoot Flash Image System (FIS) tables");
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
index 87d8795823d7..b9d097c9f6bb 100644
--- a/drivers/net/3c509.c
+++ b/drivers/net/3c509.c
@@ -1062,7 +1062,6 @@ el3_rx(struct net_device *dev)
struct sk_buff *skb;
skb = dev_alloc_skb(pkt_len+5);
- dev->stats.rx_bytes += pkt_len;
if (el3_debug > 4)
printk("Receiving packet size %d status %4.4x.\n",
pkt_len, rx_status);
@@ -1077,6 +1076,7 @@ el3_rx(struct net_device *dev)
skb->protocol = eth_type_trans(skb,dev);
netif_rx(skb);
dev->last_rx = jiffies;
+ dev->stats.rx_bytes += pkt_len;
dev->stats.rx_packets++;
continue;
}
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index b1ca6f2a44e8..8e3e968b2957 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2425,7 +2425,7 @@ config CHELSIO_T3
config EHEA
tristate "eHEA Ethernet support"
- depends on IBMEBUS && INET && SPARSEMEM && MEMORY_HOTPLUG
+ depends on IBMEBUS && INET && SPARSEMEM
select INET_LRO
---help---
This driver supports the IBM pSeries eHEA ethernet adapter.
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c
index 6e4c80d41b08..6ddc911e7d15 100644
--- a/drivers/net/atlx/atl1.c
+++ b/drivers/net/atlx/atl1.c
@@ -2023,6 +2023,7 @@ rrd_ok:
/* Good Receive */
pci_unmap_page(adapter->pdev, buffer_info->dma,
buffer_info->length, PCI_DMA_FROMDEVICE);
+ buffer_info->dma = 0;
skb = buffer_info->skb;
length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size);
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 3634b5fd7919..7023d77bf380 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -1239,12 +1239,7 @@ static int au1000_rx(struct net_device *dev)
*/
static irqreturn_t au1000_interrupt(int irq, void *dev_id)
{
- struct net_device *dev = (struct net_device *) dev_id;
-
- if (dev == NULL) {
- printk(KERN_ERR "%s: isr: null dev ptr\n", dev->name);
- return IRQ_RETVAL(1);
- }
+ struct net_device *dev = dev_id;
/* Handle RX interrupts first to minimize chance of overrun */
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
index 89c0018132ec..41443435ab1c 100644
--- a/drivers/net/bfin_mac.c
+++ b/drivers/net/bfin_mac.c
@@ -22,7 +22,6 @@
#include <linux/crc32.h>
#include <linux/device.h>
#include <linux/spinlock.h>
-#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/phy.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index 2b5740b3d182..7f3f62e1b113 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -38,6 +38,7 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <asm/gpio.h>
+#include <asm/atomic.h>
MODULE_AUTHOR("Eugene Konev <ejka@imfi.kspu.ru>");
MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)");
@@ -187,6 +188,7 @@ struct cpmac_desc {
#define CPMAC_EOQ 0x1000
struct sk_buff *skb;
struct cpmac_desc *next;
+ struct cpmac_desc *prev;
dma_addr_t mapping;
dma_addr_t data_mapping;
};
@@ -208,6 +210,7 @@ struct cpmac_priv {
struct work_struct reset_work;
struct platform_device *pdev;
struct napi_struct napi;
+ atomic_t reset_pending;
};
static irqreturn_t cpmac_irq(int, void *);
@@ -241,6 +244,16 @@ static void cpmac_dump_desc(struct net_device *dev, struct cpmac_desc *desc)
printk("\n");
}
+static void cpmac_dump_all_desc(struct net_device *dev)
+{
+ struct cpmac_priv *priv = netdev_priv(dev);
+ struct cpmac_desc *dump = priv->rx_head;
+ do {
+ cpmac_dump_desc(dev, dump);
+ dump = dump->next;
+ } while (dump != priv->rx_head);
+}
+
static void cpmac_dump_skb(struct net_device *dev, struct sk_buff *skb)
{
int i;
@@ -412,21 +425,42 @@ static struct sk_buff *cpmac_rx_one(struct cpmac_priv *priv,
static int cpmac_poll(struct napi_struct *napi, int budget)
{
struct sk_buff *skb;
- struct cpmac_desc *desc;
- int received = 0;
+ struct cpmac_desc *desc, *restart;
struct cpmac_priv *priv = container_of(napi, struct cpmac_priv, napi);
+ int received = 0, processed = 0;
spin_lock(&priv->rx_lock);
if (unlikely(!priv->rx_head)) {
if (netif_msg_rx_err(priv) && net_ratelimit())
printk(KERN_WARNING "%s: rx: polling, but no queue\n",
priv->dev->name);
+ spin_unlock(&priv->rx_lock);
netif_rx_complete(priv->dev, napi);
return 0;
}
desc = priv->rx_head;
+ restart = NULL;
while (((desc->dataflags & CPMAC_OWN) == 0) && (received < budget)) {
+ processed++;
+
+ if ((desc->dataflags & CPMAC_EOQ) != 0) {
+ /* The last update to eoq->hw_next didn't happen
+ * soon enough, and the receiver stopped here.
+ *Remember this descriptor so we can restart
+ * the receiver after freeing some space.
+ */
+ if (unlikely(restart)) {
+ if (netif_msg_rx_err(priv))
+ printk(KERN_ERR "%s: poll found a"
+ " duplicate EOQ: %p and %p\n",
+ priv->dev->name, restart, desc);
+ goto fatal_error;
+ }
+
+ restart = desc->next;
+ }
+
skb = cpmac_rx_one(priv, desc);
if (likely(skb)) {
netif_receive_skb(skb);
@@ -435,19 +469,90 @@ static int cpmac_poll(struct napi_struct *napi, int budget)
desc = desc->next;
}
+ if (desc != priv->rx_head) {
+ /* We freed some buffers, but not the whole ring,
+ * add what we did free to the rx list */
+ desc->prev->hw_next = (u32)0;
+ priv->rx_head->prev->hw_next = priv->rx_head->mapping;
+ }
+
+ /* Optimization: If we did not actually process an EOQ (perhaps because
+ * of quota limits), check to see if the tail of the queue has EOQ set.
+ * We should immediately restart in that case so that the receiver can
+ * restart and run in parallel with more packet processing.
+ * This lets us handle slightly larger bursts before running
+ * out of ring space (assuming dev->weight < ring_size) */
+
+ if (!restart &&
+ (priv->rx_head->prev->dataflags & (CPMAC_OWN|CPMAC_EOQ))
+ == CPMAC_EOQ &&
+ (priv->rx_head->dataflags & CPMAC_OWN) != 0) {
+ /* reset EOQ so the poll loop (above) doesn't try to
+ * restart this when it eventually gets to this descriptor.
+ */
+ priv->rx_head->prev->dataflags &= ~CPMAC_EOQ;
+ restart = priv->rx_head;
+ }
+
+ if (restart) {
+ priv->dev->stats.rx_errors++;
+ priv->dev->stats.rx_fifo_errors++;
+ if (netif_msg_rx_err(priv) && net_ratelimit())
+ printk(KERN_WARNING "%s: rx dma ring overrun\n",
+ priv->dev->name);
+
+ if (unlikely((restart->dataflags & CPMAC_OWN) == 0)) {
+ if (netif_msg_drv(priv))
+ printk(KERN_ERR "%s: cpmac_poll is trying to "
+ "restart rx from a descriptor that's "
+ "not free: %p\n",
+ priv->dev->name, restart);
+ goto fatal_error;
+ }
+
+ cpmac_write(priv->regs, CPMAC_RX_PTR(0), restart->mapping);
+ }
+
priv->rx_head = desc;
spin_unlock(&priv->rx_lock);
if (unlikely(netif_msg_rx_status(priv)))
printk(KERN_DEBUG "%s: poll processed %d packets\n",
priv->dev->name, received);
- if (desc->dataflags & CPMAC_OWN) {
+ if (processed == 0) {
+ /* we ran out of packets to read,
+ * revert to interrupt-driven mode */
netif_rx_complete(priv->dev, napi);
- cpmac_write(priv->regs, CPMAC_RX_PTR(0), (u32)desc->mapping);
cpmac_write(priv->regs, CPMAC_RX_INT_ENABLE, 1);
return 0;
}
return 1;
+
+fatal_error:
+ /* Something went horribly wrong.
+ * Reset hardware to try to recover rather than wedging. */
+
+ if (netif_msg_drv(priv)) {
+ printk(KERN_ERR "%s: cpmac_poll is confused. "
+ "Resetting hardware\n", priv->dev->name);
+ cpmac_dump_all_desc(priv->dev);
+ printk(KERN_DEBUG "%s: RX_PTR(0)=0x%08x RX_ACK(0)=0x%08x\n",
+ priv->dev->name,
+ cpmac_read(priv->regs, CPMAC_RX_PTR(0)),
+ cpmac_read(priv->regs, CPMAC_RX_ACK(0)));
+ }
+
+ spin_unlock(&priv->rx_lock);
+ netif_rx_complete(priv->dev, napi);
+ netif_stop_queue(priv->dev);
+ napi_disable(&priv->napi);
+
+ atomic_inc(&priv->reset_pending);
+ cpmac_hw_stop(priv->dev);
+ if (!schedule_work(&priv->reset_work))
+ atomic_dec(&priv->reset_pending);
+ return 0;
+
}
static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -456,6 +561,9 @@ static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct cpmac_desc *desc;
struct cpmac_priv *priv = netdev_priv(dev);
+ if (unlikely(atomic_read(&priv->reset_pending)))
+ return NETDEV_TX_BUSY;
+
if (unlikely(skb_padto(skb, ETH_ZLEN)))
return NETDEV_TX_OK;
@@ -621,8 +729,10 @@ static void cpmac_clear_rx(struct net_device *dev)
desc->dataflags = CPMAC_OWN;
dev->stats.rx_dropped++;
}
+ desc->hw_next = desc->next->mapping;
desc = desc->next;
}
+ priv->rx_head->prev->hw_next = 0;
}
static void cpmac_clear_tx(struct net_device *dev)
@@ -635,14 +745,14 @@ static void cpmac_clear_tx(struct net_device *dev)
priv->desc_ring[i].dataflags = 0;
if (priv->desc_ring[i].skb) {
dev_kfree_skb_any(priv->desc_ring[i].skb);
- if (netif_subqueue_stopped(dev, i))
- netif_wake_subqueue(dev, i);
+ priv->desc_ring[i].skb = NULL;
}
}
}
static void cpmac_hw_error(struct work_struct *work)
{
+ int i;
struct cpmac_priv *priv =
container_of(work, struct cpmac_priv, reset_work);
@@ -651,8 +761,48 @@ static void cpmac_hw_error(struct work_struct *work)
spin_unlock(&priv->rx_lock);
cpmac_clear_tx(priv->dev);
cpmac_hw_start(priv->dev);
- napi_enable(&priv->napi);
- netif_start_queue(priv->dev);
+ barrier();
+ atomic_dec(&priv->reset_pending);
+
+ for (i = 0; i < CPMAC_QUEUES; i++)
+ netif_wake_subqueue(priv->dev, i);
+ netif_wake_queue(priv->dev);
+ cpmac_write(priv->regs, CPMAC_MAC_INT_ENABLE, 3);
+}
+
+static void cpmac_check_status(struct net_device *dev)
+{
+ struct cpmac_priv *priv = netdev_priv(dev);
+
+ u32 macstatus = cpmac_read(priv->regs, CPMAC_MAC_STATUS);
+ int rx_channel = (macstatus >> 8) & 7;
+ int rx_code = (macstatus >> 12) & 15;
+ int tx_channel = (macstatus >> 16) & 7;
+ int tx_code = (macstatus >> 20) & 15;
+
+ if (rx_code || tx_code) {
+ if (netif_msg_drv(priv) && net_ratelimit()) {
+ /* Can't find any documentation on what these
+ *error codes actually are. So just log them and hope..
+ */
+ if (rx_code)
+ printk(KERN_WARNING "%s: host error %d on rx "
+ "channel %d (macstatus %08x), resetting\n",
+ dev->name, rx_code, rx_channel, macstatus);
+ if (tx_code)
+ printk(KERN_WARNING "%s: host error %d on tx "
+ "channel %d (macstatus %08x), resetting\n",
+ dev->name, tx_code, tx_channel, macstatus);
+ }
+
+ netif_stop_queue(dev);
+ cpmac_hw_stop(dev);
+ if (schedule_work(&priv->reset_work))
+ atomic_inc(&priv->reset_pending);
+ if (unlikely(netif_msg_hw(priv)))
+ cpmac_dump_regs(dev);
+ }
+ cpmac_write(priv->regs, CPMAC_MAC_INT_CLEAR, 0xff);
}
static irqreturn_t cpmac_irq(int irq, void *dev_id)
@@ -683,49 +833,32 @@ static irqreturn_t cpmac_irq(int irq, void *dev_id)
cpmac_write(priv->regs, CPMAC_MAC_EOI_VECTOR, 0);
- if (unlikely(status & (MAC_INT_HOST | MAC_INT_STATUS))) {
- if (netif_msg_drv(priv) && net_ratelimit())
- printk(KERN_ERR "%s: hw error, resetting...\n",
- dev->name);
- netif_stop_queue(dev);
- napi_disable(&priv->napi);
- cpmac_hw_stop(dev);
- schedule_work(&priv->reset_work);
- if (unlikely(netif_msg_hw(priv)))
- cpmac_dump_regs(dev);
- }
+ if (unlikely(status & (MAC_INT_HOST | MAC_INT_STATUS)))
+ cpmac_check_status(dev);
return IRQ_HANDLED;
}
static void cpmac_tx_timeout(struct net_device *dev)
{
- struct cpmac_priv *priv = netdev_priv(dev);
int i;
+ struct cpmac_priv *priv = netdev_priv(dev);
spin_lock(&priv->lock);
dev->stats.tx_errors++;
spin_unlock(&priv->lock);
if (netif_msg_tx_err(priv) && net_ratelimit())
printk(KERN_WARNING "%s: transmit timeout\n", dev->name);
- /*
- * FIXME: waking up random queue is not the best thing to
- * do... on the other hand why we got here at all?
- */
-#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+
+ atomic_inc(&priv->reset_pending);
+ barrier();
+ cpmac_clear_tx(dev);
+ barrier();
+ atomic_dec(&priv->reset_pending);
+
+ netif_wake_queue(priv->dev);
for (i = 0; i < CPMAC_QUEUES; i++)
- if (priv->desc_ring[i].skb) {
- priv->desc_ring[i].dataflags = 0;
- dev_kfree_skb_any(priv->desc_ring[i].skb);
- netif_wake_subqueue(dev, i);
- break;
- }
-#else
- priv->desc_ring[0].dataflags = 0;
- if (priv->desc_ring[0].skb)
- dev_kfree_skb_any(priv->desc_ring[0].skb);
- netif_wake_queue(dev);
-#endif
+ netif_wake_subqueue(dev, i);
}
static int cpmac_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -901,9 +1034,12 @@ static int cpmac_open(struct net_device *dev)
desc->buflen = CPMAC_SKB_SIZE;
desc->dataflags = CPMAC_OWN;
desc->next = &priv->rx_head[(i + 1) % priv->ring_size];
+ desc->next->prev = desc;
desc->hw_next = (u32)desc->next->mapping;
}
+ priv->rx_head->prev->hw_next = (u32)0;
+
if ((res = request_irq(dev->irq, cpmac_irq, IRQF_SHARED,
dev->name, dev))) {
if (netif_msg_drv(priv))
@@ -912,6 +1048,7 @@ static int cpmac_open(struct net_device *dev)
goto fail_irq;
}
+ atomic_set(&priv->reset_pending, 0);
INIT_WORK(&priv->reset_work, cpmac_hw_error);
cpmac_hw_start(dev);
@@ -1007,21 +1144,10 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
if (phy_id == PHY_MAX_ADDR) {
if (external_switch || dumb_switch) {
- struct fixed_phy_status status = {};
-
- /*
- * FIXME: this should be in the platform code!
- * Since there is not platform code at all (that is,
- * no mainline users of that driver), place it here
- * for now.
- */
- phy_id = 0;
- status.link = 1;
- status.duplex = 1;
- status.speed = 100;
- fixed_phy_add(PHY_POLL, phy_id, &status);
+ mdio_bus_id = 0; /* fixed phys bus */
+ phy_id = pdev->id;
} else {
- printk(KERN_ERR "cpmac: no PHY present\n");
+ dev_err(&pdev->dev, "no PHY present\n");
return -ENODEV;
}
}
@@ -1064,10 +1190,8 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
priv->msg_enable = netif_msg_init(debug_level, 0xff);
memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr));
- snprintf(priv->phy_name, BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
-
- priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0,
- PHY_INTERFACE_MODE_MII);
+ priv->phy = phy_connect(dev, cpmac_mii.phy_map[phy_id]->dev.bus_id,
+ &cpmac_adjust_link, 0, PHY_INTERFACE_MODE_MII);
if (IS_ERR(priv->phy)) {
if (netif_msg_drv(priv))
printk(KERN_ERR "%s: Could not attach to PHY\n",
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index 348371fda597..fba87abe78ee 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -1394,7 +1394,11 @@ net_open(struct net_device *dev)
#endif
if (!result) {
printk(KERN_ERR "%s: EEPROM is configured for unavailable media\n", dev->name);
- release_irq:
+release_dma:
+#if ALLOW_DMA
+ free_dma(dev->dma);
+#endif
+release_irq:
#if ALLOW_DMA
release_dma_buff(lp);
#endif
@@ -1442,12 +1446,12 @@ net_open(struct net_device *dev)
if ((result = detect_bnc(dev)) != DETECTED_NONE)
break;
printk(KERN_ERR "%s: no media detected\n", dev->name);
- goto release_irq;
+ goto release_dma;
}
switch(result) {
case DETECTED_NONE:
printk(KERN_ERR "%s: no network cable attached to configured media\n", dev->name);
- goto release_irq;
+ goto release_dma;
case DETECTED_RJ45H:
printk(KERN_INFO "%s: using half-duplex 10Base-T (RJ-45)\n", dev->name);
break;
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index d45bcd2660af..864295e081b6 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -903,7 +903,7 @@ dm9000_stop(struct net_device *ndev)
if (netif_msg_ifdown(db))
dev_dbg(db->dev, "shutting down %s\n", ndev->name);
- cancel_delayed_work(&db->phy_poll);
+ cancel_delayed_work_sync(&db->phy_poll);
netif_stop_queue(ndev);
netif_carrier_off(ndev);
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 8cbb40f3a506..cab1835173cd 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -4201,8 +4201,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
struct e1000_adapter *adapter;
struct e1000_hw *hw;
const struct e1000_info *ei = e1000_info_tbl[ent->driver_data];
- unsigned long mmio_start, mmio_len;
- unsigned long flash_start, flash_len;
+ resource_size_t mmio_start, mmio_len;
+ resource_size_t flash_start, flash_len;
static int cards_found;
int i, err, pci_using_dac;
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index d1b6d4e7495d..287a61918739 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -2213,8 +2213,6 @@ static void ehea_vlan_rx_register(struct net_device *dev,
goto out;
}
- memset(cb1->vlan_filter, 0, sizeof(cb1->vlan_filter));
-
hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
H_PORT_CB1, H_PORT_CB1_ALL, cb1);
if (hret != H_SUCCESS)
@@ -3178,11 +3176,12 @@ out_err:
static void ehea_shutdown_single_port(struct ehea_port *port)
{
+ struct ehea_adapter *adapter = port->adapter;
unregister_netdev(port->netdev);
ehea_unregister_port(port);
kfree(port->mc_list);
free_netdev(port->netdev);
- port->adapter->active_ports--;
+ adapter->active_ports--;
}
static int ehea_setup_ports(struct ehea_adapter *adapter)
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 35f66d4a4595..9eca97fb0a54 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -5823,6 +5823,7 @@ static int nv_resume(struct pci_dev *pdev)
writel(txreg, base + NvRegTransmitPoll);
rc = nv_open(dev);
+ nv_set_multicast(dev);
out:
return rc;
}
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 67b4b0728fce..a5baaf59ff66 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -1093,7 +1093,7 @@ err:
if (registered)
unregister_netdev(ndev);
- if (fep != NULL) {
+ if (fep && fep->ops) {
(*fep->ops->free_bd)(ndev);
(*fep->ops->cleanup_data)(ndev);
}
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index f90515935833..45ae9d1191d7 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -1340,9 +1340,10 @@ static unsigned int scc_set_param(struct scc_channel *scc, unsigned int cmd, uns
case PARAM_RTS:
if ( !(scc->wreg[R5] & RTS) )
{
- if (arg != TX_OFF)
+ if (arg != TX_OFF) {
scc_key_trx(scc, TX_ON);
scc_start_tx_timer(scc, t_txdelay, scc->kiss.txdelay);
+ }
} else {
if (arg == TX_OFF)
{
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index c91b12ea26ad..e0d76c75aea0 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -75,7 +75,7 @@
#include "myri10ge_mcp.h"
#include "myri10ge_mcp_gen_header.h"
-#define MYRI10GE_VERSION_STR "1.3.2-1.287"
+#define MYRI10GE_VERSION_STR "1.3.99-1.347"
MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -631,7 +631,7 @@ static int myri10ge_adopt_running_firmware(struct myri10ge_priv *mgp)
return status;
}
-int myri10ge_get_firmware_capabilities(struct myri10ge_priv *mgp)
+static int myri10ge_get_firmware_capabilities(struct myri10ge_priv *mgp)
{
struct myri10ge_cmd cmd;
int status;
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 8f328a03847b..a550c9bd126f 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -391,7 +391,9 @@ static int fmvj18x_config(struct pcmcia_device *link)
cardtype = CONTEC;
break;
case MANFID_FUJITSU:
- if (link->card_id == PRODID_FUJITSU_MBH10302)
+ if (link->conf.ConfigBase == 0x0fe0)
+ cardtype = MBH10302;
+ else if (link->card_id == PRODID_FUJITSU_MBH10302)
/* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302),
but these are MBH10304 based card. */
cardtype = MBH10304;
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index d041f831a18d..f6c4698ce738 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -1461,22 +1461,25 @@ static void
set_multicast_list(struct net_device *dev)
{
unsigned int ioaddr = dev->base_addr;
+ unsigned value;
SelectPage(0x42);
+ value = GetByte(XIRCREG42_SWC1) & 0xC0;
+
if (dev->flags & IFF_PROMISC) { /* snoop */
- PutByte(XIRCREG42_SWC1, 0x06); /* set MPE and PME */
+ PutByte(XIRCREG42_SWC1, value | 0x06); /* set MPE and PME */
} else if (dev->mc_count > 9 || (dev->flags & IFF_ALLMULTI)) {
- PutByte(XIRCREG42_SWC1, 0x02); /* set MPE */
+ PutByte(XIRCREG42_SWC1, value | 0x02); /* set MPE */
} else if (dev->mc_count) {
/* the chip can filter 9 addresses perfectly */
- PutByte(XIRCREG42_SWC1, 0x01);
+ PutByte(XIRCREG42_SWC1, value | 0x01);
SelectPage(0x40);
PutByte(XIRCREG40_CMD0, Offline);
set_addresses(dev);
SelectPage(0x40);
PutByte(XIRCREG40_CMD0, EnableRecv | Online);
} else { /* standard usage */
- PutByte(XIRCREG42_SWC1, 0x00);
+ PutByte(XIRCREG42_SWC1, value | 0x00);
}
SelectPage(0);
}
@@ -1722,6 +1725,7 @@ do_reset(struct net_device *dev, int full)
/* enable receiver and put the mac online */
if (full) {
+ set_multicast_list(dev);
SelectPage(0x40);
PutByte(XIRCREG40_CMD0, EnableRecv | Online);
}
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index a1c454dbc164..1c89b97f4e09 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -325,7 +325,7 @@ static int pcnet32_get_regs_len(struct net_device *dev);
static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *ptr);
static void pcnet32_purge_tx_ring(struct net_device *dev);
-static int pcnet32_alloc_ring(struct net_device *dev, char *name);
+static int pcnet32_alloc_ring(struct net_device *dev, const char *name);
static void pcnet32_free_ring(struct net_device *dev);
static void pcnet32_check_media(struct net_device *dev, int verbose);
@@ -1983,7 +1983,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
}
/* if any allocation fails, caller must also call pcnet32_free_ring */
-static int pcnet32_alloc_ring(struct net_device *dev, char *name)
+static int pcnet32_alloc_ring(struct net_device *dev, const char *name)
{
struct pcnet32_private *lp = netdev_priv(dev);
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 6bf9e76b0a00..6eb2d31d1e34 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -5,7 +5,7 @@
menuconfig PHYLIB
tristate "PHY Device support and infrastructure"
depends on !S390
- depends on NET_ETHERNET && (BROKEN || !S390)
+ depends on NET_ETHERNET
help
Ethernet controllers are usually attached to PHY
devices. This option provides infrastructure for
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index ac3c01d28fdf..16a0e7de5888 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -207,6 +207,7 @@ int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id)
return 0;
}
+EXPORT_SYMBOL(get_phy_id);
/**
* get_phy_device - reads the specified PHY device and returns its @phy_device struct
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c
index 8db342f2fdc9..70cfdb46aa27 100644
--- a/drivers/net/pppol2tp.c
+++ b/drivers/net/pppol2tp.c
@@ -240,12 +240,15 @@ static inline struct pppol2tp_session *pppol2tp_sock_to_session(struct sock *sk)
if (sk == NULL)
return NULL;
+ sock_hold(sk);
session = (struct pppol2tp_session *)(sk->sk_user_data);
- if (session == NULL)
- return NULL;
+ if (session == NULL) {
+ sock_put(sk);
+ goto out;
+ }
BUG_ON(session->magic != L2TP_SESSION_MAGIC);
-
+out:
return session;
}
@@ -256,12 +259,15 @@ static inline struct pppol2tp_tunnel *pppol2tp_sock_to_tunnel(struct sock *sk)
if (sk == NULL)
return NULL;
+ sock_hold(sk);
tunnel = (struct pppol2tp_tunnel *)(sk->sk_user_data);
- if (tunnel == NULL)
- return NULL;
+ if (tunnel == NULL) {
+ sock_put(sk);
+ goto out;
+ }
BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC);
-
+out:
return tunnel;
}
@@ -716,12 +722,14 @@ discard:
session->stats.rx_errors++;
kfree_skb(skb);
sock_put(session->sock);
+ sock_put(sock);
return 0;
error:
/* Put UDP header back */
__skb_push(skb, sizeof(struct udphdr));
+ sock_put(sock);
no_tunnel:
return 1;
@@ -745,10 +753,13 @@ static int pppol2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
"%s: received %d bytes\n", tunnel->name, skb->len);
if (pppol2tp_recv_core(sk, skb))
- goto pass_up;
+ goto pass_up_put;
+ sock_put(sk);
return 0;
+pass_up_put:
+ sock_put(sk);
pass_up:
return 1;
}
@@ -858,7 +869,7 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh
tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock);
if (tunnel == NULL)
- goto error;
+ goto error_put_sess;
/* What header length is configured for this session? */
hdr_len = pppol2tp_l2tp_header_len(session);
@@ -870,7 +881,7 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh
sizeof(ppph) + total_len,
0, GFP_KERNEL);
if (!skb)
- goto error;
+ goto error_put_sess_tun;
/* Reserve space for headers. */
skb_reserve(skb, NET_SKB_PAD);
@@ -900,7 +911,7 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh
error = memcpy_fromiovec(skb->data, m->msg_iov, total_len);
if (error < 0) {
kfree_skb(skb);
- goto error;
+ goto error_put_sess_tun;
}
skb_put(skb, total_len);
@@ -947,10 +958,33 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh
session->stats.tx_errors++;
}
+ return error;
+
+error_put_sess_tun:
+ sock_put(session->tunnel_sock);
+error_put_sess:
+ sock_put(sk);
error:
return error;
}
+/* Automatically called when the skb is freed.
+ */
+static void pppol2tp_sock_wfree(struct sk_buff *skb)
+{
+ sock_put(skb->sk);
+}
+
+/* For data skbs that we transmit, we associate with the tunnel socket
+ * but don't do accounting.
+ */
+static inline void pppol2tp_skb_set_owner_w(struct sk_buff *skb, struct sock *sk)
+{
+ sock_hold(sk);
+ skb->sk = sk;
+ skb->destructor = pppol2tp_sock_wfree;
+}
+
/* Transmit function called by generic PPP driver. Sends PPP frame
* over PPPoL2TP socket.
*
@@ -993,10 +1027,10 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
sk_tun = session->tunnel_sock;
if (sk_tun == NULL)
- goto abort;
+ goto abort_put_sess;
tunnel = pppol2tp_sock_to_tunnel(sk_tun);
if (tunnel == NULL)
- goto abort;
+ goto abort_put_sess;
/* What header length is configured for this session? */
hdr_len = pppol2tp_l2tp_header_len(session);
@@ -1009,7 +1043,7 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
sizeof(struct udphdr) + hdr_len + sizeof(ppph);
old_headroom = skb_headroom(skb);
if (skb_cow_head(skb, headroom))
- goto abort;
+ goto abort_put_sess_tun;
new_headroom = skb_headroom(skb);
skb_orphan(skb);
@@ -1069,7 +1103,7 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
/* Get routing info from the tunnel socket */
dst_release(skb->dst);
skb->dst = dst_clone(__sk_dst_get(sk_tun));
- skb->sk = sk_tun;
+ pppol2tp_skb_set_owner_w(skb, sk_tun);
/* Queue the packet to IP for output */
len = skb->len;
@@ -1086,8 +1120,14 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
session->stats.tx_errors++;
}
+ sock_put(sk_tun);
+ sock_put(sk);
return 1;
+abort_put_sess_tun:
+ sock_put(sk_tun);
+abort_put_sess:
+ sock_put(sk);
abort:
/* Free the original skb */
kfree_skb(skb);
@@ -1191,7 +1231,7 @@ static void pppol2tp_tunnel_destruct(struct sock *sk)
{
struct pppol2tp_tunnel *tunnel;
- tunnel = pppol2tp_sock_to_tunnel(sk);
+ tunnel = sk->sk_user_data;
if (tunnel == NULL)
goto end;
@@ -1230,10 +1270,12 @@ static void pppol2tp_session_destruct(struct sock *sk)
if (sk->sk_user_data != NULL) {
struct pppol2tp_tunnel *tunnel;
- session = pppol2tp_sock_to_session(sk);
+ session = sk->sk_user_data;
if (session == NULL)
goto out;
+ BUG_ON(session->magic != L2TP_SESSION_MAGIC);
+
/* Don't use pppol2tp_sock_to_tunnel() here to
* get the tunnel context because the tunnel
* socket might have already been closed (its
@@ -1279,6 +1321,7 @@ out:
static int pppol2tp_release(struct socket *sock)
{
struct sock *sk = sock->sk;
+ struct pppol2tp_session *session;
int error;
if (!sk)
@@ -1296,9 +1339,18 @@ static int pppol2tp_release(struct socket *sock)
sock_orphan(sk);
sock->sk = NULL;
+ session = pppol2tp_sock_to_session(sk);
+
/* Purge any queued data */
skb_queue_purge(&sk->sk_receive_queue);
skb_queue_purge(&sk->sk_write_queue);
+ if (session != NULL) {
+ struct sk_buff *skb;
+ while ((skb = skb_dequeue(&session->reorder_q))) {
+ kfree_skb(skb);
+ sock_put(sk);
+ }
+ }
release_sock(sk);
@@ -1601,7 +1653,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
error = ppp_register_channel(&po->chan);
if (error)
- goto end;
+ goto end_put_tun;
/* This is how we get the session context from the socket. */
sk->sk_user_data = session;
@@ -1621,6 +1673,8 @@ out_no_ppp:
PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
"%s: created\n", session->name);
+end_put_tun:
+ sock_put(tunnel_sock);
end:
release_sock(sk);
@@ -1668,6 +1722,7 @@ static int pppol2tp_getname(struct socket *sock, struct sockaddr *uaddr,
*usockaddr_len = len;
error = 0;
+ sock_put(sock->sk);
end:
return error;
@@ -1906,14 +1961,17 @@ static int pppol2tp_ioctl(struct socket *sock, unsigned int cmd,
err = -EBADF;
tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock);
if (tunnel == NULL)
- goto end;
+ goto end_put_sess;
err = pppol2tp_tunnel_ioctl(tunnel, cmd, arg);
- goto end;
+ sock_put(session->tunnel_sock);
+ goto end_put_sess;
}
err = pppol2tp_session_ioctl(session, cmd, arg);
+end_put_sess:
+ sock_put(sk);
end:
return err;
}
@@ -2059,14 +2117,17 @@ static int pppol2tp_setsockopt(struct socket *sock, int level, int optname,
err = -EBADF;
tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock);
if (tunnel == NULL)
- goto end;
+ goto end_put_sess;
err = pppol2tp_tunnel_setsockopt(sk, tunnel, optname, val);
+ sock_put(session->tunnel_sock);
} else
err = pppol2tp_session_setsockopt(sk, session, optname, val);
err = 0;
+end_put_sess:
+ sock_put(sk);
end:
return err;
}
@@ -2181,20 +2242,24 @@ static int pppol2tp_getsockopt(struct socket *sock, int level,
err = -EBADF;
tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock);
if (tunnel == NULL)
- goto end;
+ goto end_put_sess;
err = pppol2tp_tunnel_getsockopt(sk, tunnel, optname, &val);
+ sock_put(session->tunnel_sock);
} else
err = pppol2tp_session_getsockopt(sk, session, optname, &val);
err = -EFAULT;
if (put_user(len, (int __user *) optlen))
- goto end;
+ goto end_put_sess;
if (copy_to_user((void __user *) optval, &val, len))
- goto end;
+ goto end_put_sess;
err = 0;
+
+end_put_sess:
+ sock_put(sk);
end:
return err;
}
diff --git a/drivers/net/s2io-regs.h b/drivers/net/s2io-regs.h
index 2109508c047a..f8274f8941ea 100644
--- a/drivers/net/s2io-regs.h
+++ b/drivers/net/s2io-regs.h
@@ -250,7 +250,7 @@ struct XENA_dev_config {
u64 tx_mat0_n[0x8];
#define TX_MAT_SET(fifo, msi) vBIT(msi, (8 * fifo), 8)
- u8 unused_1[0x8];
+ u64 xmsi_mask_reg;
u64 stat_byte_cnt;
#define STAT_BC(n) vBIT(n,4,12)
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 523478ebfd69..b5c1e663417d 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -86,7 +86,7 @@
#include "s2io.h"
#include "s2io-regs.h"
-#define DRV_VERSION "2.0.26.23"
+#define DRV_VERSION "2.0.26.24"
/* S2io Driver name & version. */
static char s2io_driver_name[] = "Neterion";
@@ -1113,9 +1113,10 @@ static int s2io_on_nec_bridge(struct pci_dev *s2io_pdev)
struct pci_dev *tdev = NULL;
while ((tdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, tdev)) != NULL) {
if (tdev->vendor == NEC_VENID && tdev->device == NEC_DEVID) {
- if (tdev->bus == s2io_pdev->bus->parent)
+ if (tdev->bus == s2io_pdev->bus->parent) {
pci_dev_put(tdev);
return 1;
+ }
}
}
return 0;
@@ -1219,15 +1220,33 @@ static int init_tti(struct s2io_nic *nic, int link)
TTI_DATA1_MEM_TX_URNG_B(0x10) |
TTI_DATA1_MEM_TX_URNG_C(0x30) |
TTI_DATA1_MEM_TX_TIMER_AC_EN;
-
- if (use_continuous_tx_intrs && (link == LINK_UP))
- val64 |= TTI_DATA1_MEM_TX_TIMER_CI_EN;
+ if (i == 0)
+ if (use_continuous_tx_intrs && (link == LINK_UP))
+ val64 |= TTI_DATA1_MEM_TX_TIMER_CI_EN;
writeq(val64, &bar0->tti_data1_mem);
- val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) |
- TTI_DATA2_MEM_TX_UFC_B(0x20) |
- TTI_DATA2_MEM_TX_UFC_C(0x40) |
- TTI_DATA2_MEM_TX_UFC_D(0x80);
+ if (nic->config.intr_type == MSI_X) {
+ val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) |
+ TTI_DATA2_MEM_TX_UFC_B(0x100) |
+ TTI_DATA2_MEM_TX_UFC_C(0x200) |
+ TTI_DATA2_MEM_TX_UFC_D(0x300);
+ } else {
+ if ((nic->config.tx_steering_type ==
+ TX_DEFAULT_STEERING) &&
+ (config->tx_fifo_num > 1) &&
+ (i >= nic->udp_fifo_idx) &&
+ (i < (nic->udp_fifo_idx +
+ nic->total_udp_fifos)))
+ val64 = TTI_DATA2_MEM_TX_UFC_A(0x50) |
+ TTI_DATA2_MEM_TX_UFC_B(0x80) |
+ TTI_DATA2_MEM_TX_UFC_C(0x100) |
+ TTI_DATA2_MEM_TX_UFC_D(0x120);
+ else
+ val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) |
+ TTI_DATA2_MEM_TX_UFC_B(0x20) |
+ TTI_DATA2_MEM_TX_UFC_C(0x40) |
+ TTI_DATA2_MEM_TX_UFC_D(0x80);
+ }
writeq(val64, &bar0->tti_data2_mem);
@@ -2813,6 +2832,15 @@ static void free_rx_buffers(struct s2io_nic *sp)
}
}
+static int s2io_chk_rx_buffers(struct ring_info *ring)
+{
+ if (fill_rx_buffers(ring) == -ENOMEM) {
+ DBG_PRINT(INFO_DBG, "%s:Out of memory", ring->dev->name);
+ DBG_PRINT(INFO_DBG, " in Rx Intr!!\n");
+ }
+ return 0;
+}
+
/**
* s2io_poll - Rx interrupt handler for NAPI support
* @napi : pointer to the napi structure.
@@ -2826,57 +2854,73 @@ static void free_rx_buffers(struct s2io_nic *sp)
* 0 on success and 1 if there are No Rx packets to be processed.
*/
-static int s2io_poll(struct napi_struct *napi, int budget)
+static int s2io_poll_msix(struct napi_struct *napi, int budget)
{
- struct s2io_nic *nic = container_of(napi, struct s2io_nic, napi);
- struct net_device *dev = nic->dev;
- int pkt_cnt = 0, org_pkts_to_process;
- struct mac_info *mac_control;
+ struct ring_info *ring = container_of(napi, struct ring_info, napi);
+ struct net_device *dev = ring->dev;
struct config_param *config;
+ struct mac_info *mac_control;
+ int pkts_processed = 0;
+ u8 __iomem *addr = NULL;
+ u8 val8 = 0;
+ struct s2io_nic *nic = dev->priv;
struct XENA_dev_config __iomem *bar0 = nic->bar0;
- int i;
+ int budget_org = budget;
- mac_control = &nic->mac_control;
config = &nic->config;
+ mac_control = &nic->mac_control;
- nic->pkts_to_process = budget;
- org_pkts_to_process = nic->pkts_to_process;
+ if (unlikely(!is_s2io_card_up(nic)))
+ return 0;
- writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int);
- readl(&bar0->rx_traffic_int);
+ pkts_processed = rx_intr_handler(ring, budget);
+ s2io_chk_rx_buffers(ring);
- for (i = 0; i < config->rx_ring_num; i++) {
- rx_intr_handler(&mac_control->rings[i]);
- pkt_cnt = org_pkts_to_process - nic->pkts_to_process;
- if (!nic->pkts_to_process) {
- /* Quota for the current iteration has been met */
- goto no_rx;
- }
+ if (pkts_processed < budget_org) {
+ netif_rx_complete(dev, napi);
+ /*Re Enable MSI-Rx Vector*/
+ addr = (u8 __iomem *)&bar0->xmsi_mask_reg;
+ addr += 7 - ring->ring_no;
+ val8 = (ring->ring_no == 0) ? 0x3f : 0xbf;
+ writeb(val8, addr);
+ val8 = readb(addr);
}
+ return pkts_processed;
+}
+static int s2io_poll_inta(struct napi_struct *napi, int budget)
+{
+ struct s2io_nic *nic = container_of(napi, struct s2io_nic, napi);
+ struct ring_info *ring;
+ struct net_device *dev = nic->dev;
+ struct config_param *config;
+ struct mac_info *mac_control;
+ int pkts_processed = 0;
+ int ring_pkts_processed, i;
+ struct XENA_dev_config __iomem *bar0 = nic->bar0;
+ int budget_org = budget;
- netif_rx_complete(dev, napi);
+ config = &nic->config;
+ mac_control = &nic->mac_control;
- for (i = 0; i < config->rx_ring_num; i++) {
- if (fill_rx_buffers(&mac_control->rings[i]) == -ENOMEM) {
- DBG_PRINT(INFO_DBG, "%s:Out of memory", dev->name);
- DBG_PRINT(INFO_DBG, " in Rx Poll!!\n");
- break;
- }
- }
- /* Re enable the Rx interrupts. */
- writeq(0x0, &bar0->rx_traffic_mask);
- readl(&bar0->rx_traffic_mask);
- return pkt_cnt;
+ if (unlikely(!is_s2io_card_up(nic)))
+ return 0;
-no_rx:
for (i = 0; i < config->rx_ring_num; i++) {
- if (fill_rx_buffers(&mac_control->rings[i]) == -ENOMEM) {
- DBG_PRINT(INFO_DBG, "%s:Out of memory", dev->name);
- DBG_PRINT(INFO_DBG, " in Rx Poll!!\n");
+ ring = &mac_control->rings[i];
+ ring_pkts_processed = rx_intr_handler(ring, budget);
+ s2io_chk_rx_buffers(ring);
+ pkts_processed += ring_pkts_processed;
+ budget -= ring_pkts_processed;
+ if (budget <= 0)
break;
- }
}
- return pkt_cnt;
+ if (pkts_processed < budget_org) {
+ netif_rx_complete(dev, napi);
+ /* Re enable the Rx interrupts for the ring */
+ writeq(0, &bar0->rx_traffic_mask);
+ readl(&bar0->rx_traffic_mask);
+ }
+ return pkts_processed;
}
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -2918,7 +2962,7 @@ static void s2io_netpoll(struct net_device *dev)
/* check for received packet and indicate up to network */
for (i = 0; i < config->rx_ring_num; i++)
- rx_intr_handler(&mac_control->rings[i]);
+ rx_intr_handler(&mac_control->rings[i], 0);
for (i = 0; i < config->rx_ring_num; i++) {
if (fill_rx_buffers(&mac_control->rings[i]) == -ENOMEM) {
@@ -2934,7 +2978,8 @@ static void s2io_netpoll(struct net_device *dev)
/**
* rx_intr_handler - Rx interrupt handler
- * @nic: device private variable.
+ * @ring_info: per ring structure.
+ * @budget: budget for napi processing.
* Description:
* If the interrupt is because of a received frame or if the
* receive ring contains fresh as yet un-processed frames,this function is
@@ -2942,15 +2987,15 @@ static void s2io_netpoll(struct net_device *dev)
* stopped and sends the skb to the OSM's Rx handler and then increments
* the offset.
* Return Value:
- * NONE.
+ * No. of napi packets processed.
*/
-static void rx_intr_handler(struct ring_info *ring_data)
+static int rx_intr_handler(struct ring_info *ring_data, int budget)
{
int get_block, put_block;
struct rx_curr_get_info get_info, put_info;
struct RxD_t *rxdp;
struct sk_buff *skb;
- int pkt_cnt = 0;
+ int pkt_cnt = 0, napi_pkts = 0;
int i;
struct RxD1* rxdp1;
struct RxD3* rxdp3;
@@ -2977,7 +3022,7 @@ static void rx_intr_handler(struct ring_info *ring_data)
DBG_PRINT(ERR_DBG, "%s: The skb is ",
ring_data->dev->name);
DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
- return;
+ return 0;
}
if (ring_data->rxd_mode == RXD_MODE_1) {
rxdp1 = (struct RxD1*)rxdp;
@@ -3014,9 +3059,10 @@ static void rx_intr_handler(struct ring_info *ring_data)
rxdp = ring_data->rx_blocks[get_block].block_virt_addr;
}
- if(ring_data->nic->config.napi){
- ring_data->nic->pkts_to_process -= 1;
- if (!ring_data->nic->pkts_to_process)
+ if (ring_data->nic->config.napi) {
+ budget--;
+ napi_pkts++;
+ if (!budget)
break;
}
pkt_cnt++;
@@ -3034,6 +3080,7 @@ static void rx_intr_handler(struct ring_info *ring_data)
}
}
}
+ return(napi_pkts);
}
/**
@@ -3730,14 +3777,19 @@ static void restore_xmsi_data(struct s2io_nic *nic)
{
struct XENA_dev_config __iomem *bar0 = nic->bar0;
u64 val64;
- int i;
+ int i, msix_index;
+
+
+ if (nic->device_type == XFRAME_I_DEVICE)
+ return;
for (i=0; i < MAX_REQUESTED_MSI_X; i++) {
+ msix_index = (i) ? ((i-1) * 8 + 1): 0;
writeq(nic->msix_info[i].addr, &bar0->xmsi_address);
writeq(nic->msix_info[i].data, &bar0->xmsi_data);
- val64 = (s2BIT(7) | s2BIT(15) | vBIT(i, 26, 6));
+ val64 = (s2BIT(7) | s2BIT(15) | vBIT(msix_index, 26, 6));
writeq(val64, &bar0->xmsi_access);
- if (wait_for_msix_trans(nic, i)) {
+ if (wait_for_msix_trans(nic, msix_index)) {
DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
continue;
}
@@ -3748,13 +3800,17 @@ static void store_xmsi_data(struct s2io_nic *nic)
{
struct XENA_dev_config __iomem *bar0 = nic->bar0;
u64 val64, addr, data;
- int i;
+ int i, msix_index;
+
+ if (nic->device_type == XFRAME_I_DEVICE)
+ return;
/* Store and display */
for (i=0; i < MAX_REQUESTED_MSI_X; i++) {
- val64 = (s2BIT(15) | vBIT(i, 26, 6));
+ msix_index = (i) ? ((i-1) * 8 + 1): 0;
+ val64 = (s2BIT(15) | vBIT(msix_index, 26, 6));
writeq(val64, &bar0->xmsi_access);
- if (wait_for_msix_trans(nic, i)) {
+ if (wait_for_msix_trans(nic, msix_index)) {
DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
continue;
}
@@ -3770,11 +3826,11 @@ static void store_xmsi_data(struct s2io_nic *nic)
static int s2io_enable_msi_x(struct s2io_nic *nic)
{
struct XENA_dev_config __iomem *bar0 = nic->bar0;
- u64 tx_mat, rx_mat;
+ u64 rx_mat;
u16 msi_control; /* Temp variable */
int ret, i, j, msix_indx = 1;
- nic->entries = kcalloc(MAX_REQUESTED_MSI_X, sizeof(struct msix_entry),
+ nic->entries = kmalloc(nic->num_entries * sizeof(struct msix_entry),
GFP_KERNEL);
if (!nic->entries) {
DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n", \
@@ -3783,10 +3839,12 @@ static int s2io_enable_msi_x(struct s2io_nic *nic)
return -ENOMEM;
}
nic->mac_control.stats_info->sw_stat.mem_allocated
- += (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
+ += (nic->num_entries * sizeof(struct msix_entry));
+
+ memset(nic->entries, 0, nic->num_entries * sizeof(struct msix_entry));
nic->s2io_entries =
- kcalloc(MAX_REQUESTED_MSI_X, sizeof(struct s2io_msix_entry),
+ kmalloc(nic->num_entries * sizeof(struct s2io_msix_entry),
GFP_KERNEL);
if (!nic->s2io_entries) {
DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n",
@@ -3794,60 +3852,52 @@ static int s2io_enable_msi_x(struct s2io_nic *nic)
nic->mac_control.stats_info->sw_stat.mem_alloc_fail_cnt++;
kfree(nic->entries);
nic->mac_control.stats_info->sw_stat.mem_freed
- += (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
+ += (nic->num_entries * sizeof(struct msix_entry));
return -ENOMEM;
}
nic->mac_control.stats_info->sw_stat.mem_allocated
- += (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry));
-
- for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
- nic->entries[i].entry = i;
- nic->s2io_entries[i].entry = i;
+ += (nic->num_entries * sizeof(struct s2io_msix_entry));
+ memset(nic->s2io_entries, 0,
+ nic->num_entries * sizeof(struct s2io_msix_entry));
+
+ nic->entries[0].entry = 0;
+ nic->s2io_entries[0].entry = 0;
+ nic->s2io_entries[0].in_use = MSIX_FLG;
+ nic->s2io_entries[0].type = MSIX_ALARM_TYPE;
+ nic->s2io_entries[0].arg = &nic->mac_control.fifos;
+
+ for (i = 1; i < nic->num_entries; i++) {
+ nic->entries[i].entry = ((i - 1) * 8) + 1;
+ nic->s2io_entries[i].entry = ((i - 1) * 8) + 1;
nic->s2io_entries[i].arg = NULL;
nic->s2io_entries[i].in_use = 0;
}
- tx_mat = readq(&bar0->tx_mat0_n[0]);
- for (i=0; i<nic->config.tx_fifo_num; i++, msix_indx++) {
- tx_mat |= TX_MAT_SET(i, msix_indx);
- nic->s2io_entries[msix_indx].arg = &nic->mac_control.fifos[i];
- nic->s2io_entries[msix_indx].type = MSIX_FIFO_TYPE;
- nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
- }
- writeq(tx_mat, &bar0->tx_mat0_n[0]);
-
rx_mat = readq(&bar0->rx_mat);
- for (j = 0; j < nic->config.rx_ring_num; j++, msix_indx++) {
+ for (j = 0; j < nic->config.rx_ring_num; j++) {
rx_mat |= RX_MAT_SET(j, msix_indx);
- nic->s2io_entries[msix_indx].arg
- = &nic->mac_control.rings[j];
- nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE;
- nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
+ nic->s2io_entries[j+1].arg = &nic->mac_control.rings[j];
+ nic->s2io_entries[j+1].type = MSIX_RING_TYPE;
+ nic->s2io_entries[j+1].in_use = MSIX_FLG;
+ msix_indx += 8;
}
writeq(rx_mat, &bar0->rx_mat);
+ readq(&bar0->rx_mat);
- nic->avail_msix_vectors = 0;
- ret = pci_enable_msix(nic->pdev, nic->entries, MAX_REQUESTED_MSI_X);
+ ret = pci_enable_msix(nic->pdev, nic->entries, nic->num_entries);
/* We fail init if error or we get less vectors than min required */
- if (ret >= (nic->config.tx_fifo_num + nic->config.rx_ring_num + 1)) {
- nic->avail_msix_vectors = ret;
- ret = pci_enable_msix(nic->pdev, nic->entries, ret);
- }
if (ret) {
DBG_PRINT(ERR_DBG, "%s: Enabling MSIX failed\n", nic->dev->name);
kfree(nic->entries);
nic->mac_control.stats_info->sw_stat.mem_freed
- += (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
+ += (nic->num_entries * sizeof(struct msix_entry));
kfree(nic->s2io_entries);
nic->mac_control.stats_info->sw_stat.mem_freed
- += (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry));
+ += (nic->num_entries * sizeof(struct s2io_msix_entry));
nic->entries = NULL;
nic->s2io_entries = NULL;
- nic->avail_msix_vectors = 0;
return -ENOMEM;
}
- if (!nic->avail_msix_vectors)
- nic->avail_msix_vectors = MAX_REQUESTED_MSI_X;
/*
* To enable MSI-X, MSI also needs to be enabled, due to a bug
@@ -3919,7 +3969,7 @@ static void remove_msix_isr(struct s2io_nic *sp)
int i;
u16 msi_control;
- for (i = 0; i < MAX_REQUESTED_MSI_X; i++) {
+ for (i = 0; i < sp->num_entries; i++) {
if (sp->s2io_entries[i].in_use ==
MSIX_REGISTERED_SUCCESS) {
int vector = sp->entries[i].vector;
@@ -3975,29 +4025,6 @@ static int s2io_open(struct net_device *dev)
netif_carrier_off(dev);
sp->last_link_state = 0;
- if (sp->config.intr_type == MSI_X) {
- int ret = s2io_enable_msi_x(sp);
-
- if (!ret) {
- ret = s2io_test_msi(sp);
- /* rollback MSI-X, will re-enable during add_isr() */
- remove_msix_isr(sp);
- }
- if (ret) {
-
- DBG_PRINT(ERR_DBG,
- "%s: MSI-X requested but failed to enable\n",
- dev->name);
- sp->config.intr_type = INTA;
- }
- }
-
- /* NAPI doesn't work well with MSI(X) */
- if (sp->config.intr_type != INTA) {
- if(sp->config.napi)
- sp->config.napi = 0;
- }
-
/* Initialize H/W and enable interrupts */
err = s2io_card_up(sp);
if (err) {
@@ -4020,12 +4047,12 @@ hw_init_failed:
if (sp->entries) {
kfree(sp->entries);
sp->mac_control.stats_info->sw_stat.mem_freed
- += (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
+ += (sp->num_entries * sizeof(struct msix_entry));
}
if (sp->s2io_entries) {
kfree(sp->s2io_entries);
sp->mac_control.stats_info->sw_stat.mem_freed
- += (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry));
+ += (sp->num_entries * sizeof(struct s2io_msix_entry));
}
}
return err;
@@ -4327,40 +4354,65 @@ s2io_alarm_handle(unsigned long data)
mod_timer(&sp->alarm_timer, jiffies + HZ / 2);
}
-static int s2io_chk_rx_buffers(struct ring_info *ring)
-{
- if (fill_rx_buffers(ring) == -ENOMEM) {
- DBG_PRINT(INFO_DBG, "%s:Out of memory", ring->dev->name);
- DBG_PRINT(INFO_DBG, " in Rx Intr!!\n");
- }
- return 0;
-}
-
static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id)
{
struct ring_info *ring = (struct ring_info *)dev_id;
struct s2io_nic *sp = ring->nic;
+ struct XENA_dev_config __iomem *bar0 = sp->bar0;
+ struct net_device *dev = sp->dev;
- if (!is_s2io_card_up(sp))
+ if (unlikely(!is_s2io_card_up(sp)))
return IRQ_HANDLED;
- rx_intr_handler(ring);
- s2io_chk_rx_buffers(ring);
+ if (sp->config.napi) {
+ u8 __iomem *addr = NULL;
+ u8 val8 = 0;
+
+ addr = (u8 __iomem *)&bar0->xmsi_mask_reg;
+ addr += (7 - ring->ring_no);
+ val8 = (ring->ring_no == 0) ? 0x7f : 0xff;
+ writeb(val8, addr);
+ val8 = readb(addr);
+ netif_rx_schedule(dev, &ring->napi);
+ } else {
+ rx_intr_handler(ring, 0);
+ s2io_chk_rx_buffers(ring);
+ }
return IRQ_HANDLED;
}
static irqreturn_t s2io_msix_fifo_handle(int irq, void *dev_id)
{
- struct fifo_info *fifo = (struct fifo_info *)dev_id;
- struct s2io_nic *sp = fifo->nic;
+ int i;
+ struct fifo_info *fifos = (struct fifo_info *)dev_id;
+ struct s2io_nic *sp = fifos->nic;
+ struct XENA_dev_config __iomem *bar0 = sp->bar0;
+ struct config_param *config = &sp->config;
+ u64 reason;
- if (!is_s2io_card_up(sp))
+ if (unlikely(!is_s2io_card_up(sp)))
+ return IRQ_NONE;
+
+ reason = readq(&bar0->general_int_status);
+ if (unlikely(reason == S2IO_MINUS_ONE))
+ /* Nothing much can be done. Get out */
return IRQ_HANDLED;
- tx_intr_handler(fifo);
+ writeq(S2IO_MINUS_ONE, &bar0->general_int_mask);
+
+ if (reason & GEN_INTR_TXTRAFFIC)
+ writeq(S2IO_MINUS_ONE, &bar0->tx_traffic_int);
+
+ for (i = 0; i < config->tx_fifo_num; i++)
+ tx_intr_handler(&fifos[i]);
+
+ writeq(sp->general_int_mask, &bar0->general_int_mask);
+ readl(&bar0->general_int_status);
+
return IRQ_HANDLED;
}
+
static void s2io_txpic_intr_handle(struct s2io_nic *sp)
{
struct XENA_dev_config __iomem *bar0 = sp->bar0;
@@ -4762,14 +4814,10 @@ static irqreturn_t s2io_isr(int irq, void *dev_id)
if (config->napi) {
if (reason & GEN_INTR_RXTRAFFIC) {
- if (likely(netif_rx_schedule_prep(dev,
- &sp->napi))) {
- __netif_rx_schedule(dev, &sp->napi);
- writeq(S2IO_MINUS_ONE,
- &bar0->rx_traffic_mask);
- } else
- writeq(S2IO_MINUS_ONE,
- &bar0->rx_traffic_int);
+ netif_rx_schedule(dev, &sp->napi);
+ writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_mask);
+ writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int);
+ readl(&bar0->rx_traffic_int);
}
} else {
/*
@@ -4781,7 +4829,7 @@ static irqreturn_t s2io_isr(int irq, void *dev_id)
writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int);
for (i = 0; i < config->rx_ring_num; i++)
- rx_intr_handler(&mac_control->rings[i]);
+ rx_intr_handler(&mac_control->rings[i], 0);
}
/*
@@ -6984,62 +7032,62 @@ static int s2io_add_isr(struct s2io_nic * sp)
/* After proper initialization of H/W, register ISR */
if (sp->config.intr_type == MSI_X) {
- int i, msix_tx_cnt=0,msix_rx_cnt=0;
-
- for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) {
- if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) {
- sprintf(sp->desc[i], "%s:MSI-X-%d-TX",
+ int i, msix_rx_cnt = 0;
+
+ for (i = 0; i < sp->num_entries; i++) {
+ if (sp->s2io_entries[i].in_use == MSIX_FLG) {
+ if (sp->s2io_entries[i].type ==
+ MSIX_RING_TYPE) {
+ sprintf(sp->desc[i], "%s:MSI-X-%d-RX",
+ dev->name, i);
+ err = request_irq(sp->entries[i].vector,
+ s2io_msix_ring_handle, 0,
+ sp->desc[i],
+ sp->s2io_entries[i].arg);
+ } else if (sp->s2io_entries[i].type ==
+ MSIX_ALARM_TYPE) {
+ sprintf(sp->desc[i], "%s:MSI-X-%d-TX",
dev->name, i);
- err = request_irq(sp->entries[i].vector,
- s2io_msix_fifo_handle, 0, sp->desc[i],
- sp->s2io_entries[i].arg);
- /* If either data or addr is zero print it */
- if(!(sp->msix_info[i].addr &&
- sp->msix_info[i].data)) {
- DBG_PRINT(ERR_DBG, "%s @ Addr:0x%llx "
- "Data:0x%llx\n",sp->desc[i],
- (unsigned long long)
- sp->msix_info[i].addr,
- (unsigned long long)
- sp->msix_info[i].data);
- } else {
- msix_tx_cnt++;
+ err = request_irq(sp->entries[i].vector,
+ s2io_msix_fifo_handle, 0,
+ sp->desc[i],
+ sp->s2io_entries[i].arg);
+
}
- } else {
- sprintf(sp->desc[i], "%s:MSI-X-%d-RX",
- dev->name, i);
- err = request_irq(sp->entries[i].vector,
- s2io_msix_ring_handle, 0, sp->desc[i],
- sp->s2io_entries[i].arg);
- /* If either data or addr is zero print it */
- if(!(sp->msix_info[i].addr &&
+ /* if either data or addr is zero print it. */
+ if (!(sp->msix_info[i].addr &&
sp->msix_info[i].data)) {
- DBG_PRINT(ERR_DBG, "%s @ Addr:0x%llx "
- "Data:0x%llx\n",sp->desc[i],
+ DBG_PRINT(ERR_DBG,
+ "%s @Addr:0x%llx Data:0x%llx\n",
+ sp->desc[i],
(unsigned long long)
sp->msix_info[i].addr,
(unsigned long long)
- sp->msix_info[i].data);
- } else {
+ ntohl(sp->msix_info[i].data));
+ } else
msix_rx_cnt++;
+ if (err) {
+ remove_msix_isr(sp);
+
+ DBG_PRINT(ERR_DBG,
+ "%s:MSI-X-%d registration "
+ "failed\n", dev->name, i);
+
+ DBG_PRINT(ERR_DBG,
+ "%s: Defaulting to INTA\n",
+ dev->name);
+ sp->config.intr_type = INTA;
+ break;
}
+ sp->s2io_entries[i].in_use =
+ MSIX_REGISTERED_SUCCESS;
}
- if (err) {
- remove_msix_isr(sp);
- DBG_PRINT(ERR_DBG,"%s:MSI-X-%d registration "
- "failed\n", dev->name, i);
- DBG_PRINT(ERR_DBG, "%s: defaulting to INTA\n",
- dev->name);
- sp->config.intr_type = INTA;
- break;
- }
- sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS;
}
if (!err) {
- printk(KERN_INFO "MSI-X-TX %d entries enabled\n",
- msix_tx_cnt);
printk(KERN_INFO "MSI-X-RX %d entries enabled\n",
- msix_rx_cnt);
+ --msix_rx_cnt);
+ DBG_PRINT(INFO_DBG, "MSI-X-TX entries enabled"
+ " through alarm vector\n");
}
}
if (sp->config.intr_type == INTA) {
@@ -7080,8 +7128,15 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
clear_bit(__S2IO_STATE_CARD_UP, &sp->state);
/* Disable napi */
- if (config->napi)
- napi_disable(&sp->napi);
+ if (sp->config.napi) {
+ int off = 0;
+ if (config->intr_type == MSI_X) {
+ for (; off < sp->config.rx_ring_num; off++)
+ napi_disable(&sp->mac_control.rings[off].napi);
+ }
+ else
+ napi_disable(&sp->napi);
+ }
/* disable Tx and Rx traffic on the NIC */
if (do_io)
@@ -7173,8 +7228,15 @@ static int s2io_card_up(struct s2io_nic * sp)
}
/* Initialise napi */
- if (config->napi)
- napi_enable(&sp->napi);
+ if (config->napi) {
+ int i;
+ if (config->intr_type == MSI_X) {
+ for (i = 0; i < sp->config.rx_ring_num; i++)
+ napi_enable(&sp->mac_control.rings[i].napi);
+ } else {
+ napi_enable(&sp->napi);
+ }
+ }
/* Maintain the state prior to the open */
if (sp->promisc_flg)
@@ -7217,7 +7279,7 @@ static int s2io_card_up(struct s2io_nic * sp)
/* Enable select interrupts */
en_dis_err_alarms(sp, ENA_ALL_INTRS, ENABLE_INTRS);
if (sp->config.intr_type != INTA)
- en_dis_able_nic_intrs(sp, ENA_ALL_INTRS, DISABLE_INTRS);
+ en_dis_able_nic_intrs(sp, TX_TRAFFIC_INTR, ENABLE_INTRS);
else {
interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
interruptible |= TX_PIC_INTR;
@@ -7615,9 +7677,6 @@ static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type,
rx_ring_num = MAX_RX_RINGS;
}
- if (*dev_intr_type != INTA)
- napi = 0;
-
if ((*dev_intr_type != INTA) && (*dev_intr_type != MSI_X)) {
DBG_PRINT(ERR_DBG, "s2io: Wrong intr_type requested. "
"Defaulting to INTA\n");
@@ -7918,8 +7977,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
* will use eth_mac_addr() for dev->set_mac_address
* mac address will be set every time dev->open() is called
*/
- netif_napi_add(dev, &sp->napi, s2io_poll, 32);
-
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = s2io_netpoll;
#endif
@@ -7963,6 +8020,32 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
}
}
+ if (sp->config.intr_type == MSI_X) {
+ sp->num_entries = config->rx_ring_num + 1;
+ ret = s2io_enable_msi_x(sp);
+
+ if (!ret) {
+ ret = s2io_test_msi(sp);
+ /* rollback MSI-X, will re-enable during add_isr() */
+ remove_msix_isr(sp);
+ }
+ if (ret) {
+
+ DBG_PRINT(ERR_DBG,
+ "%s: MSI-X requested but failed to enable\n",
+ dev->name);
+ sp->config.intr_type = INTA;
+ }
+ }
+
+ if (config->intr_type == MSI_X) {
+ for (i = 0; i < config->rx_ring_num ; i++)
+ netif_napi_add(dev, &mac_control->rings[i].napi,
+ s2io_poll_msix, 64);
+ } else {
+ netif_napi_add(dev, &sp->napi, s2io_poll_inta, 64);
+ }
+
/* Not needed for Herc */
if (sp->device_type & XFRAME_I_DEVICE) {
/*
@@ -8013,6 +8096,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
/* store mac addresses from CAM to s2io_nic structure */
do_s2io_store_unicast_mc(sp);
+ /* Configure MSIX vector for number of rings configured plus one */
+ if ((sp->device_type == XFRAME_II_DEVICE) &&
+ (config->intr_type == MSI_X))
+ sp->num_entries = config->rx_ring_num + 1;
+
/* Store the values of the MSIX table in the s2io_nic structure */
store_xmsi_data(sp);
/* reset Nic and bring it to known state */
@@ -8078,8 +8166,14 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
break;
}
- if (napi)
+ switch (sp->config.napi) {
+ case 0:
+ DBG_PRINT(ERR_DBG, "%s: NAPI disabled\n", dev->name);
+ break;
+ case 1:
DBG_PRINT(ERR_DBG, "%s: NAPI enabled\n", dev->name);
+ break;
+ }
DBG_PRINT(ERR_DBG, "%s: Using %d Tx fifo(s)\n", dev->name,
sp->config.tx_fifo_num);
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 0709ebae9139..4706f7f9acb6 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -706,7 +706,7 @@ struct ring_info {
/* per-ring buffer counter */
u32 rx_bufs_left;
- #define MAX_LRO_SESSIONS 32
+#define MAX_LRO_SESSIONS 32
struct lro lro0_n[MAX_LRO_SESSIONS];
u8 lro;
@@ -725,6 +725,11 @@ struct ring_info {
/* copy of sp->pdev pointer */
struct pci_dev *pdev;
+ /* Per ring napi struct */
+ struct napi_struct napi;
+
+ unsigned long interrupt_count;
+
/*
* Place holders for the virtual and physical addresses of
* all the Rx Blocks
@@ -841,7 +846,7 @@ struct usr_addr {
* Structure to keep track of the MSI-X vectors and the corresponding
* argument registered against each vector
*/
-#define MAX_REQUESTED_MSI_X 17
+#define MAX_REQUESTED_MSI_X 9
struct s2io_msix_entry
{
u16 vector;
@@ -849,8 +854,8 @@ struct s2io_msix_entry
void *arg;
u8 type;
-#define MSIX_FIFO_TYPE 1
-#define MSIX_RING_TYPE 2
+#define MSIX_ALARM_TYPE 1
+#define MSIX_RING_TYPE 2
u8 in_use;
#define MSIX_REGISTERED_SUCCESS 0xAA
@@ -877,7 +882,6 @@ struct s2io_nic {
*/
int pkts_to_process;
struct net_device *dev;
- struct napi_struct napi;
struct mac_info mac_control;
struct config_param config;
struct pci_dev *pdev;
@@ -948,6 +952,7 @@ struct s2io_nic {
*/
u8 other_fifo_idx;
+ struct napi_struct napi;
/* after blink, the adapter must be restored with original
* values.
*/
@@ -962,6 +967,7 @@ struct s2io_nic {
unsigned long long start_time;
struct vlan_group *vlgrp;
#define MSIX_FLG 0xA5
+ int num_entries;
struct msix_entry *entries;
int msi_detected;
wait_queue_head_t msi_wait;
@@ -982,6 +988,7 @@ struct s2io_nic {
u16 lro_max_aggr_per_sess;
volatile unsigned long state;
u64 general_int_mask;
+
#define VPD_STRING_LEN 80
u8 product_name[VPD_STRING_LEN];
u8 serial_num[VPD_STRING_LEN];
@@ -1103,7 +1110,7 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev);
static int init_shared_mem(struct s2io_nic *sp);
static void free_shared_mem(struct s2io_nic *sp);
static int init_nic(struct s2io_nic *nic);
-static void rx_intr_handler(struct ring_info *ring_data);
+static int rx_intr_handler(struct ring_info *ring_data, int budget);
static void tx_intr_handler(struct fifo_info *fifo_data);
static void s2io_handle_errors(void * dev_id);
@@ -1114,7 +1121,8 @@ static void s2io_set_multicast(struct net_device *dev);
static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp);
static void s2io_link(struct s2io_nic * sp, int link);
static void s2io_reset(struct s2io_nic * sp);
-static int s2io_poll(struct napi_struct *napi, int budget);
+static int s2io_poll_msix(struct napi_struct *napi, int budget);
+static int s2io_poll_inta(struct napi_struct *napi, int budget);
static void s2io_init_pci(struct s2io_nic * sp);
static int do_s2io_prog_unicast(struct net_device *dev, u8 *addr);
static void s2io_alarm_handle(unsigned long data);
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index 888b7dec9866..33bb18f810fb 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -179,8 +179,7 @@ enum sbmac_state {
#define SBMAC_MAX_TXDESCR 256
#define SBMAC_MAX_RXDESCR 256
-#define ETHER_ALIGN 2
-#define ETHER_ADDR_LEN 6
+#define ETHER_ADDR_LEN 6
#define ENET_PACKET_SIZE 1518
/*#define ENET_PACKET_SIZE 9216 */
@@ -262,8 +261,6 @@ struct sbmac_softc {
spinlock_t sbm_lock; /* spin lock */
int sbm_devflags; /* current device flags */
- int sbm_buffersize;
-
/*
* Controller-specific things
*/
@@ -305,10 +302,11 @@ struct sbmac_softc {
static void sbdma_initctx(struct sbmacdma *d, struct sbmac_softc *s, int chan,
int txrx, int maxdescr);
static void sbdma_channel_start(struct sbmacdma *d, int rxtx);
-static int sbdma_add_rcvbuffer(struct sbmacdma *d, struct sk_buff *m);
+static int sbdma_add_rcvbuffer(struct sbmac_softc *sc, struct sbmacdma *d,
+ struct sk_buff *m);
static int sbdma_add_txbuffer(struct sbmacdma *d, struct sk_buff *m);
static void sbdma_emptyring(struct sbmacdma *d);
-static void sbdma_fillring(struct sbmacdma *d);
+static void sbdma_fillring(struct sbmac_softc *sc, struct sbmacdma *d);
static int sbdma_rx_process(struct sbmac_softc *sc, struct sbmacdma *d,
int work_to_do, int poll);
static void sbdma_tx_process(struct sbmac_softc *sc, struct sbmacdma *d,
@@ -777,16 +775,13 @@ static void sbdma_channel_stop(struct sbmacdma *d)
d->sbdma_remptr = NULL;
}
-static void sbdma_align_skb(struct sk_buff *skb,int power2,int offset)
+static inline void sbdma_align_skb(struct sk_buff *skb,
+ unsigned int power2, unsigned int offset)
{
- unsigned long addr;
- unsigned long newaddr;
-
- addr = (unsigned long) skb->data;
-
- newaddr = (addr + power2 - 1) & ~(power2 - 1);
+ unsigned char *addr = skb->data;
+ unsigned char *newaddr = PTR_ALIGN(addr, power2);
- skb_reserve(skb,newaddr-addr+offset);
+ skb_reserve(skb, newaddr - addr + offset);
}
@@ -797,7 +792,8 @@ static void sbdma_align_skb(struct sk_buff *skb,int power2,int offset)
* this queues a buffer for inbound packets.
*
* Input parameters:
- * d - DMA channel descriptor
+ * sc - softc structure
+ * d - DMA channel descriptor
* sb - sk_buff to add, or NULL if we should allocate one
*
* Return value:
@@ -806,8 +802,10 @@ static void sbdma_align_skb(struct sk_buff *skb,int power2,int offset)
********************************************************************* */
-static int sbdma_add_rcvbuffer(struct sbmacdma *d, struct sk_buff *sb)
+static int sbdma_add_rcvbuffer(struct sbmac_softc *sc, struct sbmacdma *d,
+ struct sk_buff *sb)
{
+ struct net_device *dev = sc->sbm_dev;
struct sbdmadscr *dsc;
struct sbdmadscr *nextdsc;
struct sk_buff *sb_new = NULL;
@@ -848,14 +846,16 @@ static int sbdma_add_rcvbuffer(struct sbmacdma *d, struct sk_buff *sb)
*/
if (sb == NULL) {
- sb_new = dev_alloc_skb(ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN);
+ sb_new = netdev_alloc_skb(dev, ENET_PACKET_SIZE +
+ SMP_CACHE_BYTES * 2 +
+ NET_IP_ALIGN);
if (sb_new == NULL) {
pr_info("%s: sk_buff allocation failed\n",
d->sbdma_eth->sbm_dev->name);
return -ENOBUFS;
}
- sbdma_align_skb(sb_new, SMP_CACHE_BYTES, ETHER_ALIGN);
+ sbdma_align_skb(sb_new, SMP_CACHE_BYTES, NET_IP_ALIGN);
}
else {
sb_new = sb;
@@ -874,10 +874,10 @@ static int sbdma_add_rcvbuffer(struct sbmacdma *d, struct sk_buff *sb)
* Do not interrupt per DMA transfer.
*/
dsc->dscr_a = virt_to_phys(sb_new->data) |
- V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) | 0;
+ V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize + NET_IP_ALIGN)) | 0;
#else
dsc->dscr_a = virt_to_phys(sb_new->data) |
- V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) |
+ V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize + NET_IP_ALIGN)) |
M_DMA_DSCRA_INTERRUPT;
#endif
@@ -1032,18 +1032,19 @@ static void sbdma_emptyring(struct sbmacdma *d)
* with sk_buffs
*
* Input parameters:
- * d - DMA channel
+ * sc - softc structure
+ * d - DMA channel
*
* Return value:
* nothing
********************************************************************* */
-static void sbdma_fillring(struct sbmacdma *d)
+static void sbdma_fillring(struct sbmac_softc *sc, struct sbmacdma *d)
{
int idx;
- for (idx = 0; idx < SBMAC_MAX_RXDESCR-1; idx++) {
- if (sbdma_add_rcvbuffer(d,NULL) != 0)
+ for (idx = 0; idx < SBMAC_MAX_RXDESCR - 1; idx++) {
+ if (sbdma_add_rcvbuffer(sc, d, NULL) != 0)
break;
}
}
@@ -1159,10 +1160,11 @@ again:
* packet and put it right back on the receive ring.
*/
- if (unlikely (sbdma_add_rcvbuffer(d,NULL) ==
- -ENOBUFS)) {
+ if (unlikely(sbdma_add_rcvbuffer(sc, d, NULL) ==
+ -ENOBUFS)) {
dev->stats.rx_dropped++;
- sbdma_add_rcvbuffer(d,sb); /* re-add old buffer */
+ /* Re-add old buffer */
+ sbdma_add_rcvbuffer(sc, d, sb);
/* No point in continuing at the moment */
printk(KERN_ERR "dropped packet (1)\n");
d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
@@ -1212,7 +1214,7 @@ again:
* put it back on the receive ring.
*/
dev->stats.rx_errors++;
- sbdma_add_rcvbuffer(d,sb);
+ sbdma_add_rcvbuffer(sc, d, sb);
}
@@ -1570,7 +1572,7 @@ static void sbmac_channel_start(struct sbmac_softc *s)
* Fill the receive ring
*/
- sbdma_fillring(&(s->sbm_rxdma));
+ sbdma_fillring(s, &(s->sbm_rxdma));
/*
* Turn on the rest of the bits in the enable register
@@ -2312,13 +2314,6 @@ static int sbmac_init(struct platform_device *pldev, long long base)
dev->dev_addr[i] = eaddr[i];
}
-
- /*
- * Init packet size
- */
-
- sc->sbm_buffersize = ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN;
-
/*
* Initialize context (get pointers to registers and stuff), then
* allocate the memory for the descriptor tables.
diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c
index f64a860029b7..61955f8d8011 100644
--- a/drivers/net/sc92031.c
+++ b/drivers/net/sc92031.c
@@ -953,9 +953,6 @@ static int sc92031_start_xmit(struct sk_buff *skb, struct net_device *dev)
unsigned entry;
u32 tx_status;
- if (skb_padto(skb, ETH_ZLEN))
- return NETDEV_TX_OK;
-
if (unlikely(skb->len > TX_BUF_SIZE)) {
dev->stats.tx_dropped++;
goto out;
@@ -975,6 +972,11 @@ static int sc92031_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb_copy_and_csum_dev(skb, priv->tx_bufs + entry * TX_BUF_SIZE);
len = skb->len;
+ if (len < ETH_ZLEN) {
+ memset(priv->tx_bufs + entry * TX_BUF_SIZE + len,
+ 0, ETH_ZLEN - len);
+ len = ETH_ZLEN;
+ }
wmb();
diff --git a/drivers/net/sfc/bitfield.h b/drivers/net/sfc/bitfield.h
index 2806201644cc..2c79d27404e0 100644
--- a/drivers/net/sfc/bitfield.h
+++ b/drivers/net/sfc/bitfield.h
@@ -483,7 +483,7 @@ typedef union efx_oword {
#endif
#define EFX_SET_OWORD_FIELD_VER(efx, oword, field, value) do { \
- if (FALCON_REV(efx) >= FALCON_REV_B0) { \
+ if (falcon_rev(efx) >= FALCON_REV_B0) { \
EFX_SET_OWORD_FIELD((oword), field##_B0, (value)); \
} else { \
EFX_SET_OWORD_FIELD((oword), field##_A1, (value)); \
@@ -491,7 +491,7 @@ typedef union efx_oword {
} while (0)
#define EFX_QWORD_FIELD_VER(efx, qword, field) \
- (FALCON_REV(efx) >= FALCON_REV_B0 ? \
+ (falcon_rev(efx) >= FALCON_REV_B0 ? \
EFX_QWORD_FIELD((qword), field##_B0) : \
EFX_QWORD_FIELD((qword), field##_A1))
@@ -501,8 +501,5 @@ typedef union efx_oword {
#define DMA_ADDR_T_WIDTH (8 * sizeof(dma_addr_t))
#define EFX_DMA_TYPE_WIDTH(width) \
(((width) < DMA_ADDR_T_WIDTH) ? (width) : DMA_ADDR_T_WIDTH)
-#define EFX_DMA_MAX_MASK ((DMA_ADDR_T_WIDTH == 64) ? \
- ~((u64) 0) : ~((u32) 0))
-#define EFX_DMA_MASK(mask) ((mask) & EFX_DMA_MAX_MASK)
#endif /* EFX_BITFIELD_H */
diff --git a/drivers/net/sfc/boards.c b/drivers/net/sfc/boards.c
index eecaa6d58584..7fc0328dc055 100644
--- a/drivers/net/sfc/boards.c
+++ b/drivers/net/sfc/boards.c
@@ -27,10 +27,8 @@ static void blink_led_timer(unsigned long context)
struct efx_blinker *bl = &efx->board_info.blinker;
efx->board_info.set_fault_led(efx, bl->state);
bl->state = !bl->state;
- if (bl->resubmit) {
- bl->timer.expires = jiffies + BLINK_INTERVAL;
- add_timer(&bl->timer);
- }
+ if (bl->resubmit)
+ mod_timer(&bl->timer, jiffies + BLINK_INTERVAL);
}
static void board_blink(struct efx_nic *efx, int blink)
@@ -44,8 +42,7 @@ static void board_blink(struct efx_nic *efx, int blink)
blinker->state = 0;
setup_timer(&blinker->timer, blink_led_timer,
(unsigned long)efx);
- blinker->timer.expires = jiffies + BLINK_INTERVAL;
- add_timer(&blinker->timer);
+ mod_timer(&blinker->timer, jiffies + BLINK_INTERVAL);
} else {
blinker->resubmit = 0;
if (blinker->timer.function)
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 418f2e53a95b..449760642e31 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -199,11 +199,12 @@ static inline int efx_process_channel(struct efx_channel *channel, int rx_quota)
*/
static inline void efx_channel_processed(struct efx_channel *channel)
{
- /* Write to EVQ_RPTR_REG. If a new event arrived in a race
- * with finishing processing, a new interrupt will be raised.
- */
+ /* The interrupt handler for this channel may set work_pending
+ * as soon as we acknowledge the events we've seen. Make sure
+ * it's cleared before then. */
channel->work_pending = 0;
- smp_wmb(); /* Ensure channel updated before any new interrupt. */
+ smp_wmb();
+
falcon_eventq_read_ack(channel);
}
@@ -265,7 +266,7 @@ void efx_process_channel_now(struct efx_channel *channel)
napi_disable(&channel->napi_str);
/* Poll the channel */
- (void) efx_process_channel(channel, efx->type->evq_size);
+ efx_process_channel(channel, efx->type->evq_size);
/* Ack the eventq. This may cause an interrupt to be generated
* when they are reenabled */
@@ -317,26 +318,6 @@ static void efx_remove_eventq(struct efx_channel *channel)
*
*************************************************************************/
-/* Setup per-NIC RX buffer parameters.
- * Calculate the rx buffer allocation parameters required to support
- * the current MTU, including padding for header alignment and overruns.
- */
-static void efx_calc_rx_buffer_params(struct efx_nic *efx)
-{
- unsigned int order, len;
-
- len = (max(EFX_PAGE_IP_ALIGN, NET_IP_ALIGN) +
- EFX_MAX_FRAME_LEN(efx->net_dev->mtu) +
- efx->type->rx_buffer_padding);
-
- /* Calculate page-order */
- for (order = 0; ((1u << order) * PAGE_SIZE) < len; ++order)
- ;
-
- efx->rx_buffer_len = len;
- efx->rx_buffer_order = order;
-}
-
static int efx_probe_channel(struct efx_channel *channel)
{
struct efx_tx_queue *tx_queue;
@@ -387,7 +368,14 @@ static int efx_init_channels(struct efx_nic *efx)
struct efx_channel *channel;
int rc = 0;
- efx_calc_rx_buffer_params(efx);
+ /* Calculate the rx buffer allocation parameters required to
+ * support the current MTU, including padding for header
+ * alignment and overruns.
+ */
+ efx->rx_buffer_len = (max(EFX_PAGE_IP_ALIGN, NET_IP_ALIGN) +
+ EFX_MAX_FRAME_LEN(efx->net_dev->mtu) +
+ efx->type->rx_buffer_padding);
+ efx->rx_buffer_order = get_order(efx->rx_buffer_len);
/* Initialise the channels */
efx_for_each_channel(channel, efx) {
@@ -440,9 +428,12 @@ static void efx_start_channel(struct efx_channel *channel)
netif_napi_add(channel->napi_dev, &channel->napi_str,
efx_poll, napi_weight);
+ /* The interrupt handler for this channel may set work_pending
+ * as soon as we enable it. Make sure it's cleared before
+ * then. Similarly, make sure it sees the enabled flag set. */
channel->work_pending = 0;
channel->enabled = 1;
- smp_wmb(); /* ensure channel updated before first interrupt */
+ smp_wmb();
napi_enable(&channel->napi_str);
@@ -704,7 +695,7 @@ static void efx_stop_port(struct efx_nic *efx)
mutex_unlock(&efx->mac_lock);
/* Serialise against efx_set_multicast_list() */
- if (NET_DEV_REGISTERED(efx)) {
+ if (efx_dev_registered(efx)) {
netif_tx_lock_bh(efx->net_dev);
netif_tx_unlock_bh(efx->net_dev);
}
@@ -791,22 +782,23 @@ static int efx_init_io(struct efx_nic *efx)
efx->membase = ioremap_nocache(efx->membase_phys,
efx->type->mem_map_size);
if (!efx->membase) {
- EFX_ERR(efx, "could not map memory BAR %d at %lx+%x\n",
- efx->type->mem_bar, efx->membase_phys,
+ EFX_ERR(efx, "could not map memory BAR %d at %llx+%x\n",
+ efx->type->mem_bar,
+ (unsigned long long)efx->membase_phys,
efx->type->mem_map_size);
rc = -ENOMEM;
goto fail4;
}
- EFX_LOG(efx, "memory BAR %u at %lx+%x (virtual %p)\n",
- efx->type->mem_bar, efx->membase_phys, efx->type->mem_map_size,
- efx->membase);
+ EFX_LOG(efx, "memory BAR %u at %llx+%x (virtual %p)\n",
+ efx->type->mem_bar, (unsigned long long)efx->membase_phys,
+ efx->type->mem_map_size, efx->membase);
return 0;
fail4:
release_mem_region(efx->membase_phys, efx->type->mem_map_size);
fail3:
- efx->membase_phys = 0UL;
+ efx->membase_phys = 0;
fail2:
pci_disable_device(efx->pci_dev);
fail1:
@@ -824,7 +816,7 @@ static void efx_fini_io(struct efx_nic *efx)
if (efx->membase_phys) {
pci_release_region(efx->pci_dev, efx->type->mem_bar);
- efx->membase_phys = 0UL;
+ efx->membase_phys = 0;
}
pci_disable_device(efx->pci_dev);
@@ -1043,7 +1035,7 @@ static void efx_start_all(struct efx_nic *efx)
return;
if ((efx->state != STATE_RUNNING) && (efx->state != STATE_INIT))
return;
- if (NET_DEV_REGISTERED(efx) && !netif_running(efx->net_dev))
+ if (efx_dev_registered(efx) && !netif_running(efx->net_dev))
return;
/* Mark the port as enabled so port reconfigurations can start, then
@@ -1073,9 +1065,8 @@ static void efx_flush_all(struct efx_nic *efx)
cancel_delayed_work_sync(&efx->monitor_work);
/* Ensure that all RX slow refills are complete. */
- efx_for_each_rx_queue(rx_queue, efx) {
+ efx_for_each_rx_queue(rx_queue, efx)
cancel_delayed_work_sync(&rx_queue->work);
- }
/* Stop scheduled port reconfigurations */
cancel_work_sync(&efx->reconfigure_work);
@@ -1101,9 +1092,10 @@ static void efx_stop_all(struct efx_nic *efx)
falcon_disable_interrupts(efx);
if (efx->legacy_irq)
synchronize_irq(efx->legacy_irq);
- efx_for_each_channel_with_interrupt(channel, efx)
+ efx_for_each_channel_with_interrupt(channel, efx) {
if (channel->irq)
synchronize_irq(channel->irq);
+ }
/* Stop all NAPI processing and synchronous rx refills */
efx_for_each_channel(channel, efx)
@@ -1125,7 +1117,7 @@ static void efx_stop_all(struct efx_nic *efx)
/* Stop the kernel transmit interface late, so the watchdog
* timer isn't ticking over the flush */
efx_stop_queue(efx);
- if (NET_DEV_REGISTERED(efx)) {
+ if (efx_dev_registered(efx)) {
netif_tx_lock_bh(efx->net_dev);
netif_tx_unlock_bh(efx->net_dev);
}
@@ -1344,13 +1336,17 @@ static int efx_net_stop(struct net_device *net_dev)
return 0;
}
-/* Context: process, dev_base_lock held, non-blocking. */
+/* Context: process, dev_base_lock or RTNL held, non-blocking. */
static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
{
struct efx_nic *efx = net_dev->priv;
struct efx_mac_stats *mac_stats = &efx->mac_stats;
struct net_device_stats *stats = &net_dev->stats;
+ /* Update stats if possible, but do not wait if another thread
+ * is updating them (or resetting the NIC); slightly stale
+ * stats are acceptable.
+ */
if (!spin_trylock(&efx->stats_lock))
return stats;
if (efx->state == STATE_RUNNING) {
@@ -1494,7 +1490,7 @@ static void efx_set_multicast_list(struct net_device *net_dev)
static int efx_netdev_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
- struct net_device *net_dev = (struct net_device *)ptr;
+ struct net_device *net_dev = ptr;
if (net_dev->open == efx_net_open && event == NETDEV_CHANGENAME) {
struct efx_nic *efx = net_dev->priv;
@@ -1563,7 +1559,7 @@ static void efx_unregister_netdev(struct efx_nic *efx)
efx_for_each_tx_queue(tx_queue, efx)
efx_release_tx_buffers(tx_queue);
- if (NET_DEV_REGISTERED(efx)) {
+ if (efx_dev_registered(efx)) {
strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
unregister_netdev(efx->net_dev);
}
@@ -1688,7 +1684,7 @@ static int efx_reset(struct efx_nic *efx)
if (method == RESET_TYPE_DISABLE) {
/* Reinitialise the device anyway so the driver unload sequence
* can talk to the external SRAM */
- (void) falcon_init_nic(efx);
+ falcon_init_nic(efx);
rc = -EIO;
goto fail4;
}
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index b57cc68058c0..d3f749c72d41 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -116,17 +116,8 @@ MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold");
**************************************************************************
*/
-/* DMA address mask (up to 46-bit, avoiding compiler warnings)
- *
- * Note that it is possible to have a platform with 64-bit longs and
- * 32-bit DMA addresses, or vice versa. EFX_DMA_MASK takes care of the
- * platform DMA mask.
- */
-#if BITS_PER_LONG == 64
-#define FALCON_DMA_MASK EFX_DMA_MASK(0x00003fffffffffffUL)
-#else
-#define FALCON_DMA_MASK EFX_DMA_MASK(0x00003fffffffffffULL)
-#endif
+/* DMA address mask */
+#define FALCON_DMA_MASK DMA_BIT_MASK(46)
/* TX DMA length mask (13-bit) */
#define FALCON_TX_DMA_MASK (4096 - 1)
@@ -145,7 +136,7 @@ MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold");
#define PCI_EXP_LNKSTA_LNK_WID_LBN 4
#define FALCON_IS_DUAL_FUNC(efx) \
- (FALCON_REV(efx) < FALCON_REV_B0)
+ (falcon_rev(efx) < FALCON_REV_B0)
/**************************************************************************
*
@@ -465,7 +456,7 @@ int falcon_init_tx(struct efx_tx_queue *tx_queue)
TX_DESCQ_TYPE, 0,
TX_NON_IP_DROP_DIS_B0, 1);
- if (FALCON_REV(efx) >= FALCON_REV_B0) {
+ if (falcon_rev(efx) >= FALCON_REV_B0) {
int csum = !(efx->net_dev->features & NETIF_F_IP_CSUM);
EFX_SET_OWORD_FIELD(tx_desc_ptr, TX_IP_CHKSM_DIS_B0, csum);
EFX_SET_OWORD_FIELD(tx_desc_ptr, TX_TCP_CHKSM_DIS_B0, csum);
@@ -474,7 +465,7 @@ int falcon_init_tx(struct efx_tx_queue *tx_queue)
falcon_write_table(efx, &tx_desc_ptr, efx->type->txd_ptr_tbl_base,
tx_queue->queue);
- if (FALCON_REV(efx) < FALCON_REV_B0) {
+ if (falcon_rev(efx) < FALCON_REV_B0) {
efx_oword_t reg;
BUG_ON(tx_queue->queue >= 128); /* HW limit */
@@ -635,7 +626,7 @@ int falcon_init_rx(struct efx_rx_queue *rx_queue)
efx_oword_t rx_desc_ptr;
struct efx_nic *efx = rx_queue->efx;
int rc;
- int is_b0 = FALCON_REV(efx) >= FALCON_REV_B0;
+ int is_b0 = falcon_rev(efx) >= FALCON_REV_B0;
int iscsi_digest_en = is_b0;
EFX_LOG(efx, "RX queue %d ring in special buffers %d-%d\n",
@@ -822,10 +813,10 @@ static inline void falcon_handle_tx_event(struct efx_channel *channel,
tx_ev_q_label = EFX_QWORD_FIELD(*event, TX_EV_Q_LABEL);
tx_queue = &efx->tx_queue[tx_ev_q_label];
- if (NET_DEV_REGISTERED(efx))
+ if (efx_dev_registered(efx))
netif_tx_lock(efx->net_dev);
falcon_notify_tx_desc(tx_queue);
- if (NET_DEV_REGISTERED(efx))
+ if (efx_dev_registered(efx))
netif_tx_unlock(efx->net_dev);
} else if (EFX_QWORD_FIELD(*event, TX_EV_PKT_ERR) &&
EFX_WORKAROUND_10727(efx)) {
@@ -884,7 +875,7 @@ static void falcon_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
RX_EV_TCP_UDP_CHKSUM_ERR);
rx_ev_eth_crc_err = EFX_QWORD_FIELD(*event, RX_EV_ETH_CRC_ERR);
rx_ev_frm_trunc = EFX_QWORD_FIELD(*event, RX_EV_FRM_TRUNC);
- rx_ev_drib_nib = ((FALCON_REV(efx) >= FALCON_REV_B0) ?
+ rx_ev_drib_nib = ((falcon_rev(efx) >= FALCON_REV_B0) ?
0 : EFX_QWORD_FIELD(*event, RX_EV_DRIB_NIB));
rx_ev_pause_frm = EFX_QWORD_FIELD(*event, RX_EV_PAUSE_FRM_ERR);
@@ -1065,7 +1056,7 @@ static void falcon_handle_global_event(struct efx_channel *channel,
EFX_QWORD_FIELD(*event, XG_PHY_INTR))
is_phy_event = 1;
- if ((FALCON_REV(efx) >= FALCON_REV_B0) &&
+ if ((falcon_rev(efx) >= FALCON_REV_B0) &&
EFX_OWORD_FIELD(*event, XG_MNT_INTR_B0))
is_phy_event = 1;
@@ -1405,7 +1396,7 @@ static inline void falcon_irq_ack_a1(struct efx_nic *efx)
static irqreturn_t falcon_fatal_interrupt(struct efx_nic *efx)
{
struct falcon_nic_data *nic_data = efx->nic_data;
- efx_oword_t *int_ker = (efx_oword_t *) efx->irq_status.addr;
+ efx_oword_t *int_ker = efx->irq_status.addr;
efx_oword_t fatal_intr;
int error, mem_perr;
static int n_int_errors;
@@ -1451,8 +1442,8 @@ out:
*/
static irqreturn_t falcon_legacy_interrupt_b0(int irq, void *dev_id)
{
- struct efx_nic *efx = (struct efx_nic *)dev_id;
- efx_oword_t *int_ker = (efx_oword_t *) efx->irq_status.addr;
+ struct efx_nic *efx = dev_id;
+ efx_oword_t *int_ker = efx->irq_status.addr;
struct efx_channel *channel;
efx_dword_t reg;
u32 queues;
@@ -1489,8 +1480,8 @@ static irqreturn_t falcon_legacy_interrupt_b0(int irq, void *dev_id)
static irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id)
{
- struct efx_nic *efx = (struct efx_nic *)dev_id;
- efx_oword_t *int_ker = (efx_oword_t *) efx->irq_status.addr;
+ struct efx_nic *efx = dev_id;
+ efx_oword_t *int_ker = efx->irq_status.addr;
struct efx_channel *channel;
int syserr;
int queues;
@@ -1542,9 +1533,9 @@ static irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id)
*/
static irqreturn_t falcon_msi_interrupt(int irq, void *dev_id)
{
- struct efx_channel *channel = (struct efx_channel *)dev_id;
+ struct efx_channel *channel = dev_id;
struct efx_nic *efx = channel->efx;
- efx_oword_t *int_ker = (efx_oword_t *) efx->irq_status.addr;
+ efx_oword_t *int_ker = efx->irq_status.addr;
int syserr;
efx->last_irq_cpu = raw_smp_processor_id();
@@ -1572,7 +1563,7 @@ static void falcon_setup_rss_indir_table(struct efx_nic *efx)
unsigned long offset;
efx_dword_t dword;
- if (FALCON_REV(efx) < FALCON_REV_B0)
+ if (falcon_rev(efx) < FALCON_REV_B0)
return;
for (offset = RX_RSS_INDIR_TBL_B0;
@@ -1595,7 +1586,7 @@ int falcon_init_interrupt(struct efx_nic *efx)
if (!EFX_INT_MODE_USE_MSI(efx)) {
irq_handler_t handler;
- if (FALCON_REV(efx) >= FALCON_REV_B0)
+ if (falcon_rev(efx) >= FALCON_REV_B0)
handler = falcon_legacy_interrupt_b0;
else
handler = falcon_legacy_interrupt_a1;
@@ -1636,12 +1627,13 @@ void falcon_fini_interrupt(struct efx_nic *efx)
efx_oword_t reg;
/* Disable MSI/MSI-X interrupts */
- efx_for_each_channel_with_interrupt(channel, efx)
+ efx_for_each_channel_with_interrupt(channel, efx) {
if (channel->irq)
free_irq(channel->irq, channel);
+ }
/* ACK legacy interrupt */
- if (FALCON_REV(efx) >= FALCON_REV_B0)
+ if (falcon_rev(efx) >= FALCON_REV_B0)
falcon_read(efx, &reg, INT_ISR0_B0);
else
falcon_irq_ack_a1(efx);
@@ -1732,7 +1724,7 @@ void falcon_drain_tx_fifo(struct efx_nic *efx)
efx_oword_t temp;
int count;
- if ((FALCON_REV(efx) < FALCON_REV_B0) ||
+ if ((falcon_rev(efx) < FALCON_REV_B0) ||
(efx->loopback_mode != LOOPBACK_NONE))
return;
@@ -1785,7 +1777,7 @@ void falcon_deconfigure_mac_wrapper(struct efx_nic *efx)
{
efx_oword_t temp;
- if (FALCON_REV(efx) < FALCON_REV_B0)
+ if (falcon_rev(efx) < FALCON_REV_B0)
return;
/* Isolate the MAC -> RX */
@@ -1823,7 +1815,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
MAC_SPEED, link_speed);
/* On B0, MAC backpressure can be disabled and packets get
* discarded. */
- if (FALCON_REV(efx) >= FALCON_REV_B0) {
+ if (falcon_rev(efx) >= FALCON_REV_B0) {
EFX_SET_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0,
!efx->link_up);
}
@@ -1841,7 +1833,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
EFX_SET_OWORD_FIELD_VER(efx, reg, RX_XOFF_MAC_EN, tx_fc);
/* Unisolate the MAC -> RX */
- if (FALCON_REV(efx) >= FALCON_REV_B0)
+ if (falcon_rev(efx) >= FALCON_REV_B0)
EFX_SET_OWORD_FIELD(reg, RX_INGR_EN_B0, 1);
falcon_write(efx, &reg, RX_CFG_REG_KER);
}
@@ -1856,7 +1848,7 @@ int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset)
return 0;
/* Statistics fetch will fail if the MAC is in TX drain */
- if (FALCON_REV(efx) >= FALCON_REV_B0) {
+ if (falcon_rev(efx) >= FALCON_REV_B0) {
efx_oword_t temp;
falcon_read(efx, &temp, MAC0_CTRL_REG_KER);
if (EFX_OWORD_FIELD(temp, TXFIFO_DRAIN_EN_B0))
@@ -1940,7 +1932,7 @@ static int falcon_gmii_wait(struct efx_nic *efx)
static void falcon_mdio_write(struct net_device *net_dev, int phy_id,
int addr, int value)
{
- struct efx_nic *efx = (struct efx_nic *)net_dev->priv;
+ struct efx_nic *efx = net_dev->priv;
unsigned int phy_id2 = phy_id & FALCON_PHY_ID_ID_MASK;
efx_oword_t reg;
@@ -2008,7 +2000,7 @@ static void falcon_mdio_write(struct net_device *net_dev, int phy_id,
* could be read, -1 will be returned. */
static int falcon_mdio_read(struct net_device *net_dev, int phy_id, int addr)
{
- struct efx_nic *efx = (struct efx_nic *)net_dev->priv;
+ struct efx_nic *efx = net_dev->priv;
unsigned int phy_addr = phy_id & FALCON_PHY_ID_ID_MASK;
efx_oword_t reg;
int value = -1;
@@ -2113,7 +2105,7 @@ int falcon_probe_port(struct efx_nic *efx)
falcon_init_mdio(&efx->mii);
/* Hardware flow ctrl. FalconA RX FIFO too small for pause generation */
- if (FALCON_REV(efx) >= FALCON_REV_B0)
+ if (falcon_rev(efx) >= FALCON_REV_B0)
efx->flow_control = EFX_FC_RX | EFX_FC_TX;
else
efx->flow_control = EFX_FC_RX;
@@ -2373,7 +2365,7 @@ static int falcon_probe_nic_variant(struct efx_nic *efx)
return -ENODEV;
}
- switch (FALCON_REV(efx)) {
+ switch (falcon_rev(efx)) {
case FALCON_REV_A0:
case 0xff:
EFX_ERR(efx, "Falcon rev A0 not supported\n");
@@ -2399,7 +2391,7 @@ static int falcon_probe_nic_variant(struct efx_nic *efx)
break;
default:
- EFX_ERR(efx, "Unknown Falcon rev %d\n", FALCON_REV(efx));
+ EFX_ERR(efx, "Unknown Falcon rev %d\n", falcon_rev(efx));
return -ENODEV;
}
@@ -2419,7 +2411,7 @@ int falcon_probe_nic(struct efx_nic *efx)
/* Allocate storage for hardware specific data */
nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL);
- efx->nic_data = (void *) nic_data;
+ efx->nic_data = nic_data;
/* Determine number of ports etc. */
rc = falcon_probe_nic_variant(efx);
@@ -2489,13 +2481,10 @@ int falcon_probe_nic(struct efx_nic *efx)
*/
int falcon_init_nic(struct efx_nic *efx)
{
- struct falcon_nic_data *data;
efx_oword_t temp;
unsigned thresh;
int rc;
- data = (struct falcon_nic_data *)efx->nic_data;
-
/* Set up the address region register. This is only needed
* for the B0 FPGA, but since we are just pushing in the
* reset defaults this may as well be unconditional. */
@@ -2562,7 +2551,7 @@ int falcon_init_nic(struct efx_nic *efx)
/* Set number of RSS queues for receive path. */
falcon_read(efx, &temp, RX_FILTER_CTL_REG);
- if (FALCON_REV(efx) >= FALCON_REV_B0)
+ if (falcon_rev(efx) >= FALCON_REV_B0)
EFX_SET_OWORD_FIELD(temp, NUM_KER, 0);
else
EFX_SET_OWORD_FIELD(temp, NUM_KER, efx->rss_queues - 1);
@@ -2600,7 +2589,7 @@ int falcon_init_nic(struct efx_nic *efx)
/* Prefetch threshold 2 => fetch when descriptor cache half empty */
EFX_SET_OWORD_FIELD(temp, TX_PREF_THRESHOLD, 2);
/* Squash TX of packets of 16 bytes or less */
- if (FALCON_REV(efx) >= FALCON_REV_B0 && EFX_WORKAROUND_9141(efx))
+ if (falcon_rev(efx) >= FALCON_REV_B0 && EFX_WORKAROUND_9141(efx))
EFX_SET_OWORD_FIELD(temp, TX_FLUSH_MIN_LEN_EN_B0, 1);
falcon_write(efx, &temp, TX_CFG2_REG_KER);
@@ -2617,7 +2606,7 @@ int falcon_init_nic(struct efx_nic *efx)
if (EFX_WORKAROUND_7575(efx))
EFX_SET_OWORD_FIELD_VER(efx, temp, RX_USR_BUF_SIZE,
(3 * 4096) / 32);
- if (FALCON_REV(efx) >= FALCON_REV_B0)
+ if (falcon_rev(efx) >= FALCON_REV_B0)
EFX_SET_OWORD_FIELD(temp, RX_INGR_EN_B0, 1);
/* RX FIFO flow control thresholds */
@@ -2633,7 +2622,7 @@ int falcon_init_nic(struct efx_nic *efx)
falcon_write(efx, &temp, RX_CFG_REG_KER);
/* Set destination of both TX and RX Flush events */
- if (FALCON_REV(efx) >= FALCON_REV_B0) {
+ if (falcon_rev(efx) >= FALCON_REV_B0) {
EFX_POPULATE_OWORD_1(temp, FLS_EVQ_ID, 0);
falcon_write(efx, &temp, DP_CTRL_REG);
}
@@ -2647,7 +2636,7 @@ void falcon_remove_nic(struct efx_nic *efx)
falcon_free_buffer(efx, &efx->irq_status);
- (void) falcon_reset_hw(efx, RESET_TYPE_ALL);
+ falcon_reset_hw(efx, RESET_TYPE_ALL);
/* Release the second function after the reset */
if (nic_data->pci_dev2) {
diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h
index 6117403b0c03..492f9bc28840 100644
--- a/drivers/net/sfc/falcon.h
+++ b/drivers/net/sfc/falcon.h
@@ -23,7 +23,10 @@ enum falcon_revision {
FALCON_REV_B0 = 2,
};
-#define FALCON_REV(efx) ((efx)->pci_dev->revision)
+static inline int falcon_rev(struct efx_nic *efx)
+{
+ return efx->pci_dev->revision;
+}
extern struct efx_nic_type falcon_a_nic_type;
extern struct efx_nic_type falcon_b_nic_type;
diff --git a/drivers/net/sfc/falcon_hwdefs.h b/drivers/net/sfc/falcon_hwdefs.h
index 06e2d68fc3d1..6d003114eeab 100644
--- a/drivers/net/sfc/falcon_hwdefs.h
+++ b/drivers/net/sfc/falcon_hwdefs.h
@@ -1125,7 +1125,7 @@ struct falcon_nvconfig_board_v2 {
u8 port1_phy_type;
__le16 asic_sub_revision;
__le16 board_revision;
-} __attribute__ ((packed));
+} __packed;
#define NVCONFIG_BASE 0x300
#define NVCONFIG_BOARD_MAGIC_NUM 0xFA1C
@@ -1144,6 +1144,6 @@ struct falcon_nvconfig {
__le16 board_struct_ver;
__le16 board_checksum;
struct falcon_nvconfig_board_v2 board_v2;
-} __attribute__ ((packed));
+} __packed;
#endif /* EFX_FALCON_HWDEFS_H */
diff --git a/drivers/net/sfc/falcon_io.h b/drivers/net/sfc/falcon_io.h
index ea08184ddfa9..6670cdfc41ab 100644
--- a/drivers/net/sfc/falcon_io.h
+++ b/drivers/net/sfc/falcon_io.h
@@ -56,14 +56,27 @@
#define FALCON_USE_QWORD_IO 1
#endif
-#define _falcon_writeq(efx, value, reg) \
- __raw_writeq((__force u64) (value), (efx)->membase + (reg))
-#define _falcon_writel(efx, value, reg) \
- __raw_writel((__force u32) (value), (efx)->membase + (reg))
-#define _falcon_readq(efx, reg) \
- ((__force __le64) __raw_readq((efx)->membase + (reg)))
-#define _falcon_readl(efx, reg) \
- ((__force __le32) __raw_readl((efx)->membase + (reg)))
+#ifdef FALCON_USE_QWORD_IO
+static inline void _falcon_writeq(struct efx_nic *efx, __le64 value,
+ unsigned int reg)
+{
+ __raw_writeq((__force u64)value, efx->membase + reg);
+}
+static inline __le64 _falcon_readq(struct efx_nic *efx, unsigned int reg)
+{
+ return (__force __le64)__raw_readq(efx->membase + reg);
+}
+#endif
+
+static inline void _falcon_writel(struct efx_nic *efx, __le32 value,
+ unsigned int reg)
+{
+ __raw_writel((__force u32)value, efx->membase + reg);
+}
+static inline __le32 _falcon_readl(struct efx_nic *efx, unsigned int reg)
+{
+ return (__force __le32)__raw_readl(efx->membase + reg);
+}
/* Writes to a normal 16-byte Falcon register, locking as appropriate. */
static inline void falcon_write(struct efx_nic *efx, efx_oword_t *value,
diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c
index a74b7931a3c4..55c0d9760be8 100644
--- a/drivers/net/sfc/falcon_xmac.c
+++ b/drivers/net/sfc/falcon_xmac.c
@@ -221,7 +221,7 @@ static int falcon_xgmii_status(struct efx_nic *efx)
{
efx_dword_t reg;
- if (FALCON_REV(efx) < FALCON_REV_B0)
+ if (falcon_rev(efx) < FALCON_REV_B0)
return 1;
/* The ISR latches, so clear it and re-read */
@@ -241,7 +241,7 @@ static void falcon_mask_status_intr(struct efx_nic *efx, int enable)
{
efx_dword_t reg;
- if ((FALCON_REV(efx) < FALCON_REV_B0) || LOOPBACK_INTERNAL(efx))
+ if ((falcon_rev(efx) < FALCON_REV_B0) || LOOPBACK_INTERNAL(efx))
return;
/* Flush the ISR */
@@ -454,12 +454,12 @@ static int falcon_check_xaui_link_up(struct efx_nic *efx)
EFX_LOG(efx, "%s Clobbering XAUI (%d tries left).\n",
__func__, tries);
- (void) falcon_reset_xaui(efx);
+ falcon_reset_xaui(efx);
udelay(200);
tries--;
}
- EFX_ERR(efx, "Failed to bring XAUI link back up in %d tries!\n",
+ EFX_LOG(efx, "Failed to bring XAUI link back up in %d tries!\n",
max_tries);
return 0;
}
@@ -572,7 +572,7 @@ int falcon_check_xmac(struct efx_nic *efx)
xaui_link_ok = falcon_xaui_link_ok(efx);
if (EFX_WORKAROUND_5147(efx) && !xaui_link_ok)
- (void) falcon_reset_xaui(efx);
+ falcon_reset_xaui(efx);
/* Call the PHY check_hw routine */
rc = efx->phy_op->check_hw(efx);
@@ -639,7 +639,7 @@ int falcon_xmac_set_pause(struct efx_nic *efx, enum efx_fc_type flow_control)
reset = ((flow_control & EFX_FC_TX) &&
!(efx->flow_control & EFX_FC_TX));
if (EFX_WORKAROUND_11482(efx) && reset) {
- if (FALCON_REV(efx) >= FALCON_REV_B0) {
+ if (falcon_rev(efx) >= FALCON_REV_B0) {
/* Recover by resetting the EM block */
if (efx->link_up)
falcon_drain_tx_fifo(efx);
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index 59f261b4171f..5e20e7551dae 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -42,7 +42,7 @@
#ifndef EFX_DRIVER_NAME
#define EFX_DRIVER_NAME "sfc"
#endif
-#define EFX_DRIVER_VERSION "2.2.0136"
+#define EFX_DRIVER_VERSION "2.2"
#ifdef EFX_ENABLE_DEBUG
#define EFX_BUG_ON_PARANOID(x) BUG_ON(x)
@@ -52,28 +52,19 @@
#define EFX_WARN_ON_PARANOID(x) do {} while (0)
#endif
-#define NET_DEV_REGISTERED(efx) \
- ((efx)->net_dev->reg_state == NETREG_REGISTERED)
-
-/* Include net device name in log messages if it has been registered.
- * Use efx->name not efx->net_dev->name so that races with (un)registration
- * are harmless.
- */
-#define NET_DEV_NAME(efx) (NET_DEV_REGISTERED(efx) ? (efx)->name : "")
-
/* Un-rate-limited logging */
#define EFX_ERR(efx, fmt, args...) \
-dev_err(&((efx)->pci_dev->dev), "ERR: %s " fmt, NET_DEV_NAME(efx), ##args)
+dev_err(&((efx)->pci_dev->dev), "ERR: %s " fmt, efx_dev_name(efx), ##args)
#define EFX_INFO(efx, fmt, args...) \
-dev_info(&((efx)->pci_dev->dev), "INFO: %s " fmt, NET_DEV_NAME(efx), ##args)
+dev_info(&((efx)->pci_dev->dev), "INFO: %s " fmt, efx_dev_name(efx), ##args)
#ifdef EFX_ENABLE_DEBUG
#define EFX_LOG(efx, fmt, args...) \
-dev_info(&((efx)->pci_dev->dev), "DBG: %s " fmt, NET_DEV_NAME(efx), ##args)
+dev_info(&((efx)->pci_dev->dev), "DBG: %s " fmt, efx_dev_name(efx), ##args)
#else
#define EFX_LOG(efx, fmt, args...) \
-dev_dbg(&((efx)->pci_dev->dev), "DBG: %s " fmt, NET_DEV_NAME(efx), ##args)
+dev_dbg(&((efx)->pci_dev->dev), "DBG: %s " fmt, efx_dev_name(efx), ##args)
#endif
#define EFX_TRACE(efx, fmt, args...) do {} while (0)
@@ -90,11 +81,6 @@ do {if (net_ratelimit()) EFX_INFO(efx, fmt, ##args); } while (0)
#define EFX_LOG_RL(efx, fmt, args...) \
do {if (net_ratelimit()) EFX_LOG(efx, fmt, ##args); } while (0)
-/* Kernel headers may redefine inline anyway */
-#ifndef inline
-#define inline inline __attribute__ ((always_inline))
-#endif
-
/**************************************************************************
*
* Efx data structures
@@ -695,7 +681,7 @@ struct efx_nic {
struct workqueue_struct *workqueue;
struct work_struct reset_work;
struct delayed_work monitor_work;
- unsigned long membase_phys;
+ resource_size_t membase_phys;
void __iomem *membase;
spinlock_t biu_lock;
enum efx_int_mode interrupt_mode;
@@ -719,7 +705,7 @@ struct efx_nic {
unsigned n_rx_nodesc_drop_cnt;
- void *nic_data;
+ struct falcon_nic_data *nic_data;
struct mutex mac_lock;
int port_enabled;
@@ -760,6 +746,20 @@ struct efx_nic {
void *loopback_selftest;
};
+static inline int efx_dev_registered(struct efx_nic *efx)
+{
+ return efx->net_dev->reg_state == NETREG_REGISTERED;
+}
+
+/* Net device name, for inclusion in log messages if it has been registered.
+ * Use efx->name not efx->net_dev->name so that races with (un)registration
+ * are harmless.
+ */
+static inline const char *efx_dev_name(struct efx_nic *efx)
+{
+ return efx_dev_registered(efx) ? efx->name : "";
+}
+
/**
* struct efx_nic_type - Efx device type definition
* @mem_bar: Memory BAR number
@@ -795,7 +795,7 @@ struct efx_nic_type {
unsigned int txd_ring_mask;
unsigned int rxd_ring_mask;
unsigned int evq_size;
- dma_addr_t max_dma_mask;
+ u64 max_dma_mask;
unsigned int tx_dma_mask;
unsigned bug5391_mask;
diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c
index 670622373ddf..601b001437c0 100644
--- a/drivers/net/sfc/rx.c
+++ b/drivers/net/sfc/rx.c
@@ -86,14 +86,17 @@ static unsigned int rx_refill_limit = 95;
*/
#define EFX_RXD_HEAD_ROOM 2
-/* Macros for zero-order pages (potentially) containing multiple RX buffers */
-#define RX_DATA_OFFSET(_data) \
- (((unsigned long) (_data)) & (PAGE_SIZE-1))
-#define RX_BUF_OFFSET(_rx_buf) \
- RX_DATA_OFFSET((_rx_buf)->data)
-
-#define RX_PAGE_SIZE(_efx) \
- (PAGE_SIZE * (1u << (_efx)->rx_buffer_order))
+static inline unsigned int efx_rx_buf_offset(struct efx_rx_buffer *buf)
+{
+ /* Offset is always within one page, so we don't need to consider
+ * the page order.
+ */
+ return (__force unsigned long) buf->data & (PAGE_SIZE - 1);
+}
+static inline unsigned int efx_rx_buf_size(struct efx_nic *efx)
+{
+ return PAGE_SIZE << efx->rx_buffer_order;
+}
/**************************************************************************
@@ -106,7 +109,7 @@ static unsigned int rx_refill_limit = 95;
static int efx_lro_get_skb_hdr(struct sk_buff *skb, void **ip_hdr,
void **tcpudp_hdr, u64 *hdr_flags, void *priv)
{
- struct efx_channel *channel = (struct efx_channel *)priv;
+ struct efx_channel *channel = priv;
struct iphdr *iph;
struct tcphdr *th;
@@ -131,12 +134,12 @@ static int efx_get_frag_hdr(struct skb_frag_struct *frag, void **mac_hdr,
void **ip_hdr, void **tcpudp_hdr, u64 *hdr_flags,
void *priv)
{
- struct efx_channel *channel = (struct efx_channel *)priv;
+ struct efx_channel *channel = priv;
struct ethhdr *eh;
struct iphdr *iph;
/* We support EtherII and VLAN encapsulated IPv4 */
- eh = (struct ethhdr *)(page_address(frag->page) + frag->page_offset);
+ eh = page_address(frag->page) + frag->page_offset;
*mac_hdr = eh;
if (eh->h_proto == htons(ETH_P_IP)) {
@@ -269,7 +272,7 @@ static inline int efx_init_rx_buffer_page(struct efx_rx_queue *rx_queue,
return -ENOMEM;
dma_addr = pci_map_page(efx->pci_dev, rx_buf->page,
- 0, RX_PAGE_SIZE(efx),
+ 0, efx_rx_buf_size(efx),
PCI_DMA_FROMDEVICE);
if (unlikely(pci_dma_mapping_error(dma_addr))) {
@@ -280,14 +283,14 @@ static inline int efx_init_rx_buffer_page(struct efx_rx_queue *rx_queue,
rx_queue->buf_page = rx_buf->page;
rx_queue->buf_dma_addr = dma_addr;
- rx_queue->buf_data = ((char *) page_address(rx_buf->page) +
+ rx_queue->buf_data = (page_address(rx_buf->page) +
EFX_PAGE_IP_ALIGN);
}
- offset = RX_DATA_OFFSET(rx_queue->buf_data);
rx_buf->len = bytes;
- rx_buf->dma_addr = rx_queue->buf_dma_addr + offset;
rx_buf->data = rx_queue->buf_data;
+ offset = efx_rx_buf_offset(rx_buf);
+ rx_buf->dma_addr = rx_queue->buf_dma_addr + offset;
/* Try to pack multiple buffers per page */
if (efx->rx_buffer_order == 0) {
@@ -295,7 +298,7 @@ static inline int efx_init_rx_buffer_page(struct efx_rx_queue *rx_queue,
rx_queue->buf_data += ((bytes + 0x1ff) & ~0x1ff);
offset += ((bytes + 0x1ff) & ~0x1ff);
- space = RX_PAGE_SIZE(efx) - offset;
+ space = efx_rx_buf_size(efx) - offset;
if (space >= bytes) {
/* Refs dropped on kernel releasing each skb */
get_page(rx_queue->buf_page);
@@ -344,7 +347,8 @@ static inline void efx_unmap_rx_buffer(struct efx_nic *efx,
EFX_BUG_ON_PARANOID(rx_buf->skb);
if (rx_buf->unmap_addr) {
pci_unmap_page(efx->pci_dev, rx_buf->unmap_addr,
- RX_PAGE_SIZE(efx), PCI_DMA_FROMDEVICE);
+ efx_rx_buf_size(efx),
+ PCI_DMA_FROMDEVICE);
rx_buf->unmap_addr = 0;
}
} else if (likely(rx_buf->skb)) {
@@ -400,9 +404,10 @@ static int __efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue,
return 0;
/* Record minimum fill level */
- if (unlikely(fill_level < rx_queue->min_fill))
+ if (unlikely(fill_level < rx_queue->min_fill)) {
if (fill_level)
rx_queue->min_fill = fill_level;
+ }
/* Acquire RX add lock. If this lock is contended, then a fast
* fill must already be in progress (e.g. in the refill
@@ -552,7 +557,7 @@ static inline void efx_rx_packet_lro(struct efx_channel *channel,
struct skb_frag_struct frags;
frags.page = rx_buf->page;
- frags.page_offset = RX_BUF_OFFSET(rx_buf);
+ frags.page_offset = efx_rx_buf_offset(rx_buf);
frags.size = rx_buf->len;
lro_receive_frags(lro_mgr, &frags, rx_buf->len,
@@ -597,7 +602,7 @@ static inline struct sk_buff *efx_rx_mk_skb(struct efx_rx_buffer *rx_buf,
if (unlikely(rx_buf->len > hdr_len)) {
struct skb_frag_struct *frag = skb_shinfo(skb)->frags;
frag->page = rx_buf->page;
- frag->page_offset = RX_BUF_OFFSET(rx_buf) + hdr_len;
+ frag->page_offset = efx_rx_buf_offset(rx_buf) + hdr_len;
frag->size = skb->len - hdr_len;
skb_shinfo(skb)->nr_frags = 1;
skb->data_len = frag->size;
@@ -851,7 +856,8 @@ void efx_fini_rx_queue(struct efx_rx_queue *rx_queue)
/* For a page that is part-way through splitting into RX buffers */
if (rx_queue->buf_page != NULL) {
pci_unmap_page(rx_queue->efx->pci_dev, rx_queue->buf_dma_addr,
- RX_PAGE_SIZE(rx_queue->efx), PCI_DMA_FROMDEVICE);
+ efx_rx_buf_size(rx_queue->efx),
+ PCI_DMA_FROMDEVICE);
__free_pages(rx_queue->buf_page,
rx_queue->efx->rx_buffer_order);
rx_queue->buf_page = NULL;
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c
index cbda15946e8f..3b2de9fe7f27 100644
--- a/drivers/net/sfc/selftest.c
+++ b/drivers/net/sfc/selftest.c
@@ -290,7 +290,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
payload = &state->payload;
- received = (struct efx_loopback_payload *)(char *) buf_ptr;
+ received = (struct efx_loopback_payload *) buf_ptr;
received->ip.saddr = payload->ip.saddr;
received->ip.check = payload->ip.check;
@@ -424,10 +424,10 @@ static int efx_tx_loopback(struct efx_tx_queue *tx_queue)
* interrupt handler. */
smp_wmb();
- if (NET_DEV_REGISTERED(efx))
+ if (efx_dev_registered(efx))
netif_tx_lock_bh(efx->net_dev);
rc = efx_xmit(efx, tx_queue, skb);
- if (NET_DEV_REGISTERED(efx))
+ if (efx_dev_registered(efx))
netif_tx_unlock_bh(efx->net_dev);
if (rc != NETDEV_TX_OK) {
@@ -453,7 +453,7 @@ static int efx_rx_loopback(struct efx_tx_queue *tx_queue,
int tx_done = 0, rx_good, rx_bad;
int i, rc = 0;
- if (NET_DEV_REGISTERED(efx))
+ if (efx_dev_registered(efx))
netif_tx_lock_bh(efx->net_dev);
/* Count the number of tx completions, and decrement the refcnt. Any
@@ -465,7 +465,7 @@ static int efx_rx_loopback(struct efx_tx_queue *tx_queue,
dev_kfree_skb_any(skb);
}
- if (NET_DEV_REGISTERED(efx))
+ if (efx_dev_registered(efx))
netif_tx_unlock_bh(efx->net_dev);
/* Check TX completion and received packet counts */
@@ -517,6 +517,8 @@ efx_test_loopback(struct efx_tx_queue *tx_queue,
state->packet_count = min(1 << (i << 2), state->packet_count);
state->skbs = kzalloc(sizeof(state->skbs[0]) *
state->packet_count, GFP_KERNEL);
+ if (!state->skbs)
+ return -ENOMEM;
state->flush = 0;
EFX_LOG(efx, "TX queue %d testing %s loopback with %d "
@@ -700,7 +702,7 @@ int efx_offline_test(struct efx_nic *efx,
* "flushing" so all inflight packets are dropped */
BUG_ON(efx->loopback_selftest);
state->flush = 1;
- efx->loopback_selftest = (void *)state;
+ efx->loopback_selftest = state;
rc = efx_test_loopbacks(efx, tests, loopback_modes);
diff --git a/drivers/net/sfc/sfe4001.c b/drivers/net/sfc/sfe4001.c
index 725d1a539c49..66a0d1442aba 100644
--- a/drivers/net/sfc/sfe4001.c
+++ b/drivers/net/sfc/sfe4001.c
@@ -116,18 +116,18 @@ void sfe4001_poweroff(struct efx_nic *efx)
/* Turn off all power rails */
out = 0xff;
- (void) efx_i2c_write(i2c, PCA9539, P0_OUT, &out, 1);
+ efx_i2c_write(i2c, PCA9539, P0_OUT, &out, 1);
/* Disable port 1 outputs on IO expander */
cfg = 0xff;
- (void) efx_i2c_write(i2c, PCA9539, P1_CONFIG, &cfg, 1);
+ efx_i2c_write(i2c, PCA9539, P1_CONFIG, &cfg, 1);
/* Disable port 0 outputs on IO expander */
cfg = 0xff;
- (void) efx_i2c_write(i2c, PCA9539, P0_CONFIG, &cfg, 1);
+ efx_i2c_write(i2c, PCA9539, P0_CONFIG, &cfg, 1);
/* Clear any over-temperature alert */
- (void) efx_i2c_read(i2c, MAX6647, RSL, &in, 1);
+ efx_i2c_read(i2c, MAX6647, RSL, &in, 1);
}
/* The P0_EN_3V3X line on SFE4001 boards (from A2 onward) is connected
@@ -253,14 +253,14 @@ done:
fail3:
/* Turn off all power rails */
out = 0xff;
- (void) efx_i2c_write(i2c, PCA9539, P0_OUT, &out, 1);
+ efx_i2c_write(i2c, PCA9539, P0_OUT, &out, 1);
/* Disable port 1 outputs on IO expander */
out = 0xff;
- (void) efx_i2c_write(i2c, PCA9539, P1_CONFIG, &out, 1);
+ efx_i2c_write(i2c, PCA9539, P1_CONFIG, &out, 1);
fail2:
/* Disable port 0 outputs on IO expander */
out = 0xff;
- (void) efx_i2c_write(i2c, PCA9539, P0_CONFIG, &out, 1);
+ efx_i2c_write(i2c, PCA9539, P0_CONFIG, &out, 1);
fail1:
return rc;
}
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index b1cd6deec01f..c0146061c326 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -211,6 +211,8 @@ static int tenxpress_phy_init(struct efx_nic *efx)
int rc = 0;
phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
+ if (!phy_data)
+ return -ENOMEM;
efx->phy_data = phy_data;
tenxpress_set_state(efx, TENXPRESS_STATUS_NORMAL);
@@ -376,7 +378,7 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx)
* perform a special software reset */
if ((phy_data->tx_disabled && !efx->tx_disabled) ||
loop_change) {
- (void) tenxpress_special_reset(efx);
+ tenxpress_special_reset(efx);
falcon_reset_xaui(efx);
}
diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c
index 9b436f5b4888..5cdd082ab8f6 100644
--- a/drivers/net/sfc/tx.c
+++ b/drivers/net/sfc/tx.c
@@ -387,7 +387,7 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
if (unlikely(tx_queue->stopped)) {
fill_level = tx_queue->insert_count - tx_queue->read_count;
if (fill_level < EFX_NETDEV_TX_THRESHOLD(tx_queue)) {
- EFX_BUG_ON_PARANOID(!NET_DEV_REGISTERED(efx));
+ EFX_BUG_ON_PARANOID(!efx_dev_registered(efx));
/* Do this under netif_tx_lock(), to avoid racing
* with efx_xmit(). */
@@ -639,11 +639,12 @@ static void efx_tsoh_block_free(struct efx_tx_queue *tx_queue,
base_dma = tsoh->dma_addr & PAGE_MASK;
p = &tx_queue->tso_headers_free;
- while (*p != NULL)
+ while (*p != NULL) {
if (((unsigned long)*p & PAGE_MASK) == base_kva)
*p = (*p)->next;
else
p = &(*p)->next;
+ }
pci_free_consistent(pci_dev, PAGE_SIZE, (void *)base_kva, base_dma);
}
@@ -939,9 +940,10 @@ static inline int tso_start_new_packet(struct efx_tx_queue *tx_queue,
/* Allocate a DMA-mapped header buffer. */
if (likely(TSOH_SIZE(st->p.header_length) <= TSOH_STD_SIZE)) {
- if (tx_queue->tso_headers_free == NULL)
+ if (tx_queue->tso_headers_free == NULL) {
if (efx_tsoh_block_alloc(tx_queue))
return -1;
+ }
EFX_BUG_ON_PARANOID(!tx_queue->tso_headers_free);
tsoh = tx_queue->tso_headers_free;
tx_queue->tso_headers_free = tsoh->next;
@@ -1106,9 +1108,10 @@ static void efx_fini_tso(struct efx_tx_queue *tx_queue)
{
unsigned i;
- if (tx_queue->buffer)
+ if (tx_queue->buffer) {
for (i = 0; i <= tx_queue->efx->type->txd_ring_mask; ++i)
efx_tsoh_free(tx_queue, &tx_queue->buffer[i]);
+ }
while (tx_queue->tso_headers_free != NULL)
efx_tsoh_block_free(tx_queue, tx_queue->tso_headers_free,
diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h
index dca62f190198..35ab19c27f8d 100644
--- a/drivers/net/sfc/workarounds.h
+++ b/drivers/net/sfc/workarounds.h
@@ -16,7 +16,7 @@
*/
#define EFX_WORKAROUND_ALWAYS(efx) 1
-#define EFX_WORKAROUND_FALCON_A(efx) (FALCON_REV(efx) <= FALCON_REV_A1)
+#define EFX_WORKAROUND_FALCON_A(efx) (falcon_rev(efx) <= FALCON_REV_A1)
/* XAUI resets if link not detected */
#define EFX_WORKAROUND_5147 EFX_WORKAROUND_ALWAYS
diff --git a/drivers/net/sfc/xfp_phy.c b/drivers/net/sfc/xfp_phy.c
index 3b9f9ddbc372..f3684ad28887 100644
--- a/drivers/net/sfc/xfp_phy.c
+++ b/drivers/net/sfc/xfp_phy.c
@@ -85,7 +85,9 @@ static int xfp_phy_init(struct efx_nic *efx)
int rc;
phy_data = kzalloc(sizeof(struct xfp_phy_data), GFP_KERNEL);
- efx->phy_data = (void *) phy_data;
+ if (!phy_data)
+ return -ENOMEM;
+ efx->phy_data = phy_data;
EFX_INFO(efx, "XFP: PHY ID reg %x (OUI %x model %x revision"
" %x)\n", devid, MDIO_ID_OUI(devid), MDIO_ID_MODEL(devid),
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index f226bcac7d17..3bb60530d4d7 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -1159,17 +1159,9 @@ static int sky2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
}
#ifdef SKY2_VLAN_TAG_USED
-static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
+static void sky2_set_vlan_mode(struct sky2_hw *hw, u16 port, bool onoff)
{
- struct sky2_port *sky2 = netdev_priv(dev);
- struct sky2_hw *hw = sky2->hw;
- u16 port = sky2->port;
-
- netif_tx_lock_bh(dev);
- napi_disable(&hw->napi);
-
- sky2->vlgrp = grp;
- if (grp) {
+ if (onoff) {
sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
RX_VLAN_STRIP_ON);
sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
@@ -1180,6 +1172,19 @@ static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp
sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
TX_VLAN_TAG_OFF);
}
+}
+
+static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ u16 port = sky2->port;
+
+ netif_tx_lock_bh(dev);
+ napi_disable(&hw->napi);
+
+ sky2->vlgrp = grp;
+ sky2_set_vlan_mode(hw, port, grp != NULL);
sky2_read32(hw, B0_Y2_SP_LISR);
napi_enable(&hw->napi);
@@ -1418,6 +1423,10 @@ static int sky2_up(struct net_device *dev)
sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map,
TX_RING_SIZE - 1);
+#ifdef SKY2_VLAN_TAG_USED
+ sky2_set_vlan_mode(hw, port, sky2->vlgrp != NULL);
+#endif
+
err = sky2_rx_start(sky2);
if (err)
goto err_out;
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index b4e7f30ea4e8..1aa425be3067 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -111,7 +111,7 @@ static __inline__ void tx_add_log(struct happy_meal *hp, unsigned int a, unsigne
struct hme_tx_logent *tlp;
unsigned long flags;
- save_and_cli(flags);
+ local_irq_save(flags);
tlp = &tx_log[txlog_cur_entry];
tlp->tstamp = (unsigned int)jiffies;
tlp->tx_new = hp->tx_new;
@@ -119,7 +119,7 @@ static __inline__ void tx_add_log(struct happy_meal *hp, unsigned int a, unsigne
tlp->action = a;
tlp->status = s;
txlog_cur_entry = (txlog_cur_entry + 1) & (TX_LOG_LEN - 1);
- restore_flags(flags);
+ local_irq_restore(flags);
}
static __inline__ void tx_dump_log(void)
{
diff --git a/drivers/net/tokenring/3c359.h b/drivers/net/tokenring/3c359.h
index b880cba0f6fd..74cf8e1a181b 100644
--- a/drivers/net/tokenring/3c359.h
+++ b/drivers/net/tokenring/3c359.h
@@ -264,7 +264,7 @@ struct xl_private {
u16 asb;
u8 __iomem *xl_mmio;
- char *xl_card_name;
+ const char *xl_card_name;
struct pci_dev *pdev ;
spinlock_t xl_lock ;
diff --git a/drivers/net/tokenring/olympic.h b/drivers/net/tokenring/olympic.h
index c91956310fb2..10fbba08978f 100644
--- a/drivers/net/tokenring/olympic.h
+++ b/drivers/net/tokenring/olympic.h
@@ -254,7 +254,7 @@ struct olympic_private {
u8 __iomem *olympic_mmio;
u8 __iomem *olympic_lap;
struct pci_dev *pdev ;
- char *olympic_card_name ;
+ const char *olympic_card_name;
spinlock_t olympic_lock ;
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index f9d13fa05d64..55670b5eb611 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -1729,12 +1729,15 @@ static int tulip_suspend (struct pci_dev *pdev, pm_message_t state)
if (!dev)
return -EINVAL;
- if (netif_running(dev))
- tulip_down(dev);
+ if (!netif_running(dev))
+ goto save_state;
+
+ tulip_down(dev);
netif_device_detach(dev);
free_irq(dev->irq, dev);
+save_state:
pci_save_state(pdev);
pci_disable_device(pdev);
pci_set_power_state(pdev, pci_choose_state(pdev, state));
@@ -1754,6 +1757,9 @@ static int tulip_resume(struct pci_dev *pdev)
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
+ if (!netif_running(dev))
+ return 0;
+
if ((retval = pci_enable_device(pdev))) {
printk (KERN_ERR "tulip: pci_enable_device failed in resume\n");
return retval;
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c
index 2511ca7a12aa..e9e628621639 100644
--- a/drivers/net/tulip/uli526x.c
+++ b/drivers/net/tulip/uli526x.c
@@ -225,6 +225,9 @@ static void uli526x_set_filter_mode(struct net_device *);
static const struct ethtool_ops netdev_ethtool_ops;
static u16 read_srom_word(long, int);
static irqreturn_t uli526x_interrupt(int, void *);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void uli526x_poll(struct net_device *dev);
+#endif
static void uli526x_descriptor_init(struct uli526x_board_info *, unsigned long);
static void allocate_rx_buffer(struct uli526x_board_info *);
static void update_cr6(u32, unsigned long);
@@ -339,6 +342,9 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev,
dev->get_stats = &uli526x_get_stats;
dev->set_multicast_list = &uli526x_set_filter_mode;
dev->ethtool_ops = &netdev_ethtool_ops;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = &uli526x_poll;
+#endif
spin_lock_init(&db->lock);
@@ -681,8 +687,9 @@ static irqreturn_t uli526x_interrupt(int irq, void *dev_id)
db->cr5_data = inl(ioaddr + DCR5);
outl(db->cr5_data, ioaddr + DCR5);
if ( !(db->cr5_data & 0x180c1) ) {
- spin_unlock_irqrestore(&db->lock, flags);
+ /* Restore CR7 to enable interrupt mask */
outl(db->cr7_data, ioaddr + DCR7);
+ spin_unlock_irqrestore(&db->lock, flags);
return IRQ_HANDLED;
}
@@ -715,6 +722,13 @@ static irqreturn_t uli526x_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void uli526x_poll(struct net_device *dev)
+{
+ /* ISR grabs the irqsave lock, so this should be safe */
+ uli526x_interrupt(dev->irq, dev);
+}
+#endif
/*
* Free TX resource after TX complete
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index ca0bdac07a78..fb0b918e5ccb 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -237,7 +237,7 @@ static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth,
skb->dev = ugeth->dev;
out_be32(&((struct qe_bd __iomem *)bd)->buf,
- dma_map_single(NULL,
+ dma_map_single(&ugeth->dev->dev,
skb->data,
ugeth->ug_info->uf_info.max_rx_buf_length +
UCC_GETH_RX_DATA_BUF_ALIGNMENT,
@@ -2158,7 +2158,7 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth)
continue;
for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) {
if (ugeth->tx_skbuff[i][j]) {
- dma_unmap_single(NULL,
+ dma_unmap_single(&ugeth->dev->dev,
in_be32(&((struct qe_bd __iomem *)bd)->buf),
(in_be32((u32 __iomem *)bd) &
BD_LENGTH_MASK),
@@ -2186,7 +2186,7 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth)
bd = ugeth->p_rx_bd_ring[i];
for (j = 0; j < ugeth->ug_info->bdRingLenRx[i]; j++) {
if (ugeth->rx_skbuff[i][j]) {
- dma_unmap_single(NULL,
+ dma_unmap_single(&ugeth->dev->dev,
in_be32(&((struct qe_bd __iomem *)bd)->buf),
ugeth->ug_info->
uf_info.max_rx_buf_length +
@@ -3406,7 +3406,8 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* set up the buffer descriptor */
out_be32(&((struct qe_bd __iomem *)bd)->buf,
- dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE));
+ dma_map_single(&ugeth->dev->dev, skb->data,
+ skb->len, DMA_TO_DEVICE));
/* printk(KERN_DEBUG"skb->data is 0x%x\n",skb->data); */
diff --git a/drivers/net/ucc_geth_ethtool.c b/drivers/net/ucc_geth_ethtool.c
index 299b7f176950..f5839c4a5cbd 100644
--- a/drivers/net/ucc_geth_ethtool.c
+++ b/drivers/net/ucc_geth_ethtool.c
@@ -73,6 +73,7 @@ static char tx_fw_stat_gstrings[][ETH_GSTRING_LEN] = {
"tx-frames-ok",
"tx-excessive-differ-frames",
"tx-256-511-frames",
+ "tx-512-1023-frames",
"tx-1024-1518-frames",
"tx-jumbo-frames",
};
@@ -308,7 +309,7 @@ static void uec_get_strings(struct net_device *netdev, u32 stringset, u8 *buf)
buf += UEC_TX_FW_STATS_LEN * ETH_GSTRING_LEN;
}
if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX)
- memcpy(buf, tx_fw_stat_gstrings, UEC_RX_FW_STATS_LEN *
+ memcpy(buf, rx_fw_stat_gstrings, UEC_RX_FW_STATS_LEN *
ETH_GSTRING_LEN);
}
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index dc6f097062df..37ecf845edfe 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -1440,6 +1440,10 @@ static const struct usb_device_id products [] = {
// Belkin F5D5055
USB_DEVICE(0x050d, 0x5055),
.driver_info = (unsigned long) &ax88178_info,
+}, {
+ // Apple USB Ethernet Adapter
+ USB_DEVICE(0x05ac, 0x1402),
+ .driver_info = (unsigned long) &ax88772_info,
},
{ }, // END
};
diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c
index 3969b7a2b8e6..ae467f182c40 100644
--- a/drivers/net/usb/rndis_host.c
+++ b/drivers/net/usb/rndis_host.c
@@ -194,7 +194,7 @@ int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf)
dev_dbg(&info->control->dev,
"rndis response error, code %d\n", retval);
}
- msleep(2);
+ msleep(20);
}
dev_dbg(&info->control->dev, "rndis response timeout\n");
return -ETIMEDOUT;
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index f926b5ab3d09..5450eac9e263 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -47,6 +47,9 @@ struct virtnet_info
/* Number of input buffers, and max we've ever had. */
unsigned int num, max;
+ /* For cleaning up after transmission. */
+ struct tasklet_struct tasklet;
+
/* Receive & send queues. */
struct sk_buff_head recv;
struct sk_buff_head send;
@@ -68,8 +71,13 @@ static void skb_xmit_done(struct virtqueue *svq)
/* Suppress further interrupts. */
svq->vq_ops->disable_cb(svq);
+
/* We were waiting for more output buffers. */
netif_wake_queue(vi->dev);
+
+ /* Make sure we re-xmit last_xmit_skb: if there are no more packets
+ * queued, start_xmit won't be called. */
+ tasklet_schedule(&vi->tasklet);
}
static void receive_skb(struct net_device *dev, struct sk_buff *skb,
@@ -278,6 +286,18 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
return vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb);
}
+static void xmit_tasklet(unsigned long data)
+{
+ struct virtnet_info *vi = (void *)data;
+
+ netif_tx_lock_bh(vi->dev);
+ if (vi->last_xmit_skb && xmit_skb(vi, vi->last_xmit_skb) == 0) {
+ vi->svq->vq_ops->kick(vi->svq);
+ vi->last_xmit_skb = NULL;
+ }
+ netif_tx_unlock_bh(vi->dev);
+}
+
static int start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct virtnet_info *vi = netdev_priv(dev);
@@ -287,21 +307,25 @@ again:
free_old_xmit_skbs(vi);
/* If we has a buffer left over from last time, send it now. */
- if (vi->last_xmit_skb) {
+ if (unlikely(vi->last_xmit_skb)) {
if (xmit_skb(vi, vi->last_xmit_skb) != 0) {
/* Drop this skb: we only queue one. */
vi->dev->stats.tx_dropped++;
kfree_skb(skb);
+ skb = NULL;
goto stop_queue;
}
vi->last_xmit_skb = NULL;
}
/* Put new one in send queue and do transmit */
- __skb_queue_head(&vi->send, skb);
- if (xmit_skb(vi, skb) != 0) {
- vi->last_xmit_skb = skb;
- goto stop_queue;
+ if (likely(skb)) {
+ __skb_queue_head(&vi->send, skb);
+ if (xmit_skb(vi, skb) != 0) {
+ vi->last_xmit_skb = skb;
+ skb = NULL;
+ goto stop_queue;
+ }
}
done:
vi->svq->vq_ops->kick(vi->svq);
@@ -428,6 +452,8 @@ static int virtnet_probe(struct virtio_device *vdev)
skb_queue_head_init(&vi->recv);
skb_queue_head_init(&vi->send);
+ tasklet_init(&vi->tasklet, xmit_tasklet, (unsigned long)vi);
+
err = register_netdev(dev);
if (err) {
pr_debug("virtio_net: registering device failed\n");
@@ -470,8 +496,7 @@ static void virtnet_remove(struct virtio_device *vdev)
kfree_skb(skb);
vi->num--;
}
- while ((skb = __skb_dequeue(&vi->send)) != NULL)
- kfree_skb(skb);
+ __skb_queue_purge(&vi->send);
BUG_ON(vi->num != 0);
diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c
index 9a83c9d5b8cf..7f984895b0d5 100644
--- a/drivers/net/wan/hdlc.c
+++ b/drivers/net/wan/hdlc.c
@@ -43,8 +43,7 @@ static const char* version = "HDLC support module revision 1.22";
#undef DEBUG_LINK
-static struct hdlc_proto *first_proto = NULL;
-
+static struct hdlc_proto *first_proto;
static int hdlc_change_mtu(struct net_device *dev, int new_mtu)
{
@@ -314,21 +313,25 @@ void detach_hdlc_protocol(struct net_device *dev)
void register_hdlc_protocol(struct hdlc_proto *proto)
{
+ rtnl_lock();
proto->next = first_proto;
first_proto = proto;
+ rtnl_unlock();
}
void unregister_hdlc_protocol(struct hdlc_proto *proto)
{
- struct hdlc_proto **p = &first_proto;
- while (*p) {
- if (*p == proto) {
- *p = proto->next;
- return;
- }
+ struct hdlc_proto **p;
+
+ rtnl_lock();
+ p = &first_proto;
+ while (*p != proto) {
+ BUG_ON(!*p);
p = &((*p)->next);
}
+ *p = proto->next;
+ rtnl_unlock();
}
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index 7133c688cf20..762d21c1c703 100644
--- a/drivers/net/wan/hdlc_cisco.c
+++ b/drivers/net/wan/hdlc_cisco.c
@@ -56,6 +56,7 @@ struct cisco_state {
cisco_proto settings;
struct timer_list timer;
+ spinlock_t lock;
unsigned long last_poll;
int up;
int request_sent;
@@ -158,6 +159,7 @@ static int cisco_rx(struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
hdlc_device *hdlc = dev_to_hdlc(dev);
+ struct cisco_state *st = state(hdlc);
struct hdlc_header *data = (struct hdlc_header*)skb->data;
struct cisco_packet *cisco_data;
struct in_device *in_dev;
@@ -220,11 +222,12 @@ static int cisco_rx(struct sk_buff *skb)
goto rx_error;
case CISCO_KEEPALIVE_REQ:
- state(hdlc)->rxseq = ntohl(cisco_data->par1);
- if (state(hdlc)->request_sent &&
- ntohl(cisco_data->par2) == state(hdlc)->txseq) {
- state(hdlc)->last_poll = jiffies;
- if (!state(hdlc)->up) {
+ spin_lock(&st->lock);
+ st->rxseq = ntohl(cisco_data->par1);
+ if (st->request_sent &&
+ ntohl(cisco_data->par2) == st->txseq) {
+ st->last_poll = jiffies;
+ if (!st->up) {
u32 sec, min, hrs, days;
sec = ntohl(cisco_data->time) / 1000;
min = sec / 60; sec -= min * 60;
@@ -232,12 +235,12 @@ static int cisco_rx(struct sk_buff *skb)
days = hrs / 24; hrs -= days * 24;
printk(KERN_INFO "%s: Link up (peer "
"uptime %ud%uh%um%us)\n",
- dev->name, days, hrs,
- min, sec);
+ dev->name, days, hrs, min, sec);
netif_dormant_off(dev);
- state(hdlc)->up = 1;
+ st->up = 1;
}
}
+ spin_unlock(&st->lock);
dev_kfree_skb_any(skb);
return NET_RX_SUCCESS;
@@ -261,24 +264,25 @@ static void cisco_timer(unsigned long arg)
{
struct net_device *dev = (struct net_device *)arg;
hdlc_device *hdlc = dev_to_hdlc(dev);
+ struct cisco_state *st = state(hdlc);
- if (state(hdlc)->up &&
- time_after(jiffies, state(hdlc)->last_poll +
- state(hdlc)->settings.timeout * HZ)) {
- state(hdlc)->up = 0;
+ spin_lock(&st->lock);
+ if (st->up &&
+ time_after(jiffies, st->last_poll + st->settings.timeout * HZ)) {
+ st->up = 0;
printk(KERN_INFO "%s: Link down\n", dev->name);
netif_dormant_on(dev);
}
- cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ,
- htonl(++state(hdlc)->txseq),
- htonl(state(hdlc)->rxseq));
- state(hdlc)->request_sent = 1;
- state(hdlc)->timer.expires = jiffies +
- state(hdlc)->settings.interval * HZ;
- state(hdlc)->timer.function = cisco_timer;
- state(hdlc)->timer.data = arg;
- add_timer(&state(hdlc)->timer);
+ cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, htonl(++st->txseq),
+ htonl(st->rxseq));
+ st->request_sent = 1;
+ spin_unlock(&st->lock);
+
+ st->timer.expires = jiffies + st->settings.interval * HZ;
+ st->timer.function = cisco_timer;
+ st->timer.data = arg;
+ add_timer(&st->timer);
}
@@ -286,15 +290,20 @@ static void cisco_timer(unsigned long arg)
static void cisco_start(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
- state(hdlc)->up = 0;
- state(hdlc)->request_sent = 0;
- state(hdlc)->txseq = state(hdlc)->rxseq = 0;
-
- init_timer(&state(hdlc)->timer);
- state(hdlc)->timer.expires = jiffies + HZ; /*First poll after 1s*/
- state(hdlc)->timer.function = cisco_timer;
- state(hdlc)->timer.data = (unsigned long)dev;
- add_timer(&state(hdlc)->timer);
+ struct cisco_state *st = state(hdlc);
+ unsigned long flags;
+
+ spin_lock_irqsave(&st->lock, flags);
+ st->up = 0;
+ st->request_sent = 0;
+ st->txseq = st->rxseq = 0;
+ spin_unlock_irqrestore(&st->lock, flags);
+
+ init_timer(&st->timer);
+ st->timer.expires = jiffies + HZ; /* First poll after 1 s */
+ st->timer.function = cisco_timer;
+ st->timer.data = (unsigned long)dev;
+ add_timer(&st->timer);
}
@@ -302,10 +311,16 @@ static void cisco_start(struct net_device *dev)
static void cisco_stop(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
- del_timer_sync(&state(hdlc)->timer);
+ struct cisco_state *st = state(hdlc);
+ unsigned long flags;
+
+ del_timer_sync(&st->timer);
+
+ spin_lock_irqsave(&st->lock, flags);
netif_dormant_on(dev);
- state(hdlc)->up = 0;
- state(hdlc)->request_sent = 0;
+ st->up = 0;
+ st->request_sent = 0;
+ spin_unlock_irqrestore(&st->lock, flags);
}
@@ -367,6 +382,7 @@ static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
return result;
memcpy(&state(hdlc)->settings, &new_settings, size);
+ spin_lock_init(&state(hdlc)->lock);
dev->hard_start_xmit = hdlc->xmit;
dev->header_ops = &cisco_header_ops;
dev->type = ARPHRD_CISCO;
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 4e1c690ff45f..32019fb878d8 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -2905,7 +2905,7 @@ EXPORT_SYMBOL(init_airo_card);
static int waitbusy (struct airo_info *ai) {
int delay = 0;
- while ((IN4500 (ai, COMMAND) & COMMAND_BUSY) && (delay < 10000)) {
+ while ((IN4500(ai, COMMAND) & COMMAND_BUSY) && (delay < 10000)) {
udelay (10);
if ((++delay % 20) == 0)
OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY);
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 37783cdd301a..dfa4bdd5597c 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -737,6 +737,7 @@ struct b43_wl {
struct ieee80211_tx_control beacon_txctl;
bool beacon0_uploaded;
bool beacon1_uploaded;
+ bool beacon_templates_virgin; /* Never wrote the templates? */
struct work_struct beacon_update_trigger;
/* The current QOS parameters for the 4 queues.
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 8fdba9415c04..6c3d9ea0a9f8 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -1544,6 +1544,30 @@ static void b43_write_probe_resp_template(struct b43_wldev *dev,
kfree(probe_resp_data);
}
+static void b43_upload_beacon0(struct b43_wldev *dev)
+{
+ struct b43_wl *wl = dev->wl;
+
+ if (wl->beacon0_uploaded)
+ return;
+ b43_write_beacon_template(dev, 0x68, 0x18);
+ /* FIXME: Probe resp upload doesn't really belong here,
+ * but we don't use that feature anyway. */
+ b43_write_probe_resp_template(dev, 0x268, 0x4A,
+ &__b43_ratetable[3]);
+ wl->beacon0_uploaded = 1;
+}
+
+static void b43_upload_beacon1(struct b43_wldev *dev)
+{
+ struct b43_wl *wl = dev->wl;
+
+ if (wl->beacon1_uploaded)
+ return;
+ b43_write_beacon_template(dev, 0x468, 0x1A);
+ wl->beacon1_uploaded = 1;
+}
+
static void handle_irq_beacon(struct b43_wldev *dev)
{
struct b43_wl *wl = dev->wl;
@@ -1568,24 +1592,27 @@ static void handle_irq_beacon(struct b43_wldev *dev)
return;
}
- if (!beacon0_valid) {
- if (!wl->beacon0_uploaded) {
- b43_write_beacon_template(dev, 0x68, 0x18);
- b43_write_probe_resp_template(dev, 0x268, 0x4A,
- &__b43_ratetable[3]);
- wl->beacon0_uploaded = 1;
- }
+ if (unlikely(wl->beacon_templates_virgin)) {
+ /* We never uploaded a beacon before.
+ * Upload both templates now, but only mark one valid. */
+ wl->beacon_templates_virgin = 0;
+ b43_upload_beacon0(dev);
+ b43_upload_beacon1(dev);
cmd = b43_read32(dev, B43_MMIO_MACCMD);
cmd |= B43_MACCMD_BEACON0_VALID;
b43_write32(dev, B43_MMIO_MACCMD, cmd);
- } else if (!beacon1_valid) {
- if (!wl->beacon1_uploaded) {
- b43_write_beacon_template(dev, 0x468, 0x1A);
- wl->beacon1_uploaded = 1;
+ } else {
+ if (!beacon0_valid) {
+ b43_upload_beacon0(dev);
+ cmd = b43_read32(dev, B43_MMIO_MACCMD);
+ cmd |= B43_MACCMD_BEACON0_VALID;
+ b43_write32(dev, B43_MMIO_MACCMD, cmd);
+ } else if (!beacon1_valid) {
+ b43_upload_beacon1(dev);
+ cmd = b43_read32(dev, B43_MMIO_MACCMD);
+ cmd |= B43_MACCMD_BEACON1_VALID;
+ b43_write32(dev, B43_MMIO_MACCMD, cmd);
}
- cmd = b43_read32(dev, B43_MMIO_MACCMD);
- cmd |= B43_MACCMD_BEACON1_VALID;
- b43_write32(dev, B43_MMIO_MACCMD, cmd);
}
}
@@ -4073,6 +4100,9 @@ static int b43_op_start(struct ieee80211_hw *hw)
wl->filter_flags = 0;
wl->radiotap_enabled = 0;
b43_qos_clear(wl);
+ wl->beacon0_uploaded = 0;
+ wl->beacon1_uploaded = 0;
+ wl->beacon_templates_virgin = 1;
/* First register RFkill.
* LEDs that are registered later depend on it. */
@@ -4241,7 +4271,9 @@ static void b43_chip_reset(struct work_struct *work)
goto out;
}
}
- out:
+out:
+ if (err)
+ wl->current_dev = NULL; /* Failed to init the dev. */
mutex_unlock(&wl->mutex);
if (err)
b43err(wl, "Controller restart FAILED\n");
@@ -4382,9 +4414,11 @@ static void b43_one_core_detach(struct ssb_device *dev)
struct b43_wldev *wldev;
struct b43_wl *wl;
+ /* Do not cancel ieee80211-workqueue based work here.
+ * See comment in b43_remove(). */
+
wldev = ssb_get_drvdata(dev);
wl = wldev->wl;
- cancel_work_sync(&wldev->restart_work);
b43_debugfs_remove_device(wldev);
b43_wireless_core_detach(wldev);
list_del(&wldev->list);
@@ -4569,6 +4603,10 @@ static void b43_remove(struct ssb_device *dev)
struct b43_wl *wl = ssb_get_devtypedata(dev);
struct b43_wldev *wldev = ssb_get_drvdata(dev);
+ /* We must cancel any work here before unregistering from ieee80211,
+ * as the ieee80211 unreg will destroy the workqueue. */
+ cancel_work_sync(&wldev->restart_work);
+
B43_WARN_ON(!wl);
if (wl->current_dev == wldev)
ieee80211_unregister_hw(wl->hw);
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 14a5eea2573e..204077c13870 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -3039,7 +3039,6 @@ static void b43legacy_set_pretbtt(struct b43legacy_wldev *dev)
/* Locking: wl->mutex */
static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
{
- struct b43legacy_wl *wl = dev->wl;
struct b43legacy_phy *phy = &dev->phy;
u32 macctl;
@@ -3054,12 +3053,6 @@ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
macctl |= B43legacy_MACCTL_PSM_JMP0;
b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
- mutex_unlock(&wl->mutex);
- /* Must unlock as it would otherwise deadlock. No races here.
- * Cancel possibly pending workqueues. */
- cancel_work_sync(&dev->restart_work);
- mutex_lock(&wl->mutex);
-
b43legacy_leds_exit(dev);
b43legacy_rng_exit(dev->wl);
b43legacy_pio_free(dev);
@@ -3486,6 +3479,8 @@ static void b43legacy_chip_reset(struct work_struct *work)
}
}
out:
+ if (err)
+ wl->current_dev = NULL; /* Failed to init the dev. */
mutex_unlock(&wl->mutex);
if (err)
b43legacyerr(wl, "Controller restart FAILED\n");
@@ -3618,9 +3613,11 @@ static void b43legacy_one_core_detach(struct ssb_device *dev)
struct b43legacy_wldev *wldev;
struct b43legacy_wl *wl;
+ /* Do not cancel ieee80211-workqueue based work here.
+ * See comment in b43legacy_remove(). */
+
wldev = ssb_get_drvdata(dev);
wl = wldev->wl;
- cancel_work_sync(&wldev->restart_work);
b43legacy_debugfs_remove_device(wldev);
b43legacy_wireless_core_detach(wldev);
list_del(&wldev->list);
@@ -3789,6 +3786,10 @@ static void b43legacy_remove(struct ssb_device *dev)
struct b43legacy_wl *wl = ssb_get_devtypedata(dev);
struct b43legacy_wldev *wldev = ssb_get_drvdata(dev);
+ /* We must cancel any work here before unregistering from ieee80211,
+ * as the ieee80211 unreg will destroy the workqueue. */
+ cancel_work_sync(&wldev->restart_work);
+
B43legacy_WARN_ON(!wl);
if (wl->current_dev == wldev)
ieee80211_unregister_hw(wl->hw);
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index d74c061994ae..729336774828 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -7558,8 +7558,31 @@ static int ipw_associate(void *data)
priv->ieee->iw_mode == IW_MODE_ADHOC &&
priv->config & CFG_ADHOC_CREATE &&
priv->config & CFG_STATIC_ESSID &&
- priv->config & CFG_STATIC_CHANNEL &&
- !list_empty(&priv->ieee->network_free_list)) {
+ priv->config & CFG_STATIC_CHANNEL) {
+ /* Use oldest network if the free list is empty */
+ if (list_empty(&priv->ieee->network_free_list)) {
+ struct ieee80211_network *oldest = NULL;
+ struct ieee80211_network *target;
+ DECLARE_MAC_BUF(mac);
+
+ list_for_each_entry(target, &priv->ieee->network_list, list) {
+ if ((oldest == NULL) ||
+ (target->last_scanned < oldest->last_scanned))
+ oldest = target;
+ }
+
+ /* If there are no more slots, expire the oldest */
+ list_del(&oldest->list);
+ target = oldest;
+ IPW_DEBUG_ASSOC("Expired '%s' (%s) from "
+ "network list.\n",
+ escape_essid(target->ssid,
+ target->ssid_len),
+ print_mac(mac, target->bssid));
+ list_add_tail(&target->list,
+ &priv->ieee->network_free_list);
+ }
+
element = priv->ieee->network_free_list.next;
network = list_entry(element, struct ieee80211_network, list);
ipw_adhoc_create(priv, network);
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
index c9847b1a67f7..3a7f0cb710ec 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
@@ -1162,7 +1162,6 @@ static s32 rs_get_best_rate(struct iwl_priv *priv,
/* Higher rate not available, use the original */
} else {
- new_rate = rate;
break;
}
}
@@ -2009,7 +2008,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
* 2) Not just finishing up a search
* 3) Allowing a new search
*/
- if (!update_lq && !done_search && !lq_sta->stay_in_tbl) {
+ if (!update_lq && !done_search && !lq_sta->stay_in_tbl && window->counter) {
/* Save current throughput to compare with "search" throughput*/
lq_sta->last_tpt = current_tpt;
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index ad2fabca9116..0aa0ce3b2c42 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -312,8 +312,8 @@ static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask,
if (tlv_type != TLV_TYPE_BCNMISS)
tlv->freq = freq;
- /* The command header, the event mask, and the one TLV */
- events->hdr.size = cpu_to_le16(sizeof(events->hdr) + 2 + sizeof(*tlv));
+ /* The command header, the action, the event mask, and one TLV */
+ events->hdr.size = cpu_to_le16(sizeof(events->hdr) + 4 + sizeof(*tlv));
ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events);
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index 98ddbb3b3273..1610a7308c1d 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -49,6 +49,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
{USB_DEVICE(0x5041, 0x2235)}, /* Linksys WUSB54G Portable */
/* Version 2 devices (3887) */
+ {USB_DEVICE(0x0471, 0x1230)}, /* Philips CPWUA054/00 */
{USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */
{USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */
{USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index d0b1fb15c709..18c9931e3267 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -116,6 +116,7 @@ MODULE_PARM_DESC(workaround_interval,
#define OID_802_11_ENCRYPTION_STATUS ccpu2(0x0d01011b)
#define OID_802_11_ADD_KEY ccpu2(0x0d01011d)
#define OID_802_11_REMOVE_KEY ccpu2(0x0d01011e)
+#define OID_802_11_ASSOCIATION_INFORMATION ccpu2(0x0d01011f)
#define OID_802_11_PMKID ccpu2(0x0d010123)
#define OID_802_11_NETWORK_TYPES_SUPPORTED ccpu2(0x0d010203)
#define OID_802_11_NETWORK_TYPE_IN_USE ccpu2(0x0d010204)
@@ -271,6 +272,26 @@ struct ndis_config_param {
__le32 value_length;
} __attribute__((packed));
+struct ndis_80211_assoc_info {
+ __le32 length;
+ __le16 req_ies;
+ struct req_ie {
+ __le16 capa;
+ __le16 listen_interval;
+ u8 cur_ap_address[6];
+ } req_ie;
+ __le32 req_ie_length;
+ __le32 offset_req_ies;
+ __le16 resp_ies;
+ struct resp_ie {
+ __le16 capa;
+ __le16 status_code;
+ __le16 assoc_id;
+ } resp_ie;
+ __le32 resp_ie_length;
+ __le32 offset_resp_ies;
+} __attribute__((packed));
+
/* these have to match what is in wpa_supplicant */
enum wpa_alg { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP };
enum wpa_cipher { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP,
@@ -674,6 +695,12 @@ static int get_bssid(struct usbnet *usbdev, u8 bssid[ETH_ALEN])
return ret;
}
+static int get_association_info(struct usbnet *usbdev,
+ struct ndis_80211_assoc_info *info, int len)
+{
+ return rndis_query_oid(usbdev, OID_802_11_ASSOCIATION_INFORMATION,
+ info, &len);
+}
static int is_associated(struct usbnet *usbdev)
{
@@ -2182,11 +2209,40 @@ static void rndis_wext_worker(struct work_struct *work)
struct usbnet *usbdev = priv->usbdev;
union iwreq_data evt;
unsigned char bssid[ETH_ALEN];
- int ret;
+ struct ndis_80211_assoc_info *info;
+ int assoc_size = sizeof(*info) + IW_CUSTOM_MAX + 32;
+ int ret, offset;
if (test_and_clear_bit(WORK_CONNECTION_EVENT, &priv->work_pending)) {
- ret = get_bssid(usbdev, bssid);
+ info = kzalloc(assoc_size, GFP_KERNEL);
+ if (!info)
+ goto get_bssid;
+
+ /* Get association info IEs from device and send them back to
+ * userspace. */
+ ret = get_association_info(usbdev, info, assoc_size);
+ if (!ret) {
+ evt.data.length = le32_to_cpu(info->req_ie_length);
+ if (evt.data.length > 0) {
+ offset = le32_to_cpu(info->offset_req_ies);
+ wireless_send_event(usbdev->net,
+ IWEVASSOCREQIE, &evt,
+ (char *)info + offset);
+ }
+
+ evt.data.length = le32_to_cpu(info->resp_ie_length);
+ if (evt.data.length > 0) {
+ offset = le32_to_cpu(info->offset_resp_ies);
+ wireless_send_event(usbdev->net,
+ IWEVASSOCRESPIE, &evt,
+ (char *)info + offset);
+ }
+ }
+
+ kfree(info);
+get_bssid:
+ ret = get_bssid(usbdev, bssid);
if (!ret) {
evt.data.flags = 0;
evt.data.length = 0;
@@ -2414,6 +2470,11 @@ static int bcm4320_early_init(struct usbnet *dev)
else if (priv->param_power_save > 2)
priv->param_power_save = 2;
+ if (priv->param_power_output < 0)
+ priv->param_power_output = 0;
+ else if (priv->param_power_output > 3)
+ priv->param_power_output = 3;
+
if (priv->param_roamtrigger < -80)
priv->param_roamtrigger = -80;
else if (priv->param_roamtrigger > -60)
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 57bdc153952f..611d98320593 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -328,6 +328,11 @@ static inline int rt2x00_get_link_ant_rssi(struct link *link)
return DEFAULT_RSSI;
}
+static inline void rt2x00_reset_link_ant_rssi(struct link *link)
+{
+ link->ant.rssi_ant = 0;
+}
+
static inline int rt2x00_get_link_ant_rssi_history(struct link *link,
enum antenna ant)
{
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index a9930a03f450..48608e8cc8b4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -129,6 +129,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
*/
rt2x00dev->ops->lib->config(rt2x00dev, &libconf, CONFIG_UPDATE_ANTENNA);
rt2x00lib_reset_link_tuner(rt2x00dev);
+ rt2x00_reset_link_ant_rssi(&rt2x00dev->link);
rt2x00dev->link.ant.active.rx = libconf.ant.rx;
rt2x00dev->link.ant.active.tx = libconf.ant.tx;
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index b22c02737185..2673d568bcac 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -483,9 +483,9 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
return;
- ieee80211_iterate_active_interfaces(rt2x00dev->hw,
- rt2x00lib_beacondone_iter,
- rt2x00dev);
+ ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
+ rt2x00lib_beacondone_iter,
+ rt2x00dev);
queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work);
}
@@ -507,7 +507,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
* Update TX statistics.
*/
rt2x00dev->link.qual.tx_success += success;
- rt2x00dev->link.qual.tx_failed += txdesc->retry + fail;
+ rt2x00dev->link.qual.tx_failed += fail;
/*
* Initialize TX status
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index c206b5092070..87e280a21971 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -93,6 +93,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
*/
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) {
ieee80211_stop_queues(hw);
+ dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
diff --git a/drivers/net/wireless/rtl8180_grf5101.c b/drivers/net/wireless/rtl8180_grf5101.c
index 5d47935dbac3..947ee55f18b2 100644
--- a/drivers/net/wireless/rtl8180_grf5101.c
+++ b/drivers/net/wireless/rtl8180_grf5101.c
@@ -88,7 +88,7 @@ static void grf5101_rf_set_channel(struct ieee80211_hw *dev,
write_grf5101(dev, 0x0B, chan);
write_grf5101(dev, 0x07, 0x1000);
- grf5101_write_phy_antenna(dev, chan);
+ grf5101_write_phy_antenna(dev, channel);
}
static void grf5101_rf_stop(struct ieee80211_hw *dev)
diff --git a/drivers/net/wireless/rtl8180_max2820.c b/drivers/net/wireless/rtl8180_max2820.c
index a34dfd382b6d..6c825fd7f3b6 100644
--- a/drivers/net/wireless/rtl8180_max2820.c
+++ b/drivers/net/wireless/rtl8180_max2820.c
@@ -78,7 +78,8 @@ static void max2820_rf_set_channel(struct ieee80211_hw *dev,
struct ieee80211_conf *conf)
{
struct rtl8180_priv *priv = dev->priv;
- int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
+ int channel = conf ?
+ ieee80211_frequency_to_channel(conf->channel->center_freq) : 1;
unsigned int chan_idx = channel - 1;
u32 txpw = priv->channels[chan_idx].hw_value & 0xFF;
u32 chan = max2820_chan[chan_idx];
@@ -87,7 +88,7 @@ static void max2820_rf_set_channel(struct ieee80211_hw *dev,
* sa2400, for MAXIM we do this directly from BB */
rtl8180_write_phy(dev, 3, txpw);
- max2820_write_phy_antenna(dev, chan);
+ max2820_write_phy_antenna(dev, channel);
write_max2820(dev, 3, chan);
}
diff --git a/drivers/net/wireless/rtl8180_sa2400.c b/drivers/net/wireless/rtl8180_sa2400.c
index 0311b4ea124c..cea4e0ccb92d 100644
--- a/drivers/net/wireless/rtl8180_sa2400.c
+++ b/drivers/net/wireless/rtl8180_sa2400.c
@@ -86,7 +86,7 @@ static void sa2400_rf_set_channel(struct ieee80211_hw *dev,
write_sa2400(dev, 7, txpw);
- sa2400_write_phy_antenna(dev, chan);
+ sa2400_write_phy_antenna(dev, channel);
write_sa2400(dev, 0, chan);
write_sa2400(dev, 1, 0xbb50);
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 8bddff150c70..d26f69b0184f 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -946,8 +946,7 @@ err:
work_done++;
}
- while ((skb = __skb_dequeue(&errq)))
- kfree_skb(skb);
+ __skb_queue_purge(&errq);
work_done -= handle_incoming_queue(dev, &rxq);
@@ -1079,8 +1078,7 @@ static void xennet_release_rx_bufs(struct netfront_info *np)
}
}
- while ((skb = __skb_dequeue(&free_list)) != NULL)
- dev_kfree_skb(skb);
+ __skb_queue_purge(&free_list);
spin_unlock_bh(&np->rx_lock);
}
diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c
index 715a44471617..b2ccdcbeb896 100644
--- a/drivers/of/of_i2c.c
+++ b/drivers/of/of_i2c.c
@@ -21,7 +21,6 @@ struct i2c_driver_device {
};
static struct i2c_driver_device i2c_devices[] = {
- { "dallas,ds1374", "rtc-ds1374" },
};
static int of_find_i2c_driver(struct device_node *node,
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index 925ba16355ce..a11021e8ce37 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -619,6 +619,7 @@ static struct hotplug_slot *get_slot_from_name (const char *name)
int pci_hp_register (struct hotplug_slot *slot)
{
int result;
+ struct hotplug_slot *tmp;
if (slot == NULL)
return -ENODEV;
@@ -630,7 +631,11 @@ int pci_hp_register (struct hotplug_slot *slot)
return -EINVAL;
}
- /* this can fail if we have already registered a slot with the same name */
+ /* Check if we have already registered a slot with the same name. */
+ tmp = get_slot_from_name(slot->name);
+ if (tmp)
+ return -EEXIST;
+
slot->kobj.kset = pci_hotplug_slots_kset;
result = kobject_init_and_add(&slot->kobj, &hotplug_slot_ktype, NULL,
"%s", slot->name);
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 8264a7680435..79c9ddaad3fb 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -97,6 +97,7 @@ struct controller {
u8 cap_base;
struct timer_list poll_timer;
volatile int cmd_busy;
+ unsigned int no_cmd_complete:1;
};
#define INT_BUTTON_IGNORE 0
@@ -135,6 +136,7 @@ struct controller {
#define PWR_LED_PRSN 0x00000010
#define HP_SUPR_RM_SUP 0x00000020
#define EMI_PRSN 0x00020000
+#define NO_CMD_CMPL_SUP 0x00040000
#define ATTN_BUTTN(ctrl) ((ctrl)->slot_cap & ATTN_BUTTN_PRSN)
#define POWER_CTRL(ctrl) ((ctrl)->slot_cap & PWR_CTRL_PRSN)
@@ -143,13 +145,14 @@ struct controller {
#define PWR_LED(ctrl) ((ctrl)->slot_cap & PWR_LED_PRSN)
#define HP_SUPR_RM(ctrl) ((ctrl)->slot_cap & HP_SUPR_RM_SUP)
#define EMI(ctrl) ((ctrl)->slot_cap & EMI_PRSN)
+#define NO_CMD_CMPL(ctrl) ((ctrl)->slot_cap & NO_CMD_CMPL_SUP)
extern int pciehp_sysfs_enable_slot(struct slot *slot);
extern int pciehp_sysfs_disable_slot(struct slot *slot);
-extern u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl);
-extern u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl);
-extern u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl);
-extern u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl);
+extern u8 pciehp_handle_attention_button(struct slot *p_slot);
+ extern u8 pciehp_handle_switch_change(struct slot *p_slot);
+extern u8 pciehp_handle_presence_change(struct slot *p_slot);
+extern u8 pciehp_handle_power_fault(struct slot *p_slot);
extern int pciehp_configure_device(struct slot *p_slot);
extern int pciehp_unconfigure_device(struct slot *p_slot);
extern void pciehp_queue_pushbutton_work(struct work_struct *work);
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 43d8ddb2d679..48a2ed378914 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -254,7 +254,11 @@ static int init_slots(struct controller *ctrl)
slot->hp_slot, slot->number, ctrl->slot_device_offset);
retval = pci_hp_register(hotplug_slot);
if (retval) {
- err ("pci_hp_register failed with error %d\n", retval);
+ err("pci_hp_register failed with error %d\n", retval);
+ if (retval == -EEXIST)
+ err("Failed to register slot because of name "
+ "collision. Try \'pciehp_slot_with_bus\' "
+ "module option.\n");
goto error_info;
}
/* create additional sysfs entries */
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 0a7aa628e955..96a5d55a4983 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -55,16 +55,13 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
return 0;
}
-u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl)
+u8 pciehp_handle_attention_button(struct slot *p_slot)
{
- struct slot *p_slot;
u32 event_type;
/* Attention Button Change */
dbg("pciehp: Attention button interrupt received.\n");
- p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
-
/*
* Button pressed - See if need to TAKE ACTION!!!
*/
@@ -76,18 +73,15 @@ u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl)
return 0;
}
-u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl)
+u8 pciehp_handle_switch_change(struct slot *p_slot)
{
- struct slot *p_slot;
u8 getstatus;
u32 event_type;
/* Switch Change */
dbg("pciehp: Switch interrupt received.\n");
- p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
-
if (getstatus) {
/*
* Switch opened
@@ -107,17 +101,14 @@ u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl)
return 1;
}
-u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl)
+u8 pciehp_handle_presence_change(struct slot *p_slot)
{
- struct slot *p_slot;
u32 event_type;
u8 presence_save;
/* Presence Change */
dbg("pciehp: Presence/Notify input change.\n");
- p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
-
/* Switch is open, assume a presence change
* Save the presence state
*/
@@ -141,16 +132,13 @@ u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl)
return 1;
}
-u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl)
+u8 pciehp_handle_power_fault(struct slot *p_slot)
{
- struct slot *p_slot;
u32 event_type;
/* power fault */
dbg("pciehp: Power fault interrupt received.\n");
- p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
-
if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) {
/*
* power fault Cleared
@@ -163,7 +151,7 @@ u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl)
*/
info("Power fault on Slot(%s)\n", p_slot->name);
event_type = INT_POWER_FAULT;
- info("power fault bit %x set\n", hp_slot);
+ info("power fault bit %x set\n", 0);
}
queue_interrupt_event(p_slot, event_type);
@@ -186,6 +174,13 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
}
}
+ /*
+ * After turning power off, we must wait for at least 1 second
+ * before taking any action that relies on power having been
+ * removed from the slot/adapter.
+ */
+ msleep(1000);
+
if (PWR_LED(ctrl))
pslot->hpc_ops->green_led_off(pslot);
@@ -289,6 +284,13 @@ static int remove_board(struct slot *p_slot)
}
}
+ /*
+ * After turning power off, we must wait for at least 1 second
+ * before taking any action that relies on power having been
+ * removed from the slot/adapter.
+ */
+ msleep(1000);
+
if (PWR_LED(ctrl))
/* turn off Green LED */
p_slot->hpc_ops->green_led_off(p_slot);
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 891f81a0400c..79f104963166 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -247,14 +247,38 @@ static inline void pciehp_free_irq(struct controller *ctrl)
free_irq(ctrl->pci_dev->irq, ctrl);
}
-static inline int pcie_wait_cmd(struct controller *ctrl)
+static inline int pcie_poll_cmd(struct controller *ctrl)
+{
+ u16 slot_status;
+ int timeout = 1000;
+
+ if (!pciehp_readw(ctrl, SLOTSTATUS, &slot_status))
+ if (slot_status & CMD_COMPLETED)
+ goto completed;
+ for (timeout = 1000; timeout > 0; timeout -= 100) {
+ msleep(100);
+ if (!pciehp_readw(ctrl, SLOTSTATUS, &slot_status))
+ if (slot_status & CMD_COMPLETED)
+ goto completed;
+ }
+ return 0; /* timeout */
+
+completed:
+ pciehp_writew(ctrl, SLOTSTATUS, CMD_COMPLETED);
+ return timeout;
+}
+
+static inline int pcie_wait_cmd(struct controller *ctrl, int poll)
{
int retval = 0;
unsigned int msecs = pciehp_poll_mode ? 2500 : 1000;
unsigned long timeout = msecs_to_jiffies(msecs);
int rc;
- rc = wait_event_interruptible_timeout(ctrl->queue,
+ if (poll)
+ rc = pcie_poll_cmd(ctrl);
+ else
+ rc = wait_event_interruptible_timeout(ctrl->queue,
!ctrl->cmd_busy, timeout);
if (!rc)
dbg("Command not completed in 1000 msec\n");
@@ -286,12 +310,28 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
goto out;
}
- if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) {
- /* After 1 sec and CMD_COMPLETED still not set, just
- proceed forward to issue the next command according
- to spec. Just print out the error message */
- dbg("%s: CMD_COMPLETED not clear after 1 sec.\n",
- __func__);
+ if (slot_status & CMD_COMPLETED) {
+ if (!ctrl->no_cmd_complete) {
+ /*
+ * After 1 sec and CMD_COMPLETED still not set, just
+ * proceed forward to issue the next command according
+ * to spec. Just print out the error message.
+ */
+ dbg("%s: CMD_COMPLETED not clear after 1 sec.\n",
+ __func__);
+ } else if (!NO_CMD_CMPL(ctrl)) {
+ /*
+ * This controller semms to notify of command completed
+ * event even though it supports none of power
+ * controller, attention led, power led and EMI.
+ */
+ dbg("%s: Unexpected CMD_COMPLETED. Need to wait for "
+ "command completed event.\n", __func__);
+ ctrl->no_cmd_complete = 0;
+ } else {
+ dbg("%s: Unexpected CMD_COMPLETED. Maybe the "
+ "controller is broken.\n", __func__);
+ }
}
retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
@@ -315,8 +355,18 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
/*
* Wait for command completion.
*/
- if (!retval)
- retval = pcie_wait_cmd(ctrl);
+ if (!retval && !ctrl->no_cmd_complete) {
+ int poll = 0;
+ /*
+ * if hotplug interrupt is not enabled or command
+ * completed interrupt is not enabled, we need to poll
+ * command completed event.
+ */
+ if (!(slot_ctrl & HP_INTR_ENABLE) ||
+ !(slot_ctrl & CMD_CMPL_INTR_ENABLE))
+ poll = 1;
+ retval = pcie_wait_cmd(ctrl, poll);
+ }
out:
mutex_unlock(&ctrl->ctrl_lock);
return retval;
@@ -704,13 +754,6 @@ static int hpc_power_off_slot(struct slot * slot)
}
dbg("%s: SLOTCTRL %x write cmd %x\n",
__func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
-
- /*
- * After turning power off, we must wait for at least 1 second
- * before taking any action that relies on power having been
- * removed from the slot/adapter.
- */
- msleep(1000);
out:
if (changed)
pcie_unmask_bad_dllp(ctrl);
@@ -722,6 +765,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
{
struct controller *ctrl = (struct controller *)dev_id;
u16 detected, intr_loc;
+ struct slot *p_slot;
/*
* In order to guarantee that all interrupt events are
@@ -756,21 +800,38 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
wake_up_interruptible(&ctrl->queue);
}
+ if (!(intr_loc & ~CMD_COMPLETED))
+ return IRQ_HANDLED;
+
+ /*
+ * Return without handling events if this handler routine is
+ * called before controller initialization is done. This may
+ * happen if hotplug event or another interrupt that shares
+ * the IRQ with pciehp arrives before slot initialization is
+ * done after interrupt handler is registered.
+ *
+ * FIXME - Need more structural fixes. We need to be ready to
+ * handle the event before installing interrupt handler.
+ */
+ p_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
+ if (!p_slot || !p_slot->hpc_ops)
+ return IRQ_HANDLED;
+
/* Check MRL Sensor Changed */
if (intr_loc & MRL_SENS_CHANGED)
- pciehp_handle_switch_change(0, ctrl);
+ pciehp_handle_switch_change(p_slot);
/* Check Attention Button Pressed */
if (intr_loc & ATTN_BUTTN_PRESSED)
- pciehp_handle_attention_button(0, ctrl);
+ pciehp_handle_attention_button(p_slot);
/* Check Presence Detect Changed */
if (intr_loc & PRSN_DETECT_CHANGED)
- pciehp_handle_presence_change(0, ctrl);
+ pciehp_handle_presence_change(p_slot);
/* Check Power Fault Detected */
if (intr_loc & PWR_FAULT_DETECTED)
- pciehp_handle_power_fault(0, ctrl);
+ pciehp_handle_power_fault(p_slot);
return IRQ_HANDLED;
}
@@ -1028,6 +1089,12 @@ static int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
static int pcie_init_hardware_part1(struct controller *ctrl,
struct pcie_device *dev)
{
+ /* Clear all remaining event bits in Slot Status register */
+ if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) {
+ err("%s: Cannot write to SLOTSTATUS register\n", __func__);
+ return -1;
+ }
+
/* Mask Hot-plug Interrupt Enable */
if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE)) {
err("%s: Cannot mask hotplug interrupt enable\n", __func__);
@@ -1040,16 +1107,6 @@ int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
{
u16 cmd, mask;
- /*
- * We need to clear all events before enabling hotplug interrupt
- * notification mechanism in order for hotplug controler to
- * generate interrupts.
- */
- if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) {
- err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
- return -1;
- }
-
cmd = PRSN_DETECT_ENABLE;
if (ATTN_BUTTN(ctrl))
cmd |= ATTN_BUTTN_ENABLE;
@@ -1116,6 +1173,7 @@ static inline void dbg_ctrl(struct controller *ctrl)
dbg(" Power Indicator : %3s\n", PWR_LED(ctrl) ? "yes" : "no");
dbg(" Hot-Plug Surprise : %3s\n", HP_SUPR_RM(ctrl) ? "yes" : "no");
dbg(" EMI Present : %3s\n", EMI(ctrl) ? "yes" : "no");
+ dbg(" Comamnd Completed : %3s\n", NO_CMD_CMPL(ctrl)? "no" : "yes");
pciehp_readw(ctrl, SLOTSTATUS, &reg16);
dbg("Slot Status : 0x%04x\n", reg16);
pciehp_readw(ctrl, SLOTSTATUS, &reg16);
@@ -1147,6 +1205,15 @@ int pcie_init(struct controller *ctrl, struct pcie_device *dev)
mutex_init(&ctrl->ctrl_lock);
init_waitqueue_head(&ctrl->queue);
dbg_ctrl(ctrl);
+ /*
+ * Controller doesn't notify of command completion if the "No
+ * Command Completed Support" bit is set in Slot Capability
+ * register or the controller supports none of power
+ * controller, attention led, power led and EMI.
+ */
+ if (NO_CMD_CMPL(ctrl) ||
+ !(POWER_CTRL(ctrl) | ATTN_LED(ctrl) | PWR_LED(ctrl) | EMI(ctrl)))
+ ctrl->no_cmd_complete = 1;
info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
pdev->vendor, pdev->device,
diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c
index e32148a8fa12..779c5db71be4 100644
--- a/drivers/pci/hotplug/rpadlpar_sysfs.c
+++ b/drivers/pci/hotplug/rpadlpar_sysfs.c
@@ -18,8 +18,12 @@
#include "rpadlpar.h"
#define DLPAR_KOBJ_NAME "control"
-#define ADD_SLOT_ATTR_NAME "add_slot"
-#define REMOVE_SLOT_ATTR_NAME "remove_slot"
+
+/* Those two have no quotes because they are passed to __ATTR() which
+ * stringifies the argument (yuck !)
+ */
+#define ADD_SLOT_ATTR_NAME add_slot
+#define REMOVE_SLOT_ATTR_NAME remove_slot
#define MAX_DRC_NAME_LEN 64
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index 1648076600fc..97848654652a 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -162,6 +162,10 @@ static int init_slots(struct controller *ctrl)
retval = pci_hp_register(slot->hotplug_slot);
if (retval) {
err("pci_hp_register failed with error %d\n", retval);
+ if (retval == -EEXIST)
+ err("Failed to register slot because of name "
+ "collision. Try \'shpchp_slot_with_bus\' "
+ "module option.\n");
goto error_info;
}
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 61fedb2448b6..f82495583e63 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -506,6 +506,23 @@ static void free_link_state(struct pci_dev *pdev)
pdev->link_state = NULL;
}
+static int pcie_aspm_sanity_check(struct pci_dev *pdev)
+{
+ struct pci_dev *child_dev;
+ int child_pos;
+
+ /*
+ * Some functions in a slot might not all be PCIE functions, very
+ * strange. Disable ASPM for the whole slot
+ */
+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+ child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+ if (!child_pos)
+ return -EINVAL;
+ }
+ return 0;
+}
+
/*
* pcie_aspm_init_link_state: Initiate PCI express link state.
* It is called after the pcie and its children devices are scaned.
@@ -526,6 +543,9 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
if (list_empty(&pdev->subordinate->devices))
goto out;
+ if (pcie_aspm_sanity_check(pdev))
+ goto out;
+
mutex_lock(&aspm_lock);
link_state = kzalloc(sizeof(*link_state), GFP_KERNEL);
diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c
index 0a6cea1316b4..52d0aa8c2e7a 100644
--- a/drivers/pcmcia/electra_cf.c
+++ b/drivers/pcmcia/electra_cf.c
@@ -352,6 +352,7 @@ static struct of_device_id electra_cf_match[] = {
},
{},
};
+MODULE_DEVICE_TABLE(of, electra_cf_match);
static struct of_platform_driver electra_cf_driver = {
.name = (char *)driver_name,
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index e2b7de4cb05e..1ff3bb585ab2 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -286,7 +286,7 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
pci_name(pdev), i,
(unsigned long long) pci_start,
(unsigned long long) pci_end);
- res->flags = 0;
+ res->flags |= IORESOURCE_DISABLED;
}
}
}
diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c
index 9c2496dbeee4..cf4e07b01d48 100644
--- a/drivers/pnp/system.c
+++ b/drivers/pnp/system.c
@@ -81,7 +81,7 @@ static void reserve_resources_of_dev(struct pnp_dev *dev)
}
for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
- if (res->flags & IORESOURCE_UNSET)
+ if (res->flags & (IORESOURCE_UNSET | IORESOURCE_DISABLED))
continue;
reserve_range(dev, res->start, res->end, 0);
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 6cc2c0330230..60f8afc7a56e 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -534,4 +534,12 @@ config RTC_DRV_RS5C313
help
If you say yes here you get support for the Ricoh RS5C313 RTC chips.
+config RTC_DRV_PPC
+ tristate "PowerPC machine dependent RTC support"
+ depends on PPC_MERGE
+ help
+ The PowerPC kernel has machine-specific functions for accessing
+ the RTC. This exposes that functionality through the generic RTC
+ class.
+
endif # RTC_CLASS
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 872f1218ff9f..ebe871cf16c1 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -54,3 +54,4 @@ obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o
obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o
obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
+obj-$(CONFIG_RTC_DRV_PPC) += rtc-ppc.o
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
index fa2d2f8b3f4d..640acd20fdde 100644
--- a/drivers/rtc/rtc-ds1374.c
+++ b/drivers/rtc/rtc-ds1374.c
@@ -42,7 +42,7 @@
#define DS1374_REG_TCR 0x09 /* Trickle Charge */
static const struct i2c_device_id ds1374_id[] = {
- { "rtc-ds1374", 0 },
+ { "ds1374", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ds1374_id);
diff --git a/drivers/rtc/rtc-ppc.c b/drivers/rtc/rtc-ppc.c
new file mode 100644
index 000000000000..c8e97e25ef7e
--- /dev/null
+++ b/drivers/rtc/rtc-ppc.c
@@ -0,0 +1,69 @@
+/*
+ * RTC driver for ppc_md RTC functions
+ *
+ * © 2007 Red Hat, Inc.
+ *
+ * Author: David Woodhouse <dwmw2@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <asm/machdep.h>
+
+static int ppc_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ ppc_md.get_rtc_time(tm);
+ return 0;
+}
+
+static int ppc_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ return ppc_md.set_rtc_time(tm);
+}
+
+static const struct rtc_class_ops ppc_rtc_ops = {
+ .set_time = ppc_rtc_set_time,
+ .read_time = ppc_rtc_read_time,
+};
+
+static struct rtc_device *rtc;
+static struct platform_device *ppc_rtc_pdev;
+
+static int __init ppc_rtc_init(void)
+{
+ if (!ppc_md.get_rtc_time || !ppc_md.set_rtc_time)
+ return -ENODEV;
+
+ ppc_rtc_pdev = platform_device_register_simple("ppc-rtc", 0, NULL, 0);
+ if (IS_ERR(ppc_rtc_pdev))
+ return PTR_ERR(ppc_rtc_pdev);
+
+ rtc = rtc_device_register("ppc_md", &ppc_rtc_pdev->dev,
+ &ppc_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc)) {
+ platform_device_unregister(ppc_rtc_pdev);
+ return PTR_ERR(rtc);
+ }
+
+ return 0;
+}
+
+static void __exit ppc_rtc_exit(void)
+{
+ rtc_device_unregister(rtc);
+ platform_device_unregister(ppc_rtc_pdev);
+}
+
+module_init(ppc_rtc_init);
+module_exit(ppc_rtc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
+MODULE_DESCRIPTION("Generic RTC class driver for PowerPC");
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 8ba3f135da22..1a4025683362 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -63,6 +63,7 @@ static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *);
*/
static wait_queue_head_t dasd_init_waitq;
static wait_queue_head_t dasd_flush_wq;
+static wait_queue_head_t generic_waitq;
/*
* Allocate memory for a new device structure.
@@ -1151,11 +1152,15 @@ static void __dasd_device_process_final_queue(struct dasd_device *device,
struct list_head *l, *n;
struct dasd_ccw_req *cqr;
struct dasd_block *block;
+ void (*callback)(struct dasd_ccw_req *, void *data);
+ void *callback_data;
list_for_each_safe(l, n, final_queue) {
cqr = list_entry(l, struct dasd_ccw_req, devlist);
list_del_init(&cqr->devlist);
block = cqr->block;
+ callback = cqr->callback;
+ callback_data = cqr->callback_data;
if (block)
spin_lock_bh(&block->queue_lock);
switch (cqr->status) {
@@ -1176,7 +1181,7 @@ static void __dasd_device_process_final_queue(struct dasd_device *device,
BUG();
}
if (cqr->callback != NULL)
- (cqr->callback)(cqr, cqr->callback_data);
+ (callback)(cqr, callback_data);
if (block)
spin_unlock_bh(&block->queue_lock);
}
@@ -1406,17 +1411,15 @@ static inline int _wait_for_wakeup(struct dasd_ccw_req *cqr)
*/
int dasd_sleep_on(struct dasd_ccw_req *cqr)
{
- wait_queue_head_t wait_q;
struct dasd_device *device;
int rc;
device = cqr->startdev;
- init_waitqueue_head (&wait_q);
cqr->callback = dasd_wakeup_cb;
- cqr->callback_data = (void *) &wait_q;
+ cqr->callback_data = (void *) &generic_waitq;
dasd_add_request_tail(cqr);
- wait_event(wait_q, _wait_for_wakeup(cqr));
+ wait_event(generic_waitq, _wait_for_wakeup(cqr));
/* Request status is either done or failed. */
rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO;
@@ -1429,20 +1432,18 @@ int dasd_sleep_on(struct dasd_ccw_req *cqr)
*/
int dasd_sleep_on_interruptible(struct dasd_ccw_req *cqr)
{
- wait_queue_head_t wait_q;
struct dasd_device *device;
int rc;
device = cqr->startdev;
- init_waitqueue_head (&wait_q);
cqr->callback = dasd_wakeup_cb;
- cqr->callback_data = (void *) &wait_q;
+ cqr->callback_data = (void *) &generic_waitq;
dasd_add_request_tail(cqr);
- rc = wait_event_interruptible(wait_q, _wait_for_wakeup(cqr));
+ rc = wait_event_interruptible(generic_waitq, _wait_for_wakeup(cqr));
if (rc == -ERESTARTSYS) {
dasd_cancel_req(cqr);
/* wait (non-interruptible) for final status */
- wait_event(wait_q, _wait_for_wakeup(cqr));
+ wait_event(generic_waitq, _wait_for_wakeup(cqr));
}
rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO;
return rc;
@@ -1466,7 +1467,6 @@ static inline int _dasd_term_running_cqr(struct dasd_device *device)
int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr)
{
- wait_queue_head_t wait_q;
struct dasd_device *device;
int rc;
@@ -1478,9 +1478,8 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr)
return rc;
}
- init_waitqueue_head (&wait_q);
cqr->callback = dasd_wakeup_cb;
- cqr->callback_data = (void *) &wait_q;
+ cqr->callback_data = (void *) &generic_waitq;
cqr->status = DASD_CQR_QUEUED;
list_add(&cqr->devlist, &device->ccw_queue);
@@ -1489,7 +1488,7 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr)
spin_unlock_irq(get_ccwdev_lock(device->cdev));
- wait_event(wait_q, _wait_for_wakeup(cqr));
+ wait_event(generic_waitq, _wait_for_wakeup(cqr));
/* Request status is either done or failed. */
rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO;
@@ -2430,6 +2429,7 @@ static int __init dasd_init(void)
init_waitqueue_head(&dasd_init_waitq);
init_waitqueue_head(&dasd_flush_wq);
+ init_waitqueue_head(&generic_waitq);
/* register 'common' DASD debug area, used for all DBF_XXX calls */
dasd_debug_area = debug_register("dasd", 1, 1, 8 * sizeof(long));
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 0d98f1ff2edd..848ef7e8523f 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -549,7 +549,6 @@ raw3270_start_init(struct raw3270 *rp, struct raw3270_view *view,
struct raw3270_request *rq)
{
unsigned long flags;
- wait_queue_head_t wq;
int rc;
#ifdef CONFIG_TN3270_CONSOLE
@@ -566,20 +565,20 @@ raw3270_start_init(struct raw3270 *rp, struct raw3270_view *view,
return rq->rc;
}
#endif
- init_waitqueue_head(&wq);
rq->callback = raw3270_wake_init;
- rq->callback_data = &wq;
+ rq->callback_data = &raw3270_wait_queue;
spin_lock_irqsave(get_ccwdev_lock(view->dev->cdev), flags);
rc = __raw3270_start(rp, view, rq);
spin_unlock_irqrestore(get_ccwdev_lock(view->dev->cdev), flags);
if (rc)
return rc;
/* Now wait for the completion. */
- rc = wait_event_interruptible(wq, raw3270_request_final(rq));
+ rc = wait_event_interruptible(raw3270_wait_queue,
+ raw3270_request_final(rq));
if (rc == -ERESTARTSYS) { /* Interrupted by a signal. */
raw3270_halt_io(view->dev, rq);
/* No wait for the halt to complete. */
- wait_event(wq, raw3270_request_final(rq));
+ wait_event(raw3270_wait_queue, raw3270_request_final(rq));
return -ERESTARTSYS;
}
return rq->rc;
diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c
index 9e784d5f7f57..ad05a87bc480 100644
--- a/drivers/s390/char/sclp_config.c
+++ b/drivers/s390/char/sclp_config.c
@@ -40,7 +40,7 @@ static void sclp_cpu_capability_notify(struct work_struct *work)
put_online_cpus();
}
-static void sclp_cpu_change_notify(struct work_struct *work)
+static void __ref sclp_cpu_change_notify(struct work_struct *work)
{
smp_rescan_cpus();
}
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index 35707c04e613..62576af36f47 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -71,9 +71,6 @@ static struct list_head sclp_vt220_outqueue;
/* Number of requests in outqueue */
static int sclp_vt220_outqueue_count;
-/* Wait queue used to delay write requests while we've run out of buffers */
-static wait_queue_head_t sclp_vt220_waitq;
-
/* Timer used for delaying write requests to merge subsequent messages into
* a single buffer */
static struct timer_list sclp_vt220_timer;
@@ -133,7 +130,6 @@ sclp_vt220_process_queue(struct sclp_vt220_request *request)
} while (request && __sclp_vt220_emit(request));
if (request == NULL && sclp_vt220_flush_later)
sclp_vt220_emit_current();
- wake_up(&sclp_vt220_waitq);
/* Check if the tty needs a wake up call */
if (sclp_vt220_tty != NULL) {
tty_wakeup(sclp_vt220_tty);
@@ -383,7 +379,7 @@ sclp_vt220_timeout(unsigned long data)
*/
static int
__sclp_vt220_write(const unsigned char *buf, int count, int do_schedule,
- int convertlf, int may_schedule)
+ int convertlf, int may_fail)
{
unsigned long flags;
void *page;
@@ -395,15 +391,14 @@ __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule,
overall_written = 0;
spin_lock_irqsave(&sclp_vt220_lock, flags);
do {
- /* Create a sclp output buffer if none exists yet */
+ /* Create an sclp output buffer if none exists yet */
if (sclp_vt220_current_request == NULL) {
while (list_empty(&sclp_vt220_empty)) {
spin_unlock_irqrestore(&sclp_vt220_lock, flags);
- if (in_interrupt() || !may_schedule)
- sclp_sync_wait();
+ if (may_fail)
+ goto out;
else
- wait_event(sclp_vt220_waitq,
- !list_empty(&sclp_vt220_empty));
+ sclp_sync_wait();
spin_lock_irqsave(&sclp_vt220_lock, flags);
}
page = (void *) sclp_vt220_empty.next;
@@ -437,6 +432,7 @@ __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule,
add_timer(&sclp_vt220_timer);
}
spin_unlock_irqrestore(&sclp_vt220_lock, flags);
+out:
return overall_written;
}
@@ -520,19 +516,11 @@ sclp_vt220_close(struct tty_struct *tty, struct file *filp)
* character to the tty device. If the kernel uses this routine,
* it must call the flush_chars() routine (if defined) when it is
* done stuffing characters into the driver.
- *
- * NOTE: include/linux/tty_driver.h specifies that a character should be
- * ignored if there is no room in the queue. This driver implements a different
- * semantic in that it will block when there is no more room left.
- *
- * FIXME: putchar can currently be called from BH and other non blocking
- * handlers so this semantic isn't a good idea.
*/
static int
sclp_vt220_put_char(struct tty_struct *tty, unsigned char ch)
{
- __sclp_vt220_write(&ch, 1, 0, 0, 1);
- return 1;
+ return __sclp_vt220_write(&ch, 1, 0, 0, 1);
}
/*
@@ -653,7 +641,6 @@ static int __init __sclp_vt220_init(void)
spin_lock_init(&sclp_vt220_lock);
INIT_LIST_HEAD(&sclp_vt220_empty);
INIT_LIST_HEAD(&sclp_vt220_outqueue);
- init_waitqueue_head(&sclp_vt220_waitq);
init_timer(&sclp_vt220_timer);
sclp_vt220_current_request = NULL;
sclp_vt220_buffered_chars = 0;
diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h
index dddf8d62c153..d0d565a05dfe 100644
--- a/drivers/s390/char/tape.h
+++ b/drivers/s390/char/tape.h
@@ -231,6 +231,9 @@ struct tape_device {
/* Request queue. */
struct list_head req_queue;
+ /* Request wait queue. */
+ wait_queue_head_t wait_queue;
+
/* Each tape device has (currently) two minor numbers. */
int first_minor;
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index ddc4a114e7f4..95da72bc17e8 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -179,11 +179,11 @@ tapeblock_requeue(struct work_struct *work) {
tapeblock_end_request(req, -EIO);
continue;
}
+ blkdev_dequeue_request(req);
+ nr_queued++;
spin_unlock_irq(&device->blk_data.request_queue_lock);
rc = tapeblock_start_request(device, req);
spin_lock_irq(&device->blk_data.request_queue_lock);
- blkdev_dequeue_request(req);
- nr_queued++;
}
spin_unlock_irq(&device->blk_data.request_queue_lock);
atomic_set(&device->blk_data.requeue_scheduled, 0);
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 76e44eb7c47f..c20e3c548343 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -449,6 +449,7 @@ tape_alloc_device(void)
INIT_LIST_HEAD(&device->req_queue);
INIT_LIST_HEAD(&device->node);
init_waitqueue_head(&device->state_change_wq);
+ init_waitqueue_head(&device->wait_queue);
device->tape_state = TS_INIT;
device->medium_state = MS_UNKNOWN;
*device->modeset_byte = 0;
@@ -954,21 +955,19 @@ __tape_wake_up(struct tape_request *request, void *data)
int
tape_do_io(struct tape_device *device, struct tape_request *request)
{
- wait_queue_head_t wq;
int rc;
- init_waitqueue_head(&wq);
spin_lock_irq(get_ccwdev_lock(device->cdev));
/* Setup callback */
request->callback = __tape_wake_up;
- request->callback_data = &wq;
+ request->callback_data = &device->wait_queue;
/* Add request to request queue and try to start it. */
rc = __tape_start_request(device, request);
spin_unlock_irq(get_ccwdev_lock(device->cdev));
if (rc)
return rc;
/* Request added to the queue. Wait for its completion. */
- wait_event(wq, (request->callback == NULL));
+ wait_event(device->wait_queue, (request->callback == NULL));
/* Get rc from request */
return request->rc;
}
@@ -989,20 +988,19 @@ int
tape_do_io_interruptible(struct tape_device *device,
struct tape_request *request)
{
- wait_queue_head_t wq;
int rc;
- init_waitqueue_head(&wq);
spin_lock_irq(get_ccwdev_lock(device->cdev));
/* Setup callback */
request->callback = __tape_wake_up_interruptible;
- request->callback_data = &wq;
+ request->callback_data = &device->wait_queue;
rc = __tape_start_request(device, request);
spin_unlock_irq(get_ccwdev_lock(device->cdev));
if (rc)
return rc;
/* Request added to the queue. Wait for its completion. */
- rc = wait_event_interruptible(wq, (request->callback == NULL));
+ rc = wait_event_interruptible(device->wait_queue,
+ (request->callback == NULL));
if (rc != -ERESTARTSYS)
/* Request finished normally. */
return request->rc;
@@ -1015,7 +1013,7 @@ tape_do_io_interruptible(struct tape_device *device,
/* Wait for the interrupt that acknowledges the halt. */
do {
rc = wait_event_interruptible(
- wq,
+ device->wait_queue,
(request->callback == NULL)
);
} while (rc == -ERESTARTSYS);
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c
index 9f55ce6f3c78..5ab34340919b 100644
--- a/drivers/s390/kvm/kvm_virtio.c
+++ b/drivers/s390/kvm/kvm_virtio.c
@@ -31,11 +31,6 @@
*/
static void *kvm_devices;
-/*
- * Unique numbering for kvm devices.
- */
-static unsigned int dev_index;
-
struct kvm_device {
struct virtio_device vdev;
struct kvm_device_desc *desc;
@@ -250,26 +245,25 @@ static struct device kvm_root = {
* adds a new device and register it with virtio
* appropriate drivers are loaded by the device model
*/
-static void add_kvm_device(struct kvm_device_desc *d)
+static void add_kvm_device(struct kvm_device_desc *d, unsigned int offset)
{
struct kvm_device *kdev;
kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
if (!kdev) {
- printk(KERN_EMERG "Cannot allocate kvm dev %u\n",
- dev_index++);
+ printk(KERN_EMERG "Cannot allocate kvm dev %u type %u\n",
+ offset, d->type);
return;
}
kdev->vdev.dev.parent = &kvm_root;
- kdev->vdev.index = dev_index++;
kdev->vdev.id.device = d->type;
kdev->vdev.config = &kvm_vq_configspace_ops;
kdev->desc = d;
if (register_virtio_device(&kdev->vdev) != 0) {
- printk(KERN_ERR "Failed to register kvm device %u\n",
- kdev->vdev.index);
+ printk(KERN_ERR "Failed to register kvm device %u type %u\n",
+ offset, d->type);
kfree(kdev);
}
}
@@ -289,7 +283,7 @@ static void scan_devices(void)
if (d->type == 0)
break;
- add_kvm_device(d);
+ add_kvm_device(d, i);
}
}
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index b31faeccb9cd..867f6fd5c2c0 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -1278,7 +1278,7 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance)
error = 0;
/* Check for command packet errors */
if (full_command_packet->command.newcommand.status != 0) {
- if (tw_dev->srb[request_id] != 0) {
+ if (tw_dev->srb[request_id] != NULL) {
error = twa_fill_sense(tw_dev, request_id, 1, 1);
} else {
/* Skip ioctl error prints */
@@ -1290,7 +1290,7 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance)
/* Check for correct state */
if (tw_dev->state[request_id] != TW_S_POSTED) {
- if (tw_dev->srb[request_id] != 0) {
+ if (tw_dev->srb[request_id] != NULL) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1a, "Received a request id that wasn't posted");
TW_CLEAR_ALL_INTERRUPTS(tw_dev);
goto twa_interrupt_bail;
@@ -1298,7 +1298,7 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance)
}
/* Check for internal command completion */
- if (tw_dev->srb[request_id] == 0) {
+ if (tw_dev->srb[request_id] == NULL) {
if (request_id != tw_dev->chrdev_request_id) {
if (twa_aen_complete(tw_dev, request_id))
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1b, "Error completing AEN during attention interrupt");
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index 1dca1775f4b1..0899cb61e3dd 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -3582,7 +3582,7 @@ static int checksetup(struct aha152x_setup *setup)
if (i == ARRAY_SIZE(ports))
return 0;
- if ( request_region(setup->io_port, IO_RANGE, "aha152x")==0 ) {
+ if (!request_region(setup->io_port, IO_RANGE, "aha152x")) {
printk(KERN_ERR "aha152x: io port 0x%x busy.\n", setup->io_port);
return 0;
}
@@ -3842,7 +3842,7 @@ static int __init aha152x_init(void)
if ((setup_count == 1) && (setup[0].io_port == ports[i]))
continue;
- if ( request_region(ports[i], IO_RANGE, "aha152x")==0 ) {
+ if (!request_region(ports[i], IO_RANGE, "aha152x")) {
printk(KERN_ERR "aha152x: io port 0x%x busy.\n", ports[i]);
continue;
}
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index db6de5e6afb3..7d311541c76c 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -747,7 +747,7 @@ static void send_s870(struct atp_unit *dev,unsigned char c)
dev->quhd[c] = 0;
}
workreq = dev->quereq[c][dev->quhd[c]];
- if (dev->id[c][scmd_id(workreq)].curr_req == 0) {
+ if (dev->id[c][scmd_id(workreq)].curr_req == NULL) {
dev->id[c][scmd_id(workreq)].curr_req = workreq;
dev->last_cmd[c] = scmd_id(workreq);
goto cmd_subp;
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index aaa48e0c8ed0..da876d3924be 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -444,7 +444,7 @@ static void __iomem *hptiop_map_pci_bar(struct hptiop_hba *hba, int index)
if (!(pci_resource_flags(pcidev, index) & IORESOURCE_MEM)) {
printk(KERN_ERR "scsi%d: pci resource invalid\n",
hba->host->host_no);
- return 0;
+ return NULL;
}
mem_base_phy = pci_resource_start(pcidev, index);
@@ -454,7 +454,7 @@ static void __iomem *hptiop_map_pci_bar(struct hptiop_hba *hba, int index)
if (!mem_base_virt) {
printk(KERN_ERR "scsi%d: Fail to ioremap memory space\n",
hba->host->host_no);
- return 0;
+ return NULL;
}
return mem_base_virt;
}
@@ -476,11 +476,11 @@ static void hptiop_unmap_pci_bar_itl(struct hptiop_hba *hba)
static int hptiop_map_pci_bar_mv(struct hptiop_hba *hba)
{
hba->u.mv.regs = hptiop_map_pci_bar(hba, 0);
- if (hba->u.mv.regs == 0)
+ if (hba->u.mv.regs == NULL)
return -1;
hba->u.mv.mu = hptiop_map_pci_bar(hba, 2);
- if (hba->u.mv.mu == 0) {
+ if (hba->u.mv.mu == NULL) {
iounmap(hba->u.mv.regs);
return -1;
}
@@ -1210,8 +1210,8 @@ static void hptiop_remove(struct pci_dev *pcidev)
static struct hptiop_adapter_ops hptiop_itl_ops = {
.iop_wait_ready = iop_wait_ready_itl,
- .internal_memalloc = 0,
- .internal_memfree = 0,
+ .internal_memalloc = NULL,
+ .internal_memfree = NULL,
.map_pci_bar = hptiop_map_pci_bar_itl,
.unmap_pci_bar = hptiop_unmap_pci_bar_itl,
.enable_intr = hptiop_enable_intr_itl,
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index ccfd8aca3765..5d23368a1bce 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -1348,7 +1348,7 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
del_timer(&evt_struct->timer);
- if (crq->status != VIOSRP_OK && evt_struct->cmnd)
+ if ((crq->status != VIOSRP_OK && crq->status != VIOSRP_OK2) && evt_struct->cmnd)
evt_struct->cmnd->result = DID_ERROR << 16;
if (evt_struct->done)
evt_struct->done(evt_struct);
diff --git a/drivers/scsi/ibmvscsi/viosrp.h b/drivers/scsi/ibmvscsi/viosrp.h
index 4c4aadb3e405..204604501ad8 100644
--- a/drivers/scsi/ibmvscsi/viosrp.h
+++ b/drivers/scsi/ibmvscsi/viosrp.h
@@ -65,7 +65,8 @@ enum viosrp_crq_status {
VIOSRP_VIOLATES_MAX_XFER = 0x2,
VIOSRP_PARTNER_PANIC = 0x3,
VIOSRP_DEVICE_BUSY = 0x8,
- VIOSRP_ADAPTER_FAIL = 0x10
+ VIOSRP_ADAPTER_FAIL = 0x10,
+ VIOSRP_OK2 = 0x99,
};
struct viosrp_crq {
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 51e2f299dbbb..3754ab87f89a 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -2811,7 +2811,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
/* Check for room in outstanding command list. */
for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS &&
- ha->outstanding_cmds[cnt] != 0; cnt++);
+ ha->outstanding_cmds[cnt] != NULL; cnt++);
if (cnt >= MAX_OUTSTANDING_COMMANDS) {
status = 1;
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 287690853caf..8dd88fc1244a 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -70,6 +70,9 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj,
case 2:
qla2x00_alloc_fw_dump(ha);
break;
+ case 3:
+ qla2x00_system_error(ha);
+ break;
}
return (count);
}
@@ -886,9 +889,13 @@ qla2x00_get_host_speed(struct Scsi_Host *shost)
static void
qla2x00_get_host_port_type(struct Scsi_Host *shost)
{
- scsi_qla_host_t *ha = to_qla_parent(shost_priv(shost));
+ scsi_qla_host_t *ha = shost_priv(shost);
uint32_t port_type = FC_PORTTYPE_UNKNOWN;
+ if (ha->parent) {
+ fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
+ return;
+ }
switch (ha->current_topology) {
case ISP_CFG_NL:
port_type = FC_PORTTYPE_LPORT;
@@ -1172,10 +1179,10 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
qla24xx_disable_vp(vha);
qla24xx_deallocate_vp_id(vha);
- down(&ha->vport_sem);
+ mutex_lock(&ha->vport_lock);
ha->cur_vport_count--;
clear_bit(vha->vp_idx, ha->vp_idx_map);
- up(&ha->vport_sem);
+ mutex_unlock(&ha->vport_lock);
kfree(vha->node_name);
kfree(vha->port_name);
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 299eccf6cabd..8dd600013bd1 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2457,7 +2457,7 @@ typedef struct scsi_qla_host {
#define MBX_INTR_WAIT 2
#define MBX_UPDATE_FLASH_ACTIVE 3
- struct semaphore vport_sem; /* Virtual port synchronization */
+ struct mutex vport_lock; /* Virtual port synchronization */
struct completion mbx_cmd_comp; /* Serialize mbx access */
struct completion mbx_intr_comp; /* Used for completion notification */
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index f8827068d30f..9b4bebee6879 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -228,6 +228,9 @@ extern int qla24xx_abort_target(struct fc_port *, unsigned int);
extern int qla24xx_lun_reset(struct fc_port *, unsigned int);
extern int
+qla2x00_system_error(scsi_qla_host_t *);
+
+extern int
qla2x00_set_serdes_params(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t);
extern int
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index e9bae27737d1..92fafbdbbaab 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -34,7 +34,11 @@ qla2x00_debounce_register(volatile uint16_t __iomem *addr)
static inline void
qla2x00_poll(scsi_qla_host_t *ha)
{
+ unsigned long flags;
+
+ local_irq_save(flags);
ha->isp_ops->intr_handler(0, ha);
+ local_irq_restore(flags);
}
static __inline__ scsi_qla_host_t *
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 5d9a64a7879b..ec63b79f900a 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -272,8 +272,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
uint32_t rscn_entry, host_pid;
uint8_t rscn_queue_index;
unsigned long flags;
- scsi_qla_host_t *vha;
- int i;
/* Setup to process RIO completion. */
handle_cnt = 0;
@@ -544,18 +542,10 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
break;
case MBA_PORT_UPDATE: /* Port database update */
- if ((ha->flags.npiv_supported) && (ha->num_vhosts)) {
- for_each_mapped_vp_idx(ha, i) {
- list_for_each_entry(vha, &ha->vp_list,
- vp_list) {
- if ((mb[3] & 0xff)
- == vha->vp_idx) {
- ha = vha;
- break;
- }
- }
- }
- }
+ /* Only handle SCNs for our Vport index. */
+ if (ha->parent && ha->vp_idx != (mb[3] & 0xff))
+ break;
+
/*
* If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET
* event etc. earlier indicating loop is down) then process
@@ -590,18 +580,12 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
break;
case MBA_RSCN_UPDATE: /* State Change Registration */
- if ((ha->flags.npiv_supported) && (ha->num_vhosts)) {
- for_each_mapped_vp_idx(ha, i) {
- list_for_each_entry(vha, &ha->vp_list,
- vp_list) {
- if ((mb[3] & 0xff)
- == vha->vp_idx) {
- ha = vha;
- break;
- }
- }
- }
- }
+ /* Check if the Vport has issued a SCR */
+ if (ha->parent && test_bit(VP_SCR_NEEDED, &ha->vp_flags))
+ break;
+ /* Only handle SCNs for our Vport index. */
+ if (ha->parent && ha->vp_idx != (mb[3] & 0xff))
+ break;
DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n",
ha->host_no));
@@ -1132,25 +1116,6 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
break;
qla2x00_handle_sense(sp, sense_data, sense_len);
-
- /*
- * In case of a Underrun condition, set both the lscsi
- * status and the completion status to appropriate
- * values.
- */
- if (resid &&
- ((unsigned)(scsi_bufflen(cp) - resid) <
- cp->underflow)) {
- DEBUG2(qla_printk(KERN_INFO, ha,
- "scsi(%ld:%d:%d:%d): Mid-layer underflow "
- "detected (%x of %x bytes)...returning "
- "error status.\n", ha->host_no,
- cp->device->channel, cp->device->id,
- cp->device->lun, resid,
- scsi_bufflen(cp)));
-
- cp->result = DID_ERROR << 16 | lscsi_status;
- }
} else {
/*
* If RISC reports underrun and target does not report
@@ -1639,12 +1604,12 @@ qla24xx_msix_rsp_q(int irq, void *dev_id)
ha = dev_id;
reg = &ha->iobase->isp24;
- spin_lock(&ha->hardware_lock);
+ spin_lock_irq(&ha->hardware_lock);
qla24xx_process_response_queue(ha);
WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
- spin_unlock(&ha->hardware_lock);
+ spin_unlock_irq(&ha->hardware_lock);
return IRQ_HANDLED;
}
@@ -1663,7 +1628,7 @@ qla24xx_msix_default(int irq, void *dev_id)
reg = &ha->iobase->isp24;
status = 0;
- spin_lock(&ha->hardware_lock);
+ spin_lock_irq(&ha->hardware_lock);
do {
stat = RD_REG_DWORD(&reg->host_status);
if (stat & HSRX_RISC_PAUSED) {
@@ -1716,7 +1681,7 @@ qla24xx_msix_default(int irq, void *dev_id)
}
WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
} while (0);
- spin_unlock(&ha->hardware_lock);
+ spin_unlock_irq(&ha->hardware_lock);
if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
(status & MBX_INTERRUPT) && ha->flags.mbox_int) {
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 210060420809..250d2f604397 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -2303,8 +2303,6 @@ qla24xx_lun_reset(struct fc_port *fcport, unsigned int l)
return __qla24xx_issue_tmf("Lun", TCF_LUN_RESET, fcport, l);
}
-#if 0
-
int
qla2x00_system_error(scsi_qla_host_t *ha)
{
@@ -2312,7 +2310,7 @@ qla2x00_system_error(scsi_qla_host_t *ha)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- if (!IS_FWI2_CAPABLE(ha))
+ if (!IS_QLA23XX(ha) && !IS_FWI2_CAPABLE(ha))
return QLA_FUNCTION_FAILED;
DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
@@ -2334,8 +2332,6 @@ qla2x00_system_error(scsi_qla_host_t *ha)
return rval;
}
-#endif /* 0 */
-
/**
* qla2x00_set_serdes_params() -
* @ha: HA context
@@ -2508,7 +2504,7 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *ha, dma_addr_t fce_dma,
if (mb)
memcpy(mb, mcp->mb, 8 * sizeof(*mb));
if (dwords)
- *dwords = mcp->mb[6];
+ *dwords = buffers;
}
return rval;
@@ -2807,9 +2803,9 @@ qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
*/
map = (vp_index - 1) / 8;
pos = (vp_index - 1) & 7;
- down(&ha->vport_sem);
+ mutex_lock(&ha->vport_lock);
vce->vp_idx_map[map] |= 1 << pos;
- up(&ha->vport_sem);
+ mutex_unlock(&ha->vport_lock);
rval = qla2x00_issue_iocb(ha, vce, vce_dma, 0);
if (rval != QLA_SUCCESS) {
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index f2b04979e5f0..62a3ad6e8ecb 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -32,12 +32,12 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha)
scsi_qla_host_t *ha = vha->parent;
/* Find an empty slot and assign an vp_id */
- down(&ha->vport_sem);
+ mutex_lock(&ha->vport_lock);
vp_id = find_first_zero_bit(ha->vp_idx_map, ha->max_npiv_vports + 1);
if (vp_id > ha->max_npiv_vports) {
DEBUG15(printk ("vp_id %d is bigger than max-supported %d.\n",
vp_id, ha->max_npiv_vports));
- up(&ha->vport_sem);
+ mutex_unlock(&ha->vport_lock);
return vp_id;
}
@@ -45,7 +45,7 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha)
ha->num_vhosts++;
vha->vp_idx = vp_id;
list_add_tail(&vha->vp_list, &ha->vp_list);
- up(&ha->vport_sem);
+ mutex_unlock(&ha->vport_lock);
return vp_id;
}
@@ -55,12 +55,12 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
uint16_t vp_id;
scsi_qla_host_t *ha = vha->parent;
- down(&ha->vport_sem);
+ mutex_lock(&ha->vport_lock);
vp_id = vha->vp_idx;
ha->num_vhosts--;
clear_bit(vp_id, ha->vp_idx_map);
list_del(&vha->vp_list);
- up(&ha->vport_sem);
+ mutex_unlock(&ha->vport_lock);
}
static scsi_qla_host_t *
@@ -145,9 +145,9 @@ qla24xx_enable_vp(scsi_qla_host_t *vha)
}
/* Initialize the new vport unless it is a persistent port */
- down(&ha->vport_sem);
+ mutex_lock(&ha->vport_lock);
ret = qla24xx_modify_vp_config(vha);
- up(&ha->vport_sem);
+ mutex_unlock(&ha->vport_lock);
if (ret != QLA_SUCCESS) {
fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED);
@@ -406,6 +406,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
INIT_LIST_HEAD(&vha->list);
INIT_LIST_HEAD(&vha->fcports);
INIT_LIST_HEAD(&vha->vp_fcports);
+ INIT_LIST_HEAD(&vha->work_list);
vha->dpc_flags = 0L;
set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
@@ -437,10 +438,10 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
vha->flags.init_done = 1;
num_hosts++;
- down(&ha->vport_sem);
+ mutex_lock(&ha->vport_lock);
set_bit(vha->vp_idx, ha->vp_idx_map);
ha->cur_vport_count++;
- up(&ha->vport_sem);
+ mutex_unlock(&ha->vport_lock);
return vha;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 3223fd16bcfe..48eaa3bb5433 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -10,6 +10,7 @@
#include <linux/vmalloc.h>
#include <linux/delay.h>
#include <linux/kthread.h>
+#include <linux/mutex.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsicam.h>
@@ -1631,7 +1632,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* load the F/W, read paramaters, and init the H/W */
ha->instance = num_hosts;
- init_MUTEX(&ha->vport_sem);
+ mutex_init(&ha->vport_lock);
init_completion(&ha->mbx_cmd_comp);
complete(&ha->mbx_cmd_comp);
init_completion(&ha->mbx_intr_comp);
@@ -2156,13 +2157,14 @@ static int
qla2x00_post_work(struct scsi_qla_host *ha, struct qla_work_evt *e, int locked)
{
unsigned long flags;
+ scsi_qla_host_t *pha = to_qla_parent(ha);
if (!locked)
- spin_lock_irqsave(&ha->hardware_lock, flags);
+ spin_lock_irqsave(&pha->hardware_lock, flags);
list_add_tail(&e->list, &ha->work_list);
qla2xxx_wake_dpc(ha);
if (!locked)
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ spin_unlock_irqrestore(&pha->hardware_lock, flags);
return QLA_SUCCESS;
}
@@ -2202,12 +2204,13 @@ static void
qla2x00_do_work(struct scsi_qla_host *ha)
{
struct qla_work_evt *e;
+ scsi_qla_host_t *pha = to_qla_parent(ha);
- spin_lock_irq(&ha->hardware_lock);
+ spin_lock_irq(&pha->hardware_lock);
while (!list_empty(&ha->work_list)) {
e = list_entry(ha->work_list.next, struct qla_work_evt, list);
list_del_init(&e->list);
- spin_unlock_irq(&ha->hardware_lock);
+ spin_unlock_irq(&pha->hardware_lock);
switch (e->type) {
case QLA_EVT_AEN:
@@ -2221,9 +2224,9 @@ qla2x00_do_work(struct scsi_qla_host *ha)
}
if (e->flags & QLA_EVT_FLAG_FREE)
kfree(e);
- spin_lock_irq(&ha->hardware_lock);
+ spin_lock_irq(&pha->hardware_lock);
}
- spin_unlock_irq(&ha->hardware_lock);
+ spin_unlock_irq(&pha->hardware_lock);
}
/**************************************************************************
@@ -2634,7 +2637,7 @@ qla2x00_timer(scsi_qla_host_t *ha)
#define FW_FILE_ISP24XX "ql2400_fw.bin"
#define FW_FILE_ISP25XX "ql2500_fw.bin"
-static DECLARE_MUTEX(qla_fw_lock);
+static DEFINE_MUTEX(qla_fw_lock);
static struct fw_blob qla_fw_blobs[FW_BLOBS] = {
{ .name = FW_FILE_ISP21XX, .segs = { 0x1000, 0 }, },
@@ -2665,7 +2668,7 @@ qla2x00_request_firmware(scsi_qla_host_t *ha)
blob = &qla_fw_blobs[FW_ISP25XX];
}
- down(&qla_fw_lock);
+ mutex_lock(&qla_fw_lock);
if (blob->fw)
goto out;
@@ -2678,7 +2681,7 @@ qla2x00_request_firmware(scsi_qla_host_t *ha)
}
out:
- up(&qla_fw_lock);
+ mutex_unlock(&qla_fw_lock);
return blob;
}
@@ -2687,11 +2690,11 @@ qla2x00_release_firmware(void)
{
int idx;
- down(&qla_fw_lock);
+ mutex_lock(&qla_fw_lock);
for (idx = 0; idx < FW_BLOBS; idx++)
if (qla_fw_blobs[idx].fw)
release_firmware(qla_fw_blobs[idx].fw);
- up(&qla_fw_lock);
+ mutex_unlock(&qla_fw_lock);
}
static pci_ers_result_t
@@ -2864,7 +2867,8 @@ qla2x00_module_init(void)
return -ENODEV;
}
- printk(KERN_INFO "QLogic Fibre Channel HBA Driver\n");
+ printk(KERN_INFO "QLogic Fibre Channel HBA Driver: %s\n",
+ qla2x00_version_str);
ret = pci_register_driver(&qla2xxx_pci_driver);
if (ret) {
kmem_cache_destroy(srb_cachep);
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index afeae2bfe7eb..d058c8862b35 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,7 +7,7 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "8.02.01-k2"
+#define QLA2XXX_VERSION "8.02.01-k4"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 2
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 049103f1d16f..93d2b6714453 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -359,7 +359,12 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv)
static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
{
- struct scsi_device *sdev = to_scsi_device(dev);
+ struct scsi_device *sdev;
+
+ if (dev->type != &scsi_dev_type)
+ return 0;
+
+ sdev = to_scsi_device(dev);
add_uevent_var(env, "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type);
return 0;
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 1400ea6a2491..1bc00b721e9d 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -43,7 +43,6 @@
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/serial.h>
#include "8250.h"
@@ -93,6 +92,7 @@ static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS;
*/
#define CONFIG_HUB6 1
+#include <asm/serial.h>
/*
* SERIAL_PORT_DFNS tells us about built-in ports that have no
* standard enumeration mechanism. Platforms that can find all
@@ -1547,8 +1547,6 @@ static int serial_link_irq_chain(struct uart_8250_port *up)
i->head = &up->list;
spin_unlock_irq(&i->lock);
- irq_flags |= SERIAL_EXTRA_IRQ_FLAGS;
-
ret = request_irq(up->port.irq, serial8250_interrupt,
irq_flags, "serial", i);
if (ret < 0)
diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h
index a10a40cc0d9e..91bd28f2bb47 100644
--- a/drivers/serial/8250.h
+++ b/drivers/serial/8250.h
@@ -78,8 +78,3 @@ struct serial8250_config {
#else
#define ALPHA_KLUDGE_MCR 0
#endif
-
-#ifndef SERIAL_EXTRA_IRQ_FLAGS
-#define SERIAL_EXTRA_IRQ_FLAGS 0
-#endif
-
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 53fa19cf2f06..788c3559522d 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -2602,7 +2602,12 @@ static struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS200,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0811 */
pbn_b2_2_115200 },
-
+ /*
+ * IntaShield IS-400
+ */
+ { PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS400,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0dc0 */
+ pbn_b2_4_115200 },
/*
* Perle PCI-RAS cards
*/
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index c065a704a93a..42be8b01a40f 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -1318,7 +1318,7 @@ static void __init atmel_console_get_options(struct uart_port *port, int *baud,
* If the baud rate generator isn't running, the port wasn't
* initialized by the boot loader.
*/
- quot = UART_GET_BRGR(port);
+ quot = UART_GET_BRGR(port) & ATMEL_US_CD;
if (!quot)
return;
diff --git a/drivers/serial/sb1250-duart.c b/drivers/serial/sb1250-duart.c
index 2d6c08b3dbcf..f8e1447a022a 100644
--- a/drivers/serial/sb1250-duart.c
+++ b/drivers/serial/sb1250-duart.c
@@ -924,7 +924,7 @@ console_initcall(sbd_serial_console_init);
static struct uart_driver sbd_reg = {
.owner = THIS_MODULE,
- .driver_name = "serial",
+ .driver_name = "sb1250_duart",
.dev_name = "duart",
.major = TTY_MAJOR,
.minor = SB1250_DUART_MINOR_BASE,
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index eab032733790..c9b64e73c987 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -1165,6 +1165,15 @@ out:
return ret;
}
+static void uart_set_ldisc(struct tty_struct *tty)
+{
+ struct uart_state *state = tty->driver_data;
+ struct uart_port *port = state->port;
+
+ if (port->ops->set_ldisc)
+ port->ops->set_ldisc(port);
+}
+
static void uart_set_termios(struct tty_struct *tty,
struct ktermios *old_termios)
{
@@ -2054,6 +2063,8 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
{
struct uart_state *state = drv->state + port->line;
+ struct device *tty_dev;
+ struct uart_match match = {port, drv};
mutex_lock(&state->mutex);
@@ -2063,7 +2074,8 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
return 0;
}
- if (!port->suspended) {
+ tty_dev = device_find_child(port->dev, &match, serial_match_port);
+ if (!port->suspended && device_may_wakeup(tty_dev)) {
disable_irq_wake(port->irq);
mutex_unlock(&state->mutex);
return 0;
@@ -2285,6 +2297,7 @@ static const struct tty_operations uart_ops = {
.unthrottle = uart_unthrottle,
.send_xchar = uart_send_xchar,
.set_termios = uart_set_termios,
+ .set_ldisc = uart_set_ldisc,
.stop = uart_stop,
.start = uart_start,
.hangup = uart_hangup,
diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c
index 01917c433f17..566a8b42e05a 100644
--- a/drivers/serial/ucc_uart.c
+++ b/drivers/serial/ucc_uart.c
@@ -195,7 +195,7 @@ struct uart_qe_port {
static struct uart_driver ucc_uart_driver = {
.owner = THIS_MODULE,
- .driver_name = "serial",
+ .driver_name = "ucc_uart",
.dev_name = "ttyQE",
.major = SERIAL_QE_MAJOR,
.minor = SERIAL_QE_MINOR,
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index b3518ca9f04e..799337f7fde1 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -25,6 +25,7 @@
#include <linux/ioctl.h>
#include <linux/fs.h>
#include <linux/device.h>
+#include <linux/err.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/mutex.h>
@@ -67,10 +68,12 @@ static unsigned long minors[N_SPI_MINORS / BITS_PER_LONG];
| SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP)
struct spidev_data {
- struct device dev;
+ dev_t devt;
+ spinlock_t spi_lock;
struct spi_device *spi;
struct list_head device_entry;
+ /* buffer is NULL unless this device is open (users > 0) */
struct mutex buf_lock;
unsigned users;
u8 *buffer;
@@ -85,12 +88,75 @@ MODULE_PARM_DESC(bufsiz, "data bytes in biggest supported SPI message");
/*-------------------------------------------------------------------------*/
+/*
+ * We can't use the standard synchronous wrappers for file I/O; we
+ * need to protect against async removal of the underlying spi_device.
+ */
+static void spidev_complete(void *arg)
+{
+ complete(arg);
+}
+
+static ssize_t
+spidev_sync(struct spidev_data *spidev, struct spi_message *message)
+{
+ DECLARE_COMPLETION_ONSTACK(done);
+ int status;
+
+ message->complete = spidev_complete;
+ message->context = &done;
+
+ spin_lock_irq(&spidev->spi_lock);
+ if (spidev->spi == NULL)
+ status = -ESHUTDOWN;
+ else
+ status = spi_async(spidev->spi, message);
+ spin_unlock_irq(&spidev->spi_lock);
+
+ if (status == 0) {
+ wait_for_completion(&done);
+ status = message->status;
+ if (status == 0)
+ status = message->actual_length;
+ }
+ return status;
+}
+
+static inline ssize_t
+spidev_sync_write(struct spidev_data *spidev, size_t len)
+{
+ struct spi_transfer t = {
+ .tx_buf = spidev->buffer,
+ .len = len,
+ };
+ struct spi_message m;
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+ return spidev_sync(spidev, &m);
+}
+
+static inline ssize_t
+spidev_sync_read(struct spidev_data *spidev, size_t len)
+{
+ struct spi_transfer t = {
+ .rx_buf = spidev->buffer,
+ .len = len,
+ };
+ struct spi_message m;
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+ return spidev_sync(spidev, &m);
+}
+
+/*-------------------------------------------------------------------------*/
+
/* Read-only message with current device setup */
static ssize_t
spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
struct spidev_data *spidev;
- struct spi_device *spi;
ssize_t status = 0;
/* chipselect only toggles at start or end of operation */
@@ -98,10 +164,9 @@ spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
return -EMSGSIZE;
spidev = filp->private_data;
- spi = spidev->spi;
mutex_lock(&spidev->buf_lock);
- status = spi_read(spi, spidev->buffer, count);
+ status = spidev_sync_read(spidev, count);
if (status == 0) {
unsigned long missing;
@@ -122,7 +187,6 @@ spidev_write(struct file *filp, const char __user *buf,
size_t count, loff_t *f_pos)
{
struct spidev_data *spidev;
- struct spi_device *spi;
ssize_t status = 0;
unsigned long missing;
@@ -131,12 +195,11 @@ spidev_write(struct file *filp, const char __user *buf,
return -EMSGSIZE;
spidev = filp->private_data;
- spi = spidev->spi;
mutex_lock(&spidev->buf_lock);
missing = copy_from_user(spidev->buffer, buf, count);
if (missing == 0) {
- status = spi_write(spi, spidev->buffer, count);
+ status = spidev_sync_write(spidev, count);
if (status == 0)
status = count;
} else
@@ -153,7 +216,6 @@ static int spidev_message(struct spidev_data *spidev,
struct spi_transfer *k_xfers;
struct spi_transfer *k_tmp;
struct spi_ioc_transfer *u_tmp;
- struct spi_device *spi = spidev->spi;
unsigned n, total;
u8 *buf;
int status = -EFAULT;
@@ -215,7 +277,7 @@ static int spidev_message(struct spidev_data *spidev,
spi_message_add_tail(k_tmp, &msg);
}
- status = spi_sync(spi, &msg);
+ status = spidev_sync(spidev, &msg);
if (status < 0)
goto done;
@@ -269,8 +331,16 @@ spidev_ioctl(struct inode *inode, struct file *filp,
if (err)
return -EFAULT;
+ /* guard against device removal before, or while,
+ * we issue this ioctl.
+ */
spidev = filp->private_data;
- spi = spidev->spi;
+ spin_lock_irq(&spidev->spi_lock);
+ spi = spi_dev_get(spidev->spi);
+ spin_unlock_irq(&spidev->spi_lock);
+
+ if (spi == NULL)
+ return -ESHUTDOWN;
switch (cmd) {
/* read requests */
@@ -356,8 +426,10 @@ spidev_ioctl(struct inode *inode, struct file *filp,
default:
/* segmented and/or full-duplex I/O request */
if (_IOC_NR(cmd) != _IOC_NR(SPI_IOC_MESSAGE(0))
- || _IOC_DIR(cmd) != _IOC_WRITE)
- return -ENOTTY;
+ || _IOC_DIR(cmd) != _IOC_WRITE) {
+ retval = -ENOTTY;
+ break;
+ }
tmp = _IOC_SIZE(cmd);
if ((tmp % sizeof(struct spi_ioc_transfer)) != 0) {
@@ -385,6 +457,7 @@ spidev_ioctl(struct inode *inode, struct file *filp,
kfree(ioc);
break;
}
+ spi_dev_put(spi);
return retval;
}
@@ -396,7 +469,7 @@ static int spidev_open(struct inode *inode, struct file *filp)
mutex_lock(&device_list_lock);
list_for_each_entry(spidev, &device_list, device_entry) {
- if (spidev->dev.devt == inode->i_rdev) {
+ if (spidev->devt == inode->i_rdev) {
status = 0;
break;
}
@@ -429,10 +502,22 @@ static int spidev_release(struct inode *inode, struct file *filp)
mutex_lock(&device_list_lock);
spidev = filp->private_data;
filp->private_data = NULL;
+
+ /* last close? */
spidev->users--;
if (!spidev->users) {
+ int dofree;
+
kfree(spidev->buffer);
spidev->buffer = NULL;
+
+ /* ... after we unbound from the underlying device? */
+ spin_lock_irq(&spidev->spi_lock);
+ dofree = (spidev->spi == NULL);
+ spin_unlock_irq(&spidev->spi_lock);
+
+ if (dofree)
+ kfree(spidev);
}
mutex_unlock(&device_list_lock);
@@ -459,19 +544,7 @@ static struct file_operations spidev_fops = {
* It also simplifies memory management.
*/
-static void spidev_classdev_release(struct device *dev)
-{
- struct spidev_data *spidev;
-
- spidev = container_of(dev, struct spidev_data, dev);
- kfree(spidev);
-}
-
-static struct class spidev_class = {
- .name = "spidev",
- .owner = THIS_MODULE,
- .dev_release = spidev_classdev_release,
-};
+static struct class *spidev_class;
/*-------------------------------------------------------------------------*/
@@ -488,6 +561,7 @@ static int spidev_probe(struct spi_device *spi)
/* Initialize the driver data */
spidev->spi = spi;
+ spin_lock_init(&spidev->spi_lock);
mutex_init(&spidev->buf_lock);
INIT_LIST_HEAD(&spidev->device_entry);
@@ -498,20 +572,20 @@ static int spidev_probe(struct spi_device *spi)
mutex_lock(&device_list_lock);
minor = find_first_zero_bit(minors, N_SPI_MINORS);
if (minor < N_SPI_MINORS) {
- spidev->dev.parent = &spi->dev;
- spidev->dev.class = &spidev_class;
- spidev->dev.devt = MKDEV(SPIDEV_MAJOR, minor);
- snprintf(spidev->dev.bus_id, sizeof spidev->dev.bus_id,
+ struct device *dev;
+
+ spidev->devt = MKDEV(SPIDEV_MAJOR, minor);
+ dev = device_create(spidev_class, &spi->dev, spidev->devt,
"spidev%d.%d",
spi->master->bus_num, spi->chip_select);
- status = device_register(&spidev->dev);
+ status = IS_ERR(dev) ? PTR_ERR(dev) : 0;
} else {
dev_dbg(&spi->dev, "no minor number available!\n");
status = -ENODEV;
}
if (status == 0) {
set_bit(minor, minors);
- dev_set_drvdata(&spi->dev, spidev);
+ spi_set_drvdata(spi, spidev);
list_add(&spidev->device_entry, &device_list);
}
mutex_unlock(&device_list_lock);
@@ -524,15 +598,21 @@ static int spidev_probe(struct spi_device *spi)
static int spidev_remove(struct spi_device *spi)
{
- struct spidev_data *spidev = dev_get_drvdata(&spi->dev);
+ struct spidev_data *spidev = spi_get_drvdata(spi);
- mutex_lock(&device_list_lock);
+ /* make sure ops on existing fds can abort cleanly */
+ spin_lock_irq(&spidev->spi_lock);
+ spidev->spi = NULL;
+ spi_set_drvdata(spi, NULL);
+ spin_unlock_irq(&spidev->spi_lock);
+ /* prevent new opens */
+ mutex_lock(&device_list_lock);
list_del(&spidev->device_entry);
- dev_set_drvdata(&spi->dev, NULL);
- clear_bit(MINOR(spidev->dev.devt), minors);
- device_unregister(&spidev->dev);
-
+ device_destroy(spidev_class, spidev->devt);
+ clear_bit(MINOR(spidev->devt), minors);
+ if (spidev->users == 0)
+ kfree(spidev);
mutex_unlock(&device_list_lock);
return 0;
@@ -568,15 +648,15 @@ static int __init spidev_init(void)
if (status < 0)
return status;
- status = class_register(&spidev_class);
- if (status < 0) {
+ spidev_class = class_create(THIS_MODULE, "spidev");
+ if (IS_ERR(spidev_class)) {
unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);
- return status;
+ return PTR_ERR(spidev_class);
}
status = spi_register_driver(&spidev_spi);
if (status < 0) {
- class_unregister(&spidev_class);
+ class_destroy(spidev_class);
unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);
}
return status;
@@ -586,7 +666,7 @@ module_init(spidev_init);
static void __exit spidev_exit(void)
{
spi_unregister_driver(&spidev_spi);
- class_unregister(&spidev_class);
+ class_destroy(spidev_class);
unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);
}
module_exit(spidev_exit);
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c
index 75def13e797d..d28c53868093 100644
--- a/drivers/ssb/driver_pcicore.c
+++ b/drivers/ssb/driver_pcicore.c
@@ -537,12 +537,12 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
int err = 0;
u32 tmp;
- might_sleep();
-
if (!pdev)
goto out;
bus = pdev->bus;
+ might_sleep_if(pdev->id.coreid != SSB_DEV_PCI);
+
/* Enable interrupts for this device. */
if (bus->host_pci &&
((pdev->id.revision >= 6) || (pdev->id.coreid == SSB_DEV_PCIE))) {
diff --git a/drivers/usb/c67x00/c67x00-ll-hpi.c b/drivers/usb/c67x00/c67x00-ll-hpi.c
index 5100fbbf6cb0..a9636f43bca2 100644
--- a/drivers/usb/c67x00/c67x00-ll-hpi.c
+++ b/drivers/usb/c67x00/c67x00-ll-hpi.c
@@ -120,7 +120,7 @@ static void hpi_write_word(struct c67x00_device *dev, u16 reg, u16 value)
* Only data is little endian, addr has cpu endianess
*/
static void hpi_write_words_le16(struct c67x00_device *dev, u16 addr,
- u16 *data, u16 count)
+ __le16 *data, u16 count)
{
unsigned long flags;
int i;
@@ -129,7 +129,7 @@ static void hpi_write_words_le16(struct c67x00_device *dev, u16 addr,
hpi_write_reg(dev, HPI_ADDR, addr);
for (i = 0; i < count; i++)
- hpi_write_reg(dev, HPI_DATA, cpu_to_le16(*data++));
+ hpi_write_reg(dev, HPI_DATA, le16_to_cpu(*data++));
spin_unlock_irqrestore(&dev->hpi.lock, flags);
}
@@ -138,7 +138,7 @@ static void hpi_write_words_le16(struct c67x00_device *dev, u16 addr,
* Only data is little endian, addr has cpu endianess
*/
static void hpi_read_words_le16(struct c67x00_device *dev, u16 addr,
- u16 *data, u16 count)
+ __le16 *data, u16 count)
{
unsigned long flags;
int i;
@@ -146,7 +146,7 @@ static void hpi_read_words_le16(struct c67x00_device *dev, u16 addr,
spin_lock_irqsave(&dev->hpi.lock, flags);
hpi_write_reg(dev, HPI_ADDR, addr);
for (i = 0; i < count; i++)
- *data++ = le16_to_cpu(hpi_read_reg(dev, HPI_DATA));
+ *data++ = cpu_to_le16(hpi_read_reg(dev, HPI_DATA));
spin_unlock_irqrestore(&dev->hpi.lock, flags);
}
@@ -425,7 +425,7 @@ void c67x00_ll_write_mem_le16(struct c67x00_device *dev, u16 addr,
len--;
}
- hpi_write_words_le16(dev, addr, (u16 *)buf, len / 2);
+ hpi_write_words_le16(dev, addr, (__le16 *)buf, len / 2);
buf += len & ~0x01;
addr += len & ~0x01;
len &= 0x01;
@@ -456,7 +456,7 @@ void c67x00_ll_read_mem_le16(struct c67x00_device *dev, u16 addr,
len--;
}
- hpi_read_words_le16(dev, addr, (u16 *)buf, len / 2);
+ hpi_read_words_le16(dev, addr, (__le16 *)buf, len / 2);
buf += len & ~0x01;
addr += len & ~0x01;
len &= 0x01;
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 107666d4e2ec..731db051070a 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -611,8 +611,8 @@ next_desc:
goto err;
}
- desc->wMaxPacketSize = ep->wMaxPacketSize;
- desc->bMaxPacketSize0 = cpu_to_le16(udev->descriptor.bMaxPacketSize0);
+ desc->wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize);
+ desc->bMaxPacketSize0 = udev->descriptor.bMaxPacketSize0;
desc->orq = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
if (!desc->orq)
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index c1cb94e9f242..7e912f21fd36 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -155,9 +155,6 @@ static int generic_probe(struct usb_device *udev)
{
int err, c;
- /* put device-specific files into sysfs */
- usb_create_sysfs_dev_files(udev);
-
/* Choose and set the configuration. This registers the interfaces
* with the driver core and lets interface drivers bind to them.
*/
@@ -189,8 +186,6 @@ static void generic_disconnect(struct usb_device *udev)
* unconfigure the device */
if (udev->actconfig)
usb_set_configuration(udev, -1);
-
- usb_remove_sysfs_dev_files(udev);
}
#ifdef CONFIG_PM
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index 1e4b81e9eb50..a0bf5df6cb6f 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -213,6 +213,8 @@ struct hc_driver {
/* force handover of high-speed port to full-speed companion */
void (*relinquish_port)(struct usb_hcd *, int);
+ /* has a port been handed over to a companion? */
+ int (*port_handed_over)(struct usb_hcd *, int);
};
extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index eb57fcc701d7..8eb4da332f56 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1326,6 +1326,12 @@ void usb_disconnect(struct usb_device **pdev)
usb_unlock_device(udev);
+ /* Remove the device-specific files from sysfs. This must be
+ * done with udev unlocked, because some of the attribute
+ * routines try to acquire the device lock.
+ */
+ usb_remove_sysfs_dev_files(udev);
+
/* Unregister the device. The device driver is responsible
* for removing the device files from usbfs and sysfs and for
* de-configuring the device.
@@ -1541,6 +1547,9 @@ int usb_new_device(struct usb_device *udev)
goto fail;
}
+ /* put device-specific files into sysfs */
+ usb_create_sysfs_dev_files(udev);
+
/* Tell the world! */
announce_device(udev);
return err;
@@ -2744,7 +2753,11 @@ loop:
if ((status == -ENOTCONN) || (status == -ENOTSUPP))
break;
}
- dev_err(hub_dev, "unable to enumerate USB device on port %d\n", port1);
+ if (hub->hdev->parent ||
+ !hcd->driver->port_handed_over ||
+ !(hcd->driver->port_handed_over)(hcd, port1))
+ dev_err(hub_dev, "unable to enumerate USB device on port %d\n",
+ port1);
done:
hub_port_disable(hub, port1, 1);
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 2e2019390290..3da1ab4b389d 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -47,6 +47,10 @@ static const struct usb_device_id usb_quirk_list[] = {
/* Edirol SD-20 */
{ USB_DEVICE(0x0582, 0x0027), .driver_info = USB_QUIRK_RESET_RESUME },
+ /* Avision AV600U */
+ { USB_DEVICE(0x0638, 0x0a13), .driver_info =
+ USB_QUIRK_STRING_FETCH_255 },
+
/* M-Systems Flash Disk Pioneers */
{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index c783cb111847..5e1f5d55bf04 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -588,35 +588,33 @@ read_descriptors(struct kobject *kobj, struct bin_attribute *attr,
container_of(kobj, struct device, kobj));
size_t nleft = count;
size_t srclen, n;
+ int cfgno;
+ void *src;
- usb_lock_device(udev);
-
- /* The binary attribute begins with the device descriptor */
- srclen = sizeof(struct usb_device_descriptor);
- if (off < srclen) {
- n = min_t(size_t, nleft, srclen - off);
- memcpy(buf, off + (char *) &udev->descriptor, n);
- nleft -= n;
- buf += n;
- off = 0;
- } else {
- off -= srclen;
- }
-
- /* Then follows the raw descriptor entry for the current
- * configuration (config plus subsidiary descriptors).
+ /* The binary attribute begins with the device descriptor.
+ * Following that are the raw descriptor entries for all the
+ * configurations (config plus subsidiary descriptors).
*/
- if (udev->actconfig) {
- int cfgno = udev->actconfig - udev->config;
-
- srclen = __le16_to_cpu(udev->actconfig->desc.wTotalLength);
+ for (cfgno = -1; cfgno < udev->descriptor.bNumConfigurations &&
+ nleft > 0; ++cfgno) {
+ if (cfgno < 0) {
+ src = &udev->descriptor;
+ srclen = sizeof(struct usb_device_descriptor);
+ } else {
+ src = udev->rawdescriptors[cfgno];
+ srclen = __le16_to_cpu(udev->config[cfgno].desc.
+ wTotalLength);
+ }
if (off < srclen) {
- n = min_t(size_t, nleft, srclen - off);
- memcpy(buf, off + udev->rawdescriptors[cfgno], n);
+ n = min(nleft, srclen - (size_t) off);
+ memcpy(buf, src + off, n);
nleft -= n;
+ buf += n;
+ off = 0;
+ } else {
+ off -= srclen;
}
}
- usb_unlock_device(udev);
return count - nleft;
}
diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c
index 651b82701394..18687543d7fa 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.c
+++ b/drivers/usb/gadget/fsl_usb2_udc.c
@@ -1627,7 +1627,9 @@ static int reset_queues(struct fsl_udc *udc)
udc_reset_ep_queue(udc, pipe);
/* report disconnect; the driver is already quiesced */
+ spin_unlock(&udc->lock);
udc->driver->disconnect(&udc->gadget);
+ spin_lock(&udc->lock);
return 0;
}
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
index 8b5f991e949c..08a4335401a9 100644
--- a/drivers/usb/host/ehci-au1xxx.c
+++ b/drivers/usb/host/ehci-au1xxx.c
@@ -223,6 +223,7 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
.bus_suspend = ehci_bus_suspend,
.bus_resume = ehci_bus_resume,
.relinquish_port = ehci_relinquish_port,
+ .port_handed_over = ehci_port_handed_over,
};
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 6d9bed6c1f48..7370d6187c64 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -269,7 +269,7 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
if (retval)
return retval;
- ehci->is_tdi_rh_tt = 1;
+ hcd->has_tt = 1;
ehci->sbrn = 0x20;
@@ -295,10 +295,6 @@ static const struct hc_driver ehci_fsl_hc_driver = {
*/
.reset = ehci_fsl_setup,
.start = ehci_run,
-#ifdef CONFIG_PM
- .suspend = ehci_bus_suspend,
- .resume = ehci_bus_resume,
-#endif
.stop = ehci_stop,
.shutdown = ehci_shutdown,
@@ -322,6 +318,7 @@ static const struct hc_driver ehci_fsl_hc_driver = {
.bus_suspend = ehci_bus_suspend,
.bus_resume = ehci_bus_resume,
.relinquish_port = ehci_relinquish_port,
+ .port_handed_over = ehci_port_handed_over,
};
static int ehci_fsl_drv_probe(struct platform_device *pdev)
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 382587c4457c..740835bb8575 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -609,7 +609,7 @@ static int ehci_hub_control (
}
break;
case USB_PORT_FEAT_C_SUSPEND:
- /* we auto-clear this feature */
+ clear_bit(wIndex, &ehci->port_c_suspend);
break;
case USB_PORT_FEAT_POWER:
if (HCS_PPC (ehci->hcs_params))
@@ -688,7 +688,7 @@ static int ehci_hub_control (
/* resume completed? */
else if (time_after_eq(jiffies,
ehci->reset_done[wIndex])) {
- status |= 1 << USB_PORT_FEAT_C_SUSPEND;
+ set_bit(wIndex, &ehci->port_c_suspend);
ehci->reset_done[wIndex] = 0;
/* stop resume signaling */
@@ -765,6 +765,8 @@ static int ehci_hub_control (
status |= 1 << USB_PORT_FEAT_RESET;
if (temp & PORT_POWER)
status |= 1 << USB_PORT_FEAT_POWER;
+ if (test_bit(wIndex, &ehci->port_c_suspend))
+ status |= 1 << USB_PORT_FEAT_C_SUSPEND;
#ifndef VERBOSE_DEBUG
if (status & ~0xffff) /* only if wPortChange is interesting */
@@ -875,3 +877,13 @@ static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum)
set_owner(ehci, --portnum, PORT_OWNER);
}
+static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ u32 __iomem *reg;
+
+ if (ehci_is_TDI(ehci))
+ return 0;
+ reg = &ehci->regs->port_status[portnum - 1];
+ return ehci_readl(ehci, reg) & PORT_OWNER;
+}
diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
index 601c8795a854..9d042f220097 100644
--- a/drivers/usb/host/ehci-ixp4xx.c
+++ b/drivers/usb/host/ehci-ixp4xx.c
@@ -26,7 +26,7 @@ static int ixp4xx_ehci_init(struct usb_hcd *hcd)
+ HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
- ehci->is_tdi_rh_tt = 1;
+ hcd->has_tt = 1;
ehci_reset(ehci);
retval = ehci_init(hcd);
@@ -58,6 +58,8 @@ static const struct hc_driver ixp4xx_ehci_hc_driver = {
.bus_suspend = ehci_bus_suspend,
.bus_resume = ehci_bus_resume,
#endif
+ .relinquish_port = ehci_relinquish_port,
+ .port_handed_over = ehci_port_handed_over,
};
static int ixp4xx_ehci_probe(struct platform_device *pdev)
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index 3adfda813a7b..ab625f0ba1d9 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -139,10 +139,6 @@ static const struct hc_driver ehci_orion_hc_driver = {
*/
.reset = ehci_orion_setup,
.start = ehci_run,
-#ifdef CONFIG_PM
- .suspend = ehci_bus_suspend,
- .resume = ehci_bus_resume,
-#endif
.stop = ehci_stop,
.shutdown = ehci_shutdown,
@@ -165,6 +161,8 @@ static const struct hc_driver ehci_orion_hc_driver = {
.hub_control = ehci_hub_control,
.bus_suspend = ehci_bus_suspend,
.bus_resume = ehci_bus_resume,
+ .relinquish_port = ehci_relinquish_port,
+ .port_handed_over = ehci_port_handed_over,
};
static void __init
@@ -250,7 +248,7 @@ static int __init ehci_orion_drv_probe(struct platform_device *pdev)
ehci->regs = hcd->regs + 0x100 +
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
- ehci->is_tdi_rh_tt = 1;
+ hcd->has_tt = 1;
ehci->sbrn = 0x20;
/*
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 5bb7f6bb13f3..c46a58f9181d 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -129,7 +129,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
switch (pdev->vendor) {
case PCI_VENDOR_ID_TDI:
if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
- ehci->is_tdi_rh_tt = 1;
hcd->has_tt = 1;
tdi_reset(ehci);
}
@@ -379,7 +378,8 @@ static const struct hc_driver ehci_pci_hc_driver = {
.hub_control = ehci_hub_control,
.bus_suspend = ehci_bus_suspend,
.bus_resume = ehci_bus_resume,
- .relinquish_port = ehci_relinquish_port,
+ .relinquish_port = ehci_relinquish_port,
+ .port_handed_over = ehci_port_handed_over,
};
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
index ee305b1f99ff..b018deed2e8f 100644
--- a/drivers/usb/host/ehci-ppc-of.c
+++ b/drivers/usb/host/ehci-ppc-of.c
@@ -76,6 +76,8 @@ static const struct hc_driver ehci_ppc_of_hc_driver = {
.bus_suspend = ehci_bus_suspend,
.bus_resume = ehci_bus_resume,
#endif
+ .relinquish_port = ehci_relinquish_port,
+ .port_handed_over = ehci_port_handed_over,
};
diff --git a/drivers/usb/host/ehci-ppc-soc.c b/drivers/usb/host/ehci-ppc-soc.c
index 6c76036783a1..529590eb4037 100644
--- a/drivers/usb/host/ehci-ppc-soc.c
+++ b/drivers/usb/host/ehci-ppc-soc.c
@@ -163,6 +163,7 @@ static const struct hc_driver ehci_ppc_soc_hc_driver = {
.bus_suspend = ehci_bus_suspend,
.bus_resume = ehci_bus_resume,
.relinquish_port = ehci_relinquish_port,
+ .port_handed_over = ehci_port_handed_over,
};
static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev)
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
index 69782221bcf3..37e6abeb794c 100644
--- a/drivers/usb/host/ehci-ps3.c
+++ b/drivers/usb/host/ehci-ps3.c
@@ -73,6 +73,7 @@ static const struct hc_driver ps3_ehci_hc_driver = {
.bus_resume = ehci_bus_resume,
#endif
.relinquish_port = ehci_relinquish_port,
+ .port_handed_over = ehci_port_handed_over,
};
static int ps3_ehci_probe(struct ps3_system_bus_device *dev)
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index be575e46eac3..b7853c8bac0f 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1349,18 +1349,27 @@ iso_stream_schedule (
/* when's the last uframe this urb could start? */
max = now + mod;
- /* typical case: reuse current schedule. stream is still active,
- * and no gaps from host falling behind (irq delays etc)
+ /* Typical case: reuse current schedule, stream is still active.
+ * Hopefully there are no gaps from the host falling behind
+ * (irq delays etc), but if there are we'll take the next
+ * slot in the schedule, implicitly assuming URB_ISO_ASAP.
*/
if (likely (!list_empty (&stream->td_list))) {
start = stream->next_uframe;
if (start < now)
start += mod;
- if (likely ((start + sched->span) < max))
- goto ready;
- /* else fell behind; someday, try to reschedule */
- status = -EL2NSYNC;
- goto fail;
+
+ /* Fell behind (by up to twice the slop amount)? */
+ if (start >= max - 2 * 8 * SCHEDULE_SLOP)
+ start += stream->interval * DIV_ROUND_UP(
+ max - start, stream->interval) - mod;
+
+ /* Tried to schedule too far into the future? */
+ if (unlikely((start + sched->span) >= max)) {
+ status = -EFBIG;
+ goto fail;
+ }
+ goto ready;
}
/* need to schedule; when's the next (u)frame we could start?
@@ -1613,6 +1622,9 @@ itd_complete (
} else if (likely ((t & EHCI_ISOC_ACTIVE) == 0)) {
desc->status = 0;
desc->actual_length = EHCI_ITD_LENGTH (t);
+ } else {
+ /* URB was too late */
+ desc->status = -EXDEV;
}
}
@@ -2095,7 +2107,7 @@ done:
static void
scan_periodic (struct ehci_hcd *ehci)
{
- unsigned frame, clock, now_uframe, mod;
+ unsigned now_uframe, frame, clock, clock_frame, mod;
unsigned modified;
mod = ehci->periodic_size << 3;
@@ -2111,6 +2123,7 @@ scan_periodic (struct ehci_hcd *ehci)
else
clock = now_uframe + mod - 1;
clock %= mod;
+ clock_frame = clock >> 3;
for (;;) {
union ehci_shadow q, *q_p;
@@ -2157,22 +2170,26 @@ restart:
case Q_TYPE_ITD:
/* If this ITD is still active, leave it for
* later processing ... check the next entry.
+ * No need to check for activity unless the
+ * frame is current.
*/
- rmb ();
- for (uf = 0; uf < 8 && live; uf++) {
- if (0 == (q.itd->hw_transaction [uf]
- & ITD_ACTIVE(ehci)))
- continue;
- incomplete = true;
- q_p = &q.itd->itd_next;
- hw_p = &q.itd->hw_next;
- type = Q_NEXT_TYPE(ehci,
+ if (frame == clock_frame && live) {
+ rmb();
+ for (uf = 0; uf < 8; uf++) {
+ if (q.itd->hw_transaction[uf] &
+ ITD_ACTIVE(ehci))
+ break;
+ }
+ if (uf < 8) {
+ incomplete = true;
+ q_p = &q.itd->itd_next;
+ hw_p = &q.itd->hw_next;
+ type = Q_NEXT_TYPE(ehci,
q.itd->hw_next);
- q = *q_p;
- break;
+ q = *q_p;
+ break;
+ }
}
- if (uf < 8 && live)
- break;
/* Take finished ITDs out of the schedule
* and process them: recycle, maybe report
@@ -2189,9 +2206,12 @@ restart:
case Q_TYPE_SITD:
/* If this SITD is still active, leave it for
* later processing ... check the next entry.
+ * No need to check for activity unless the
+ * frame is current.
*/
- if ((q.sitd->hw_results & SITD_ACTIVE(ehci))
- && live) {
+ if (frame == clock_frame && live &&
+ (q.sitd->hw_results &
+ SITD_ACTIVE(ehci))) {
incomplete = true;
q_p = &q.sitd->sitd_next;
hw_p = &q.sitd->hw_next;
@@ -2260,6 +2280,7 @@ restart:
/* rescan the rest of this frame, then ... */
clock = now;
+ clock_frame = clock >> 3;
} else {
now_uframe++;
now_uframe %= mod;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index bf92d209a1a9..35a03095757e 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -97,6 +97,8 @@ struct ehci_hcd { /* one per controller */
dedicated to the companion controller */
unsigned long owned_ports; /* which ports are
owned by the companion during a bus suspend */
+ unsigned long port_c_suspend; /* which ports have
+ the change-suspend feature turned on */
/* per-HC memory pools (could be per-bus, but ...) */
struct dma_pool *qh_pool; /* qh per active urb */
@@ -112,7 +114,6 @@ struct ehci_hcd { /* one per controller */
u32 command;
/* SILICON QUIRKS */
- unsigned is_tdi_rh_tt:1; /* TDI roothub with TT */
unsigned no_selective_suspend:1;
unsigned has_fsl_port_bug:1; /* FreeScale */
unsigned big_endian_mmio:1;
@@ -678,7 +679,7 @@ struct ehci_fstn {
* needed (mostly in root hub code).
*/
-#define ehci_is_TDI(e) ((e)->is_tdi_rh_tt)
+#define ehci_is_TDI(e) (ehci_to_hcd(e)->has_tt)
/* Returns the speed of a device attached to a port on the root hub. */
static inline unsigned int
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c
index 440bf94f0d4c..c9db3fe98726 100644
--- a/drivers/usb/host/isp1760-if.c
+++ b/drivers/usb/host/isp1760-if.c
@@ -104,8 +104,8 @@ static u32 nxp_pci_io_base;
static u32 iolength;
static u32 pci_mem_phy0;
static u32 length;
-static u8 *chip_addr;
-static u8 *iobase;
+static u8 __iomem *chip_addr;
+static u8 __iomem *iobase;
static int __devinit isp1761_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index a53db1d4e07a..eb6c06979f3b 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -269,3 +269,14 @@ config USB_TEST
See <http://www.linux-usb.org/usbtest/> for more information,
including sample test device firmware and "how to use it".
+config USB_ISIGHTFW
+ tristate "iSight firmware loading support"
+ depends on USB
+ help
+ This driver loads firmware for USB Apple iSight cameras, allowing
+ them to be driven by the USB video class driver available at
+ http://linux-uvc.berlios.de
+
+ The firmware for this driver must be extracted from the MacOS
+ driver beforehand. Tools for doing so are available at
+ http://bersace03.free.fr
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index b68e6b774f1a..aba091cb5ec0 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_USB_EMI62) += emi62.o
obj-$(CONFIG_USB_FTDI_ELAN) += ftdi-elan.o
obj-$(CONFIG_USB_IDMOUSE) += idmouse.o
obj-$(CONFIG_USB_IOWARRIOR) += iowarrior.o
+obj-$(CONFIG_USB_ISIGHTFW) += isight_firmware.o
obj-$(CONFIG_USB_LCD) += usblcd.o
obj-$(CONFIG_USB_LD) += ldusb.o
obj-$(CONFIG_USB_LED) += usbled.o
diff --git a/drivers/usb/misc/isight_firmware.c b/drivers/usb/misc/isight_firmware.c
new file mode 100644
index 000000000000..390e04885536
--- /dev/null
+++ b/drivers/usb/misc/isight_firmware.c
@@ -0,0 +1,131 @@
+/*
+ * Driver for loading USB isight firmware
+ *
+ * Copyright (C) 2008 Matthew Garrett <mjg@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, version 2.
+ *
+ * The USB isight cameras in recent Apples are roughly compatible with the USB
+ * video class specification, and can be driven by uvcvideo. However, they
+ * need firmware to be loaded beforehand. After firmware loading, the device
+ * detaches from the USB bus and reattaches with a new device ID. It can then
+ * be claimed by the uvc driver.
+ *
+ * The firmware is non-free and must be extracted by the user. Tools to do this
+ * are available at http://bersace03.free.fr/ift/
+ *
+ * The isight firmware loading was reverse engineered by Johannes Berg
+ * <johannes@sipsolutions.de>, and this driver is based on code by Ronald
+ * Bultje <rbultje@ronald.bitfreak.net>
+ */
+
+#include <linux/usb.h>
+#include <linux/firmware.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+
+static struct usb_device_id id_table[] = {
+ {USB_DEVICE(0x05ac, 0x8300)},
+ {},
+};
+
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static int isight_firmware_load(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *dev = interface_to_usbdev(intf);
+ int llen, len, req, ret = 0;
+ const struct firmware *firmware;
+ unsigned char *buf;
+ unsigned char data[4];
+ char *ptr;
+
+ if (request_firmware(&firmware, "isight.fw", &dev->dev) != 0) {
+ printk(KERN_ERR "Unable to load isight firmware\n");
+ return -ENODEV;
+ }
+
+ ptr = firmware->data;
+
+ if (usb_control_msg
+ (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\1", 1,
+ 300) != 1) {
+ printk(KERN_ERR
+ "Failed to initialise isight firmware loader\n");
+ ret = -ENODEV;
+ goto out;
+ }
+
+ while (1) {
+ memcpy(data, ptr, 4);
+ len = (data[0] << 8 | data[1]);
+ req = (data[2] << 8 | data[3]);
+ ptr += 4;
+
+ if (len == 0x8001)
+ break; /* success */
+ else if (len == 0)
+ continue;
+
+ for (; len > 0; req += 50) {
+ llen = len > 50 ? 50 : len;
+ len -= llen;
+
+ buf = kmalloc(llen, GFP_KERNEL);
+ memcpy(buf, ptr, llen);
+
+ ptr += llen;
+
+ if (usb_control_msg
+ (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, req, 0,
+ buf, llen, 300) != llen) {
+ printk(KERN_ERR
+ "Failed to load isight firmware\n");
+ kfree(buf);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ kfree(buf);
+ }
+ }
+ if (usb_control_msg
+ (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\0", 1,
+ 300) != 1) {
+ printk(KERN_ERR "isight firmware loading completion failed\n");
+ ret = -ENODEV;
+ }
+out:
+ release_firmware(firmware);
+ return ret;
+}
+
+static void isight_firmware_disconnect(struct usb_interface *intf)
+{
+}
+
+static struct usb_driver isight_firmware_driver = {
+ .name = "isight_firmware",
+ .probe = isight_firmware_load,
+ .disconnect = isight_firmware_disconnect,
+ .id_table = id_table,
+};
+
+static int __init isight_firmware_init(void)
+{
+ return usb_register(&isight_firmware_driver);
+}
+
+static void __exit isight_firmware_exit(void)
+{
+ usb_deregister(&isight_firmware_driver);
+}
+
+module_init(isight_firmware_init);
+module_exit(isight_firmware_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 3cee6feac174..5234e7a3bd2c 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -174,8 +174,270 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) },
- { USB_DEVICE(MTXORB_VK_VID, MTXORB_VK_PID),
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0100_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0101_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0102_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0103_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0104_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0105_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0106_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0107_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0108_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0109_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010A_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010B_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010C_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010D_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010E_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010F_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0110_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0111_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0112_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0113_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0114_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0115_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0116_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0117_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0118_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0119_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011A_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011B_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011C_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011D_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011E_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011F_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0120_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0121_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0122_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0123_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0124_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0125_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0126_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0127_PID),
.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0128_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0129_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012A_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012B_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012C_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012D_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012E_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012F_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0130_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0131_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0132_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0133_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0134_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0135_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0136_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0137_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0138_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0139_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013A_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013B_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013C_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013D_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013E_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013F_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0140_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0141_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0142_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0143_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0144_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0145_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0146_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0147_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0148_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0149_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014A_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014B_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014C_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014D_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014E_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014F_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0150_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0151_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0152_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0153_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0154_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0155_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0156_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0157_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0158_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0159_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015A_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015B_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015C_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015D_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015E_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015F_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0160_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0161_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0162_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0163_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0164_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0165_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0166_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0167_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0168_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0169_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016A_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016B_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016C_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016D_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016E_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016F_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0170_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0171_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0172_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0173_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0174_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0175_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0176_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0177_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0178_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0179_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017A_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017B_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017C_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017D_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017E_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017F_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0180_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0181_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0182_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0183_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0184_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0185_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0186_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0187_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0188_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0189_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018A_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018B_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018C_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018D_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018E_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018F_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0190_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0191_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0192_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0193_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0194_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0195_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0196_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0197_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0198_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0199_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019A_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019B_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019C_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019D_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019E_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019F_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A0_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A1_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A2_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A3_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A4_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A5_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A6_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A7_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A8_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A9_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AA_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AB_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AC_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AD_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AE_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AF_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B0_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B1_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B2_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B3_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B4_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B5_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B6_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B7_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B8_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B9_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BA_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BB_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BC_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BD_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BE_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BF_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C0_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C1_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C2_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C3_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C4_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C5_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C6_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C7_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C8_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C9_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CA_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CB_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CC_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CD_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CE_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CF_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D0_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D1_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D2_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D3_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D4_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D5_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D6_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D7_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D8_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D9_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DA_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DB_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DC_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DD_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DE_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DF_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E0_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E1_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E2_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E3_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E4_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E5_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E6_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E7_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E8_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E9_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EA_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EB_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EC_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01ED_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EE_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EF_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F0_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F1_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F2_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F3_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F4_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F5_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F6_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F7_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F8_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F9_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FA_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FB_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FC_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FD_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FE_PID) },
+ { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FF_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) },
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index a72f2c81d664..06e0ecabb3eb 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -114,11 +114,268 @@
#define FTDI_OOCDLINK_PID 0xbaf8 /* Amontec JTAGkey */
/*
- * The following are the values for the Matrix Orbital VK204-25-USB
- * display, which use the FT232RL.
- */
-#define MTXORB_VK_VID 0x1b3d
-#define MTXORB_VK_PID 0x0158
+ * The following are the values for the Matrix Orbital FTDI Range
+ * Anything in this range will use an FT232RL.
+ */
+#define MTXORB_VID 0x1B3D
+#define MTXORB_FTDI_RANGE_0100_PID 0x0100
+#define MTXORB_FTDI_RANGE_0101_PID 0x0101
+#define MTXORB_FTDI_RANGE_0102_PID 0x0102
+#define MTXORB_FTDI_RANGE_0103_PID 0x0103
+#define MTXORB_FTDI_RANGE_0104_PID 0x0104
+#define MTXORB_FTDI_RANGE_0105_PID 0x0105
+#define MTXORB_FTDI_RANGE_0106_PID 0x0106
+#define MTXORB_FTDI_RANGE_0107_PID 0x0107
+#define MTXORB_FTDI_RANGE_0108_PID 0x0108
+#define MTXORB_FTDI_RANGE_0109_PID 0x0109
+#define MTXORB_FTDI_RANGE_010A_PID 0x010A
+#define MTXORB_FTDI_RANGE_010B_PID 0x010B
+#define MTXORB_FTDI_RANGE_010C_PID 0x010C
+#define MTXORB_FTDI_RANGE_010D_PID 0x010D
+#define MTXORB_FTDI_RANGE_010E_PID 0x010E
+#define MTXORB_FTDI_RANGE_010F_PID 0x010F
+#define MTXORB_FTDI_RANGE_0110_PID 0x0110
+#define MTXORB_FTDI_RANGE_0111_PID 0x0111
+#define MTXORB_FTDI_RANGE_0112_PID 0x0112
+#define MTXORB_FTDI_RANGE_0113_PID 0x0113
+#define MTXORB_FTDI_RANGE_0114_PID 0x0114
+#define MTXORB_FTDI_RANGE_0115_PID 0x0115
+#define MTXORB_FTDI_RANGE_0116_PID 0x0116
+#define MTXORB_FTDI_RANGE_0117_PID 0x0117
+#define MTXORB_FTDI_RANGE_0118_PID 0x0118
+#define MTXORB_FTDI_RANGE_0119_PID 0x0119
+#define MTXORB_FTDI_RANGE_011A_PID 0x011A
+#define MTXORB_FTDI_RANGE_011B_PID 0x011B
+#define MTXORB_FTDI_RANGE_011C_PID 0x011C
+#define MTXORB_FTDI_RANGE_011D_PID 0x011D
+#define MTXORB_FTDI_RANGE_011E_PID 0x011E
+#define MTXORB_FTDI_RANGE_011F_PID 0x011F
+#define MTXORB_FTDI_RANGE_0120_PID 0x0120
+#define MTXORB_FTDI_RANGE_0121_PID 0x0121
+#define MTXORB_FTDI_RANGE_0122_PID 0x0122
+#define MTXORB_FTDI_RANGE_0123_PID 0x0123
+#define MTXORB_FTDI_RANGE_0124_PID 0x0124
+#define MTXORB_FTDI_RANGE_0125_PID 0x0125
+#define MTXORB_FTDI_RANGE_0126_PID 0x0126
+#define MTXORB_FTDI_RANGE_0127_PID 0x0127
+#define MTXORB_FTDI_RANGE_0128_PID 0x0128
+#define MTXORB_FTDI_RANGE_0129_PID 0x0129
+#define MTXORB_FTDI_RANGE_012A_PID 0x012A
+#define MTXORB_FTDI_RANGE_012B_PID 0x012B
+#define MTXORB_FTDI_RANGE_012C_PID 0x012C
+#define MTXORB_FTDI_RANGE_012D_PID 0x012D
+#define MTXORB_FTDI_RANGE_012E_PID 0x012E
+#define MTXORB_FTDI_RANGE_012F_PID 0x012F
+#define MTXORB_FTDI_RANGE_0130_PID 0x0130
+#define MTXORB_FTDI_RANGE_0131_PID 0x0131
+#define MTXORB_FTDI_RANGE_0132_PID 0x0132
+#define MTXORB_FTDI_RANGE_0133_PID 0x0133
+#define MTXORB_FTDI_RANGE_0134_PID 0x0134
+#define MTXORB_FTDI_RANGE_0135_PID 0x0135
+#define MTXORB_FTDI_RANGE_0136_PID 0x0136
+#define MTXORB_FTDI_RANGE_0137_PID 0x0137
+#define MTXORB_FTDI_RANGE_0138_PID 0x0138
+#define MTXORB_FTDI_RANGE_0139_PID 0x0139
+#define MTXORB_FTDI_RANGE_013A_PID 0x013A
+#define MTXORB_FTDI_RANGE_013B_PID 0x013B
+#define MTXORB_FTDI_RANGE_013C_PID 0x013C
+#define MTXORB_FTDI_RANGE_013D_PID 0x013D
+#define MTXORB_FTDI_RANGE_013E_PID 0x013E
+#define MTXORB_FTDI_RANGE_013F_PID 0x013F
+#define MTXORB_FTDI_RANGE_0140_PID 0x0140
+#define MTXORB_FTDI_RANGE_0141_PID 0x0141
+#define MTXORB_FTDI_RANGE_0142_PID 0x0142
+#define MTXORB_FTDI_RANGE_0143_PID 0x0143
+#define MTXORB_FTDI_RANGE_0144_PID 0x0144
+#define MTXORB_FTDI_RANGE_0145_PID 0x0145
+#define MTXORB_FTDI_RANGE_0146_PID 0x0146
+#define MTXORB_FTDI_RANGE_0147_PID 0x0147
+#define MTXORB_FTDI_RANGE_0148_PID 0x0148
+#define MTXORB_FTDI_RANGE_0149_PID 0x0149
+#define MTXORB_FTDI_RANGE_014A_PID 0x014A
+#define MTXORB_FTDI_RANGE_014B_PID 0x014B
+#define MTXORB_FTDI_RANGE_014C_PID 0x014C
+#define MTXORB_FTDI_RANGE_014D_PID 0x014D
+#define MTXORB_FTDI_RANGE_014E_PID 0x014E
+#define MTXORB_FTDI_RANGE_014F_PID 0x014F
+#define MTXORB_FTDI_RANGE_0150_PID 0x0150
+#define MTXORB_FTDI_RANGE_0151_PID 0x0151
+#define MTXORB_FTDI_RANGE_0152_PID 0x0152
+#define MTXORB_FTDI_RANGE_0153_PID 0x0153
+#define MTXORB_FTDI_RANGE_0154_PID 0x0154
+#define MTXORB_FTDI_RANGE_0155_PID 0x0155
+#define MTXORB_FTDI_RANGE_0156_PID 0x0156
+#define MTXORB_FTDI_RANGE_0157_PID 0x0157
+#define MTXORB_FTDI_RANGE_0158_PID 0x0158
+#define MTXORB_FTDI_RANGE_0159_PID 0x0159
+#define MTXORB_FTDI_RANGE_015A_PID 0x015A
+#define MTXORB_FTDI_RANGE_015B_PID 0x015B
+#define MTXORB_FTDI_RANGE_015C_PID 0x015C
+#define MTXORB_FTDI_RANGE_015D_PID 0x015D
+#define MTXORB_FTDI_RANGE_015E_PID 0x015E
+#define MTXORB_FTDI_RANGE_015F_PID 0x015F
+#define MTXORB_FTDI_RANGE_0160_PID 0x0160
+#define MTXORB_FTDI_RANGE_0161_PID 0x0161
+#define MTXORB_FTDI_RANGE_0162_PID 0x0162
+#define MTXORB_FTDI_RANGE_0163_PID 0x0163
+#define MTXORB_FTDI_RANGE_0164_PID 0x0164
+#define MTXORB_FTDI_RANGE_0165_PID 0x0165
+#define MTXORB_FTDI_RANGE_0166_PID 0x0166
+#define MTXORB_FTDI_RANGE_0167_PID 0x0167
+#define MTXORB_FTDI_RANGE_0168_PID 0x0168
+#define MTXORB_FTDI_RANGE_0169_PID 0x0169
+#define MTXORB_FTDI_RANGE_016A_PID 0x016A
+#define MTXORB_FTDI_RANGE_016B_PID 0x016B
+#define MTXORB_FTDI_RANGE_016C_PID 0x016C
+#define MTXORB_FTDI_RANGE_016D_PID 0x016D
+#define MTXORB_FTDI_RANGE_016E_PID 0x016E
+#define MTXORB_FTDI_RANGE_016F_PID 0x016F
+#define MTXORB_FTDI_RANGE_0170_PID 0x0170
+#define MTXORB_FTDI_RANGE_0171_PID 0x0171
+#define MTXORB_FTDI_RANGE_0172_PID 0x0172
+#define MTXORB_FTDI_RANGE_0173_PID 0x0173
+#define MTXORB_FTDI_RANGE_0174_PID 0x0174
+#define MTXORB_FTDI_RANGE_0175_PID 0x0175
+#define MTXORB_FTDI_RANGE_0176_PID 0x0176
+#define MTXORB_FTDI_RANGE_0177_PID 0x0177
+#define MTXORB_FTDI_RANGE_0178_PID 0x0178
+#define MTXORB_FTDI_RANGE_0179_PID 0x0179
+#define MTXORB_FTDI_RANGE_017A_PID 0x017A
+#define MTXORB_FTDI_RANGE_017B_PID 0x017B
+#define MTXORB_FTDI_RANGE_017C_PID 0x017C
+#define MTXORB_FTDI_RANGE_017D_PID 0x017D
+#define MTXORB_FTDI_RANGE_017E_PID 0x017E
+#define MTXORB_FTDI_RANGE_017F_PID 0x017F
+#define MTXORB_FTDI_RANGE_0180_PID 0x0180
+#define MTXORB_FTDI_RANGE_0181_PID 0x0181
+#define MTXORB_FTDI_RANGE_0182_PID 0x0182
+#define MTXORB_FTDI_RANGE_0183_PID 0x0183
+#define MTXORB_FTDI_RANGE_0184_PID 0x0184
+#define MTXORB_FTDI_RANGE_0185_PID 0x0185
+#define MTXORB_FTDI_RANGE_0186_PID 0x0186
+#define MTXORB_FTDI_RANGE_0187_PID 0x0187
+#define MTXORB_FTDI_RANGE_0188_PID 0x0188
+#define MTXORB_FTDI_RANGE_0189_PID 0x0189
+#define MTXORB_FTDI_RANGE_018A_PID 0x018A
+#define MTXORB_FTDI_RANGE_018B_PID 0x018B
+#define MTXORB_FTDI_RANGE_018C_PID 0x018C
+#define MTXORB_FTDI_RANGE_018D_PID 0x018D
+#define MTXORB_FTDI_RANGE_018E_PID 0x018E
+#define MTXORB_FTDI_RANGE_018F_PID 0x018F
+#define MTXORB_FTDI_RANGE_0190_PID 0x0190
+#define MTXORB_FTDI_RANGE_0191_PID 0x0191
+#define MTXORB_FTDI_RANGE_0192_PID 0x0192
+#define MTXORB_FTDI_RANGE_0193_PID 0x0193
+#define MTXORB_FTDI_RANGE_0194_PID 0x0194
+#define MTXORB_FTDI_RANGE_0195_PID 0x0195
+#define MTXORB_FTDI_RANGE_0196_PID 0x0196
+#define MTXORB_FTDI_RANGE_0197_PID 0x0197
+#define MTXORB_FTDI_RANGE_0198_PID 0x0198
+#define MTXORB_FTDI_RANGE_0199_PID 0x0199
+#define MTXORB_FTDI_RANGE_019A_PID 0x019A
+#define MTXORB_FTDI_RANGE_019B_PID 0x019B
+#define MTXORB_FTDI_RANGE_019C_PID 0x019C
+#define MTXORB_FTDI_RANGE_019D_PID 0x019D
+#define MTXORB_FTDI_RANGE_019E_PID 0x019E
+#define MTXORB_FTDI_RANGE_019F_PID 0x019F
+#define MTXORB_FTDI_RANGE_01A0_PID 0x01A0
+#define MTXORB_FTDI_RANGE_01A1_PID 0x01A1
+#define MTXORB_FTDI_RANGE_01A2_PID 0x01A2
+#define MTXORB_FTDI_RANGE_01A3_PID 0x01A3
+#define MTXORB_FTDI_RANGE_01A4_PID 0x01A4
+#define MTXORB_FTDI_RANGE_01A5_PID 0x01A5
+#define MTXORB_FTDI_RANGE_01A6_PID 0x01A6
+#define MTXORB_FTDI_RANGE_01A7_PID 0x01A7
+#define MTXORB_FTDI_RANGE_01A8_PID 0x01A8
+#define MTXORB_FTDI_RANGE_01A9_PID 0x01A9
+#define MTXORB_FTDI_RANGE_01AA_PID 0x01AA
+#define MTXORB_FTDI_RANGE_01AB_PID 0x01AB
+#define MTXORB_FTDI_RANGE_01AC_PID 0x01AC
+#define MTXORB_FTDI_RANGE_01AD_PID 0x01AD
+#define MTXORB_FTDI_RANGE_01AE_PID 0x01AE
+#define MTXORB_FTDI_RANGE_01AF_PID 0x01AF
+#define MTXORB_FTDI_RANGE_01B0_PID 0x01B0
+#define MTXORB_FTDI_RANGE_01B1_PID 0x01B1
+#define MTXORB_FTDI_RANGE_01B2_PID 0x01B2
+#define MTXORB_FTDI_RANGE_01B3_PID 0x01B3
+#define MTXORB_FTDI_RANGE_01B4_PID 0x01B4
+#define MTXORB_FTDI_RANGE_01B5_PID 0x01B5
+#define MTXORB_FTDI_RANGE_01B6_PID 0x01B6
+#define MTXORB_FTDI_RANGE_01B7_PID 0x01B7
+#define MTXORB_FTDI_RANGE_01B8_PID 0x01B8
+#define MTXORB_FTDI_RANGE_01B9_PID 0x01B9
+#define MTXORB_FTDI_RANGE_01BA_PID 0x01BA
+#define MTXORB_FTDI_RANGE_01BB_PID 0x01BB
+#define MTXORB_FTDI_RANGE_01BC_PID 0x01BC
+#define MTXORB_FTDI_RANGE_01BD_PID 0x01BD
+#define MTXORB_FTDI_RANGE_01BE_PID 0x01BE
+#define MTXORB_FTDI_RANGE_01BF_PID 0x01BF
+#define MTXORB_FTDI_RANGE_01C0_PID 0x01C0
+#define MTXORB_FTDI_RANGE_01C1_PID 0x01C1
+#define MTXORB_FTDI_RANGE_01C2_PID 0x01C2
+#define MTXORB_FTDI_RANGE_01C3_PID 0x01C3
+#define MTXORB_FTDI_RANGE_01C4_PID 0x01C4
+#define MTXORB_FTDI_RANGE_01C5_PID 0x01C5
+#define MTXORB_FTDI_RANGE_01C6_PID 0x01C6
+#define MTXORB_FTDI_RANGE_01C7_PID 0x01C7
+#define MTXORB_FTDI_RANGE_01C8_PID 0x01C8
+#define MTXORB_FTDI_RANGE_01C9_PID 0x01C9
+#define MTXORB_FTDI_RANGE_01CA_PID 0x01CA
+#define MTXORB_FTDI_RANGE_01CB_PID 0x01CB
+#define MTXORB_FTDI_RANGE_01CC_PID 0x01CC
+#define MTXORB_FTDI_RANGE_01CD_PID 0x01CD
+#define MTXORB_FTDI_RANGE_01CE_PID 0x01CE
+#define MTXORB_FTDI_RANGE_01CF_PID 0x01CF
+#define MTXORB_FTDI_RANGE_01D0_PID 0x01D0
+#define MTXORB_FTDI_RANGE_01D1_PID 0x01D1
+#define MTXORB_FTDI_RANGE_01D2_PID 0x01D2
+#define MTXORB_FTDI_RANGE_01D3_PID 0x01D3
+#define MTXORB_FTDI_RANGE_01D4_PID 0x01D4
+#define MTXORB_FTDI_RANGE_01D5_PID 0x01D5
+#define MTXORB_FTDI_RANGE_01D6_PID 0x01D6
+#define MTXORB_FTDI_RANGE_01D7_PID 0x01D7
+#define MTXORB_FTDI_RANGE_01D8_PID 0x01D8
+#define MTXORB_FTDI_RANGE_01D9_PID 0x01D9
+#define MTXORB_FTDI_RANGE_01DA_PID 0x01DA
+#define MTXORB_FTDI_RANGE_01DB_PID 0x01DB
+#define MTXORB_FTDI_RANGE_01DC_PID 0x01DC
+#define MTXORB_FTDI_RANGE_01DD_PID 0x01DD
+#define MTXORB_FTDI_RANGE_01DE_PID 0x01DE
+#define MTXORB_FTDI_RANGE_01DF_PID 0x01DF
+#define MTXORB_FTDI_RANGE_01E0_PID 0x01E0
+#define MTXORB_FTDI_RANGE_01E1_PID 0x01E1
+#define MTXORB_FTDI_RANGE_01E2_PID 0x01E2
+#define MTXORB_FTDI_RANGE_01E3_PID 0x01E3
+#define MTXORB_FTDI_RANGE_01E4_PID 0x01E4
+#define MTXORB_FTDI_RANGE_01E5_PID 0x01E5
+#define MTXORB_FTDI_RANGE_01E6_PID 0x01E6
+#define MTXORB_FTDI_RANGE_01E7_PID 0x01E7
+#define MTXORB_FTDI_RANGE_01E8_PID 0x01E8
+#define MTXORB_FTDI_RANGE_01E9_PID 0x01E9
+#define MTXORB_FTDI_RANGE_01EA_PID 0x01EA
+#define MTXORB_FTDI_RANGE_01EB_PID 0x01EB
+#define MTXORB_FTDI_RANGE_01EC_PID 0x01EC
+#define MTXORB_FTDI_RANGE_01ED_PID 0x01ED
+#define MTXORB_FTDI_RANGE_01EE_PID 0x01EE
+#define MTXORB_FTDI_RANGE_01EF_PID 0x01EF
+#define MTXORB_FTDI_RANGE_01F0_PID 0x01F0
+#define MTXORB_FTDI_RANGE_01F1_PID 0x01F1
+#define MTXORB_FTDI_RANGE_01F2_PID 0x01F2
+#define MTXORB_FTDI_RANGE_01F3_PID 0x01F3
+#define MTXORB_FTDI_RANGE_01F4_PID 0x01F4
+#define MTXORB_FTDI_RANGE_01F5_PID 0x01F5
+#define MTXORB_FTDI_RANGE_01F6_PID 0x01F6
+#define MTXORB_FTDI_RANGE_01F7_PID 0x01F7
+#define MTXORB_FTDI_RANGE_01F8_PID 0x01F8
+#define MTXORB_FTDI_RANGE_01F9_PID 0x01F9
+#define MTXORB_FTDI_RANGE_01FA_PID 0x01FA
+#define MTXORB_FTDI_RANGE_01FB_PID 0x01FB
+#define MTXORB_FTDI_RANGE_01FC_PID 0x01FC
+#define MTXORB_FTDI_RANGE_01FD_PID 0x01FD
+#define MTXORB_FTDI_RANGE_01FE_PID 0x01FE
+#define MTXORB_FTDI_RANGE_01FF_PID 0x01FF
+
+
/* Interbiometrics USB I/O Board */
/* Developed for Interbiometrics by Rudolf Gugler */
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 6cecd2c12b1d..43cfde83a93b 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -236,25 +236,25 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_EX) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_NETWORK) },
- { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) },
- { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401) },
- { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403) },
- { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1405) },
- { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1406) },
- { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1408) },
- { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1409) },
- { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1410) },
- { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1411) },
- { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1412) },
- { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1413) },
- { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1414) },
- { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1415) },
- { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1416) },
- { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417) },
- { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418) },
- { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1405, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1406, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1408, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1409, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1410, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1411, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1412, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1413, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1414, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1415, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1416, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419, 0xff, 0xff, 0xff) },
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_9508) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 234c5eea95a2..103195abd417 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -56,6 +56,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) },
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) },
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ALDIGA) },
+ { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MMX) },
{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
{ USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index 3bdefe020501..cff160abb130 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -14,6 +14,7 @@
#define PL2303_PRODUCT_ID_PHAROS 0xaaa0
#define PL2303_PRODUCT_ID_RSAQ3 0xaaa2
#define PL2303_PRODUCT_ID_ALDIGA 0x0611
+#define PL2303_PRODUCT_ID_MMX 0x0612
#define ATEN_VENDOR_ID 0x0557
#define ATEN_VENDOR_ID2 0x0547
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 1b09578cbb10..45fe3663fa7f 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -405,7 +405,7 @@ UNUSUAL_DEV( 0x04a5, 0x3010, 0x0100, 0x0100,
UNUSUAL_DEV( 0x04b4, 0x6830, 0x0000, 0x9999,
"Cypress",
"Cypress AT2LP",
- US_SC_CYP_ATACB, US_PR_BULK, NULL,
+ US_SC_CYP_ATACB, US_PR_DEVICE, NULL,
0),
#endif
@@ -1522,7 +1522,7 @@ UNUSUAL_DEV( 0x0fce, 0xe031, 0x0000, 0x0000,
"Sony Ericsson",
"M600i",
US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_FIX_CAPACITY ),
+ US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
/* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu>
* Tested on hardware version 1.10.
@@ -1716,10 +1716,12 @@ UNUSUAL_DEV( 0x22b8, 0x3010, 0x0001, 0x0001,
/*
* Patch by Pete Zaitcev <zaitcev@redhat.com>
* Report by Mark Patton. Red Hat bz#208928.
+ * Added support for rev 0x0002 (Motorola ROKR W5)
+ * by Javier Smaldone <javier@smaldone.com.ar>
*/
-UNUSUAL_DEV( 0x22b8, 0x4810, 0x0001, 0x0001,
+UNUSUAL_DEV( 0x22b8, 0x4810, 0x0001, 0x0002,
"Motorola",
- "RAZR V3i",
+ "RAZR V3i/ROKR W5",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY),
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index e4bcf5376a99..bd4ac0bafecb 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -3356,7 +3356,7 @@ static int __devinit atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *i
info->fix.mmio_start = raddr;
par->ati_regbase = ioremap(info->fix.mmio_start, 0x1000);
- if (par->ati_regbase == 0)
+ if (par->ati_regbase == NULL)
return -ENOMEM;
info->fix.mmio_start += par->aux_start ? 0x400 : 0xc00;
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 72cd0d2f14ec..400e9264e456 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -2277,8 +2277,8 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
do {
rinfo->fb_base = ioremap (rinfo->fb_base_phys,
rinfo->mapped_vram);
- } while ( rinfo->fb_base == 0 &&
- ((rinfo->mapped_vram /=2) >= MIN_MAPPED_VRAM) );
+ } while (rinfo->fb_base == NULL &&
+ ((rinfo->mapped_vram /= 2) >= MIN_MAPPED_VRAM));
if (rinfo->fb_base == NULL) {
printk (KERN_ERR "radeonfb (%s): cannot map FB\n",
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 5fa8b76673cb..97aff8db10bf 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -2275,9 +2275,7 @@ static int fbcon_switch(struct vc_data *vc)
* in fb_set_var()
*/
info->var.activate = var.activate;
- var.yoffset = info->var.yoffset;
- var.xoffset = info->var.xoffset;
- var.vmode = info->var.vmode;
+ var.vmode |= info->var.vmode & ~FB_VMODE_MASK;
fb_set_var(info, &var);
ops->var = info->var;
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
index f3107ad7e545..95883236c0cd 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/matrox/matroxfb_base.h
@@ -200,7 +200,7 @@ static inline int mga_ioremap(unsigned long phys, unsigned long size, int flags,
virt->vaddr = ioremap_nocache(phys, size);
else
virt->vaddr = ioremap(phys, size);
- return (virt->vaddr == 0); /* 0, !0... 0, error_code in future */
+ return (virt->vaddr == NULL); /* 0, !0... 0, error_code in future */
}
static inline void mga_iounmap(vaddr_t va) {
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index 473562191586..d3c3af53a290 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -28,6 +28,7 @@
#endif
const char *fb_mode_option;
+EXPORT_SYMBOL_GPL(fb_mode_option);
/*
* Standard video mode definitions (taken from XFree86)
@@ -590,6 +591,7 @@ done:
"", (margins) ? " with margins" : "", (interlace) ?
" interlaced" : "");
+ memset(&cvt_mode, 0, sizeof(cvt_mode));
cvt_mode.xres = xres;
cvt_mode.yres = yres;
cvt_mode.refresh = (refresh) ? refresh : 60;
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 3ee314beacc1..274bc93ab7d8 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -1351,7 +1351,6 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
struct pxafb_info *fbi;
void *addr;
struct pxafb_mach_info *inf = dev->platform_data;
- struct pxafb_mode_info *mode = inf->modes;
/* Alloc the pxafb_info and pseudo_palette in one step */
fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 16, GFP_KERNEL);
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index 13b38cbbe4cf..f0598961c6b0 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -1,75 +1,15 @@
-/*
- * linux/drivers/video/s3c2410fb.c
- * Copyright (c) Arnaud Patard, Ben Dooks
+/* linux/drivers/video/s3c2410fb.c
+ * Copyright (c) 2004,2005 Arnaud Patard
+ * Copyright (c) 2004-2008 Ben Dooks
+ *
+ * S3C2410 LCD Framebuffer Driver
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*
- * S3C2410 LCD Controller Frame Buffer Driver
- * based on skeletonfb.c, sa1100fb.c and others
- *
- * ChangeLog
- * 2005-04-07: Arnaud Patard <arnaud.patard@rtp-net.org>
- * - u32 state -> pm_message_t state
- * - S3C2410_{VA,SZ}_LCD -> S3C24XX
- *
- * 2005-03-15: Arnaud Patard <arnaud.patard@rtp-net.org>
- * - Removed the ioctl
- * - use readl/writel instead of __raw_writel/__raw_readl
- *
- * 2004-12-04: Arnaud Patard <arnaud.patard@rtp-net.org>
- * - Added the possibility to set on or off the
- * debugging messages
- * - Replaced 0 and 1 by on or off when reading the
- * /sys files
- *
- * 2005-03-23: Ben Dooks <ben-linux@fluff.org>
- * - added non 16bpp modes
- * - updated platform information for range of x/y/bpp
- * - add code to ensure palette is written correctly
- * - add pixel clock divisor control
- *
- * 2004-11-11: Arnaud Patard <arnaud.patard@rtp-net.org>
- * - Removed the use of currcon as it no more exists
- * - Added LCD power sysfs interface
- *
- * 2004-11-03: Ben Dooks <ben-linux@fluff.org>
- * - minor cleanups
- * - add suspend/resume support
- * - s3c2410fb_setcolreg() not valid in >8bpp modes
- * - removed last CONFIG_FB_S3C2410_FIXED
- * - ensure lcd controller stopped before cleanup
- * - added sysfs interface for backlight power
- * - added mask for gpio configuration
- * - ensured IRQs disabled during GPIO configuration
- * - disable TPAL before enabling video
- *
- * 2004-09-20: Arnaud Patard <arnaud.patard@rtp-net.org>
- * - Suppress command line options
- *
- * 2004-09-15: Arnaud Patard <arnaud.patard@rtp-net.org>
- * - code cleanup
- *
- * 2004-09-07: Arnaud Patard <arnaud.patard@rtp-net.org>
- * - Renamed from h1940fb.c to s3c2410fb.c
- * - Add support for different devices
- * - Backlight support
- *
- * 2004-09-05: Herbert Pötzl <herbert@13thfloor.at>
- * - added clock (de-)allocation code
- * - added fixem fbmem option
- *
- * 2004-07-27: Arnaud Patard <arnaud.patard@rtp-net.org>
- * - code cleanup
- * - added a forgotten return in h1940fb_init
- *
- * 2004-07-19: Herbert Pötzl <herbert@13thfloor.at>
- * - code cleanup and extended debugging
- *
- * 2004-07-15: Arnaud Patard <arnaud.patard@rtp-net.org>
- * - First version
- */
+ * Driver based on skeletonfb.c, sa1100fb.c and others.
+*/
#include <linux/module.h>
#include <linux/kernel.h>
@@ -580,6 +520,27 @@ static int s3c2410fb_setcolreg(unsigned regno,
return 0;
}
+/* s3c2410fb_lcd_enable
+ *
+ * shutdown the lcd controller
+ */
+static void s3c2410fb_lcd_enable(struct s3c2410fb_info *fbi, int enable)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ if (enable)
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID;
+ else
+ fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID;
+
+ writel(fbi->regs.lcdcon1, fbi->io + S3C2410_LCDCON1);
+
+ local_irq_restore(flags);
+}
+
+
/*
* s3c2410fb_blank
* @blank_mode: the blank mode we want.
@@ -589,9 +550,6 @@ static int s3c2410fb_setcolreg(unsigned regno,
* blanking succeeded, != 0 if un-/blanking failed due to e.g. a
* video mode which doesn't support it. Implements VESA suspend
* and powerdown modes on hardware that supports disabling hsync/vsync:
- * blank_mode == 2: suspend vsync
- * blank_mode == 3: suspend hsync
- * blank_mode == 4: powerdown
*
* Returns negative errno on error, or zero on success.
*
@@ -605,6 +563,12 @@ static int s3c2410fb_blank(int blank_mode, struct fb_info *info)
tpal_reg += is_s3c2412(fbi) ? S3C2412_TPAL : S3C2410_TPAL;
+ if (blank_mode == FB_BLANK_POWERDOWN) {
+ s3c2410fb_lcd_enable(fbi, 0);
+ } else {
+ s3c2410fb_lcd_enable(fbi, 1);
+ }
+
if (blank_mode == FB_BLANK_UNBLANK)
writel(0x0, tpal_reg);
else {
@@ -948,7 +912,10 @@ static int __init s3c24xxfb_probe(struct platform_device *pdev,
}
/* create device files */
- device_create_file(&pdev->dev, &dev_attr_debug);
+ ret = device_create_file(&pdev->dev, &dev_attr_debug);
+ if (ret) {
+ printk(KERN_ERR "failed to add debug attribute\n");
+ }
printk(KERN_INFO "fb%d: %s frame buffer device\n",
fbinfo->node, fbinfo->fix.id);
@@ -983,21 +950,6 @@ static int __init s3c2412fb_probe(struct platform_device *pdev)
return s3c24xxfb_probe(pdev, DRV_S3C2412);
}
-/* s3c2410fb_stop_lcd
- *
- * shutdown the lcd controller
- */
-static void s3c2410fb_stop_lcd(struct s3c2410fb_info *fbi)
-{
- unsigned long flags;
-
- local_irq_save(flags);
-
- fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID;
- writel(fbi->regs.lcdcon1, fbi->io + S3C2410_LCDCON1);
-
- local_irq_restore(flags);
-}
/*
* Cleanup
@@ -1010,7 +962,7 @@ static int s3c2410fb_remove(struct platform_device *pdev)
unregister_framebuffer(fbinfo);
- s3c2410fb_stop_lcd(info);
+ s3c2410fb_lcd_enable(info, 0);
msleep(1);
s3c2410fb_unmap_video_memory(fbinfo);
@@ -1043,7 +995,7 @@ static int s3c2410fb_suspend(struct platform_device *dev, pm_message_t state)
struct fb_info *fbinfo = platform_get_drvdata(dev);
struct s3c2410fb_info *info = fbinfo->par;
- s3c2410fb_stop_lcd(info);
+ s3c2410fb_lcd_enable(info, 0);
/* sleep before disabling the clock, we need to ensure
* the LCD DMA engine is not going to get back on the bus
@@ -1118,3 +1070,5 @@ MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>, "
"Ben Dooks <ben-linux@fluff.org>");
MODULE_DESCRIPTION("Framebuffer driver for the s3c2410");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:s3c2410-lcd");
+MODULE_ALIAS("platform:s3c2412-lcd");
diff --git a/drivers/video/s3c2410fb.h b/drivers/video/s3c2410fb.h
index dbb73b95e2ef..9a6ba3e9d1b8 100644
--- a/drivers/video/s3c2410fb.h
+++ b/drivers/video/s3c2410fb.h
@@ -1,26 +1,14 @@
/*
* linux/drivers/video/s3c2410fb.h
- * Copyright (c) Arnaud Patard
+ * Copyright (c) 2004 Arnaud Patard
+ *
+ * S3C2410 LCD Framebuffer Driver
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*
- * S3C2410 LCD Controller Frame Buffer Driver
- * based on skeletonfb.c, sa1100fb.h
- *
- * ChangeLog
- *
- * 2004-12-04: Arnaud Patard <arnaud.patard@rtp-net.org>
- * - Moved dprintk to s3c2410fb.c
- *
- * 2004-09-07: Arnaud Patard <arnaud.patard@rtp-net.org>
- * - Renamed from h1940fb.h to s3c2410fb.h
- * - Changed h1940 to s3c2410
- *
- * 2004-07-15: Arnaud Patard <arnaud.patard@rtp-net.org>
- * - First version
- */
+*/
#ifndef __S3C2410FB_H
#define __S3C2410FB_H
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 73803624c131..b9343844cd1f 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -5787,7 +5787,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
} else {
struct sis_video_info *countvideo = card_list;
ivideo->cardnumber = 1;
- while((countvideo = countvideo->next) != 0)
+ while((countvideo = countvideo->next) != NULL)
ivideo->cardnumber++;
}
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index 742b5c656d66..15d4a768b1f6 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -663,14 +663,14 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
sm501fb_sync_regs(fbi);
mdelay(10);
- if (pd->flags & SM501FB_FLAG_PANEL_USE_VBIASEN) {
+ if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) {
control |= SM501_DC_PANEL_CONTROL_BIAS; /* VBIASEN */
writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
}
- if (pd->flags & SM501FB_FLAG_PANEL_USE_FPEN) {
+ if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) {
control |= SM501_DC_PANEL_CONTROL_FPEN;
writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
@@ -678,14 +678,14 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
}
} else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) {
/* disable panel power */
- if (pd->flags & SM501FB_FLAG_PANEL_USE_FPEN) {
+ if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) {
control &= ~SM501_DC_PANEL_CONTROL_FPEN;
writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
}
- if (pd->flags & SM501FB_FLAG_PANEL_USE_VBIASEN) {
+ if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) {
control &= ~SM501_DC_PANEL_CONTROL_BIAS;
writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index 13866789b356..0f3c2bb7bf35 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -2,6 +2,9 @@
#include <linux/spinlock.h>
#include <linux/virtio_config.h>
+/* Unique numbering for virtio devices. */
+static unsigned int dev_index;
+
static ssize_t device_show(struct device *_d,
struct device_attribute *attr, char *buf)
{
@@ -166,7 +169,10 @@ int register_virtio_device(struct virtio_device *dev)
int err;
dev->dev.bus = &virtio_bus;
- sprintf(dev->dev.bus_id, "%u", dev->index);
+
+ /* Assign a unique device index and hence name. */
+ dev->index = dev_index++;
+ sprintf(dev->dev.bus_id, "virtio%u", dev->index);
/* We always start by resetting the device, in case a previous
* driver messed it up. This also tests that code path a little. */
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
index 27e9fc9117cd..eae7236310e4 100644
--- a/drivers/virtio/virtio_pci.c
+++ b/drivers/virtio/virtio_pci.c
@@ -78,9 +78,6 @@ static struct device virtio_pci_root = {
.bus_id = "virtio-pci",
};
-/* Unique numbering for devices under the kvm root */
-static unsigned int dev_index;
-
/* Convert a generic virtio device to our structure */
static struct virtio_pci_device *to_vp_device(struct virtio_device *vdev)
{
@@ -325,10 +322,6 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev,
if (vp_dev == NULL)
return -ENOMEM;
- snprintf(vp_dev->vdev.dev.bus_id, BUS_ID_SIZE, "virtio%d", dev_index);
- vp_dev->vdev.index = dev_index;
- dev_index++;
-
vp_dev->vdev.dev.parent = &virtio_pci_root;
vp_dev->vdev.config = &virtio_pci_config_ops;
vp_dev->pci_dev = pci_dev;
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 937a49d6772c..72bf8bc09014 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -227,7 +227,6 @@ static bool vring_enable_cb(struct virtqueue *_vq)
struct vring_virtqueue *vq = to_vvq(_vq);
START_USE(vq);
- BUG_ON(!(vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT));
/* We optimistically turn back on interrupts, then check if there was
* more to do. */
@@ -254,13 +253,6 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
if (unlikely(vq->broken))
return IRQ_HANDLED;
- /* Other side may have missed us turning off the interrupt,
- * but we should preserve disable semantic for virtio users. */
- if (unlikely(vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)) {
- pr_debug("virtqueue interrupt after disable for %p\n", vq);
- return IRQ_HANDLED;
- }
-
pr_debug("virtqueue callback for %p (%p)\n", vq, vq->vq.callback);
if (vq->vq.callback)
vq->vq.callback(&vq->vq);
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 254d115cafab..ccb78f66c2b6 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -295,6 +295,19 @@ config ALIM7101_WDT
Most people will say N.
+config GEODE_WDT
+ tristate "AMD Geode CS5535/CS5536 Watchdog"
+ depends on MGEODE_LX
+ help
+ This driver enables a watchdog capability built into the
+ CS5535/CS5536 companion chips for the AMD Geode GX and LX
+ processors. This watchdog watches your kernel to make sure
+ it doesn't freeze, and if it does, it reboots your computer after
+ a certain amount of time.
+
+ You can compile this driver directly into the kernel, or use
+ it as a module. The module will be called geodewdt.
+
config SC520_WDT
tristate "AMD Elan SC520 processor Watchdog"
depends on X86
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index f3fb170fe5c6..25b352b664d9 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -59,6 +59,7 @@ obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o
obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o
+obj-$(CONFIG_GEODE_WDT) += geodewdt.o
obj-$(CONFIG_SC520_WDT) += sc520_wdt.o
obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
obj-$(CONFIG_IB700_WDT) += ib700wdt.o
diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c
index 1237113dc14a..03b3e3d91e7c 100644
--- a/drivers/watchdog/bfin_wdt.c
+++ b/drivers/watchdog/bfin_wdt.c
@@ -29,7 +29,8 @@
#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
#define stampit() stamp("here i am")
-#define pr_init(fmt, args...) ({ static const __initdata char __fmt[] = fmt; printk(__fmt, ## args); })
+#define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); })
+#define pr_init(fmt, args...) ({ static const __initconst char __fmt[] = fmt; printk(__fmt, ## args); })
#define WATCHDOG_NAME "bfin-wdt"
#define PFX WATCHDOG_NAME ": "
@@ -377,20 +378,6 @@ static int bfin_wdt_resume(struct platform_device *pdev)
# define bfin_wdt_resume NULL
#endif
-static struct platform_device bfin_wdt_device = {
- .name = WATCHDOG_NAME,
- .id = -1,
-};
-
-static struct platform_driver bfin_wdt_driver = {
- .driver = {
- .name = WATCHDOG_NAME,
- .owner = THIS_MODULE,
- },
- .suspend = bfin_wdt_suspend,
- .resume = bfin_wdt_resume,
-};
-
static const struct file_operations bfin_wdt_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
@@ -418,11 +405,67 @@ static struct notifier_block bfin_wdt_notifier = {
};
/**
- * bfin_wdt_init - Initialize module
+ * bfin_wdt_probe - Initialize module
*
- * Registers the device and notifier handler. Actual device
+ * Registers the misc device and notifier handler. Actual device
* initialization is handled by bfin_wdt_open().
*/
+static int __devinit bfin_wdt_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ ret = register_reboot_notifier(&bfin_wdt_notifier);
+ if (ret) {
+ pr_devinit(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret);
+ return ret;
+ }
+
+ ret = misc_register(&bfin_wdt_miscdev);
+ if (ret) {
+ pr_devinit(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+ WATCHDOG_MINOR, ret);
+ unregister_reboot_notifier(&bfin_wdt_notifier);
+ return ret;
+ }
+
+ pr_devinit(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n",
+ timeout, nowayout);
+
+ return 0;
+}
+
+/**
+ * bfin_wdt_remove - Initialize module
+ *
+ * Unregisters the misc device and notifier handler. Actual device
+ * deinitialization is handled by bfin_wdt_close().
+ */
+static int __devexit bfin_wdt_remove(struct platform_device *pdev)
+{
+ misc_deregister(&bfin_wdt_miscdev);
+ unregister_reboot_notifier(&bfin_wdt_notifier);
+ return 0;
+}
+
+static struct platform_device *bfin_wdt_device;
+
+static struct platform_driver bfin_wdt_driver = {
+ .probe = bfin_wdt_probe,
+ .remove = __devexit_p(bfin_wdt_remove),
+ .suspend = bfin_wdt_suspend,
+ .resume = bfin_wdt_resume,
+ .driver = {
+ .name = WATCHDOG_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+/**
+ * bfin_wdt_init - Initialize module
+ *
+ * Checks the module params and registers the platform device & driver.
+ * Real work is in the platform probe function.
+ */
static int __init bfin_wdt_init(void)
{
int ret;
@@ -436,44 +479,32 @@ static int __init bfin_wdt_init(void)
/* Since this is an on-chip device and needs no board-specific
* resources, we'll handle all the platform device stuff here.
*/
- ret = platform_device_register(&bfin_wdt_device);
- if (ret)
- return ret;
-
- ret = platform_driver_probe(&bfin_wdt_driver, NULL);
- if (ret)
- return ret;
-
- ret = register_reboot_notifier(&bfin_wdt_notifier);
+ ret = platform_driver_register(&bfin_wdt_driver);
if (ret) {
- pr_init(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret);
+ pr_init(KERN_ERR PFX "unable to register driver\n");
return ret;
}
- ret = misc_register(&bfin_wdt_miscdev);
- if (ret) {
- pr_init(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
- WATCHDOG_MINOR, ret);
- unregister_reboot_notifier(&bfin_wdt_notifier);
- return ret;
+ bfin_wdt_device = platform_device_register_simple(WATCHDOG_NAME, -1, NULL, 0);
+ if (IS_ERR(bfin_wdt_device)) {
+ pr_init(KERN_ERR PFX "unable to register device\n");
+ platform_driver_unregister(&bfin_wdt_driver);
+ return PTR_ERR(bfin_wdt_device);
}
- pr_init(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n",
- timeout, nowayout);
-
return 0;
}
/**
* bfin_wdt_exit - Deinitialize module
*
- * Unregisters the device and notifier handler. Actual device
- * deinitialization is handled by bfin_wdt_close().
+ * Back out the platform device & driver steps. Real work is in the
+ * platform remove function.
*/
static void __exit bfin_wdt_exit(void)
{
- misc_deregister(&bfin_wdt_miscdev);
- unregister_reboot_notifier(&bfin_wdt_notifier);
+ platform_device_unregister(bfin_wdt_device);
+ platform_driver_unregister(&bfin_wdt_driver);
}
module_init(bfin_wdt_init);
diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c
index d362f5bf658a..c1ba0db48501 100644
--- a/drivers/watchdog/booke_wdt.c
+++ b/drivers/watchdog/booke_wdt.c
@@ -1,12 +1,10 @@
/*
- * drivers/char/watchdog/booke_wdt.c
- *
* Watchdog timer for PowerPC Book-E systems
*
* Author: Matthew McClintock
* Maintainer: Kumar Gala <galak@kernel.crashing.org>
*
- * Copyright 2005 Freescale Semiconductor Inc.
+ * Copyright 2005, 2008 Freescale Semiconductor Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -16,6 +14,7 @@
#include <linux/module.h>
#include <linux/fs.h>
+#include <linux/smp.h>
#include <linux/miscdevice.h>
#include <linux/notifier.h>
#include <linux/watchdog.h>
@@ -38,7 +37,7 @@
#define WDT_PERIOD_DEFAULT 3 /* Refer to the PPC40x and PPC4xx manuals */
#endif /* for timing information */
-u32 booke_wdt_enabled = 0;
+u32 booke_wdt_enabled;
u32 booke_wdt_period = WDT_PERIOD_DEFAULT;
#ifdef CONFIG_FSL_BOOKE
@@ -47,33 +46,31 @@ u32 booke_wdt_period = WDT_PERIOD_DEFAULT;
#define WDTP(x) (TCR_WP(x))
#endif
-/*
- * booke_wdt_ping:
- */
-static __inline__ void booke_wdt_ping(void)
+static DEFINE_SPINLOCK(booke_wdt_lock);
+
+static void __booke_wdt_ping(void *data)
{
mtspr(SPRN_TSR, TSR_ENW|TSR_WIS);
}
-/*
- * booke_wdt_enable:
- */
-static __inline__ void booke_wdt_enable(void)
+static void booke_wdt_ping(void)
+{
+ on_each_cpu(__booke_wdt_ping, NULL, 0, 0);
+}
+
+static void __booke_wdt_enable(void *data)
{
u32 val;
/* clear status before enabling watchdog */
- booke_wdt_ping();
+ __booke_wdt_ping(NULL);
val = mfspr(SPRN_TCR);
val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period));
mtspr(SPRN_TCR, val);
}
-/*
- * booke_wdt_write:
- */
-static ssize_t booke_wdt_write (struct file *file, const char __user *buf,
+static ssize_t booke_wdt_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
booke_wdt_ping();
@@ -81,15 +78,11 @@ static ssize_t booke_wdt_write (struct file *file, const char __user *buf,
}
static struct watchdog_info ident = {
- .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
- .firmware_version = 0,
- .identity = "PowerPC Book-E Watchdog",
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+ .identity = "PowerPC Book-E Watchdog",
};
-/*
- * booke_wdt_ioctl:
- */
-static int booke_wdt_ioctl (struct inode *inode, struct file *file,
+static int booke_wdt_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
u32 tmp = 0;
@@ -97,7 +90,7 @@ static int booke_wdt_ioctl (struct inode *inode, struct file *file,
switch (cmd) {
case WDIOC_GETSUPPORT:
- if (copy_to_user ((struct watchdog_info __user *) arg, &ident,
+ if (copy_to_user((struct watchdog_info __user *)arg, &ident,
sizeof(struct watchdog_info)))
return -EFAULT;
case WDIOC_GETSTATUS:
@@ -132,33 +125,33 @@ static int booke_wdt_ioctl (struct inode *inode, struct file *file,
return 0;
}
-/*
- * booke_wdt_open:
- */
-static int booke_wdt_open (struct inode *inode, struct file *file)
+
+static int booke_wdt_open(struct inode *inode, struct file *file)
{
+ spin_lock(&booke_wdt_lock);
if (booke_wdt_enabled == 0) {
booke_wdt_enabled = 1;
- booke_wdt_enable();
- printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
- booke_wdt_period);
+ on_each_cpu(__booke_wdt_enable, NULL, 0, 0);
+ printk(KERN_INFO "PowerPC Book-E Watchdog Timer Enabled "
+ "(wdt_period=%d)\n", booke_wdt_period);
}
+ spin_unlock(&booke_wdt_lock);
return nonseekable_open(inode, file);
}
static const struct file_operations booke_wdt_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .write = booke_wdt_write,
- .ioctl = booke_wdt_ioctl,
- .open = booke_wdt_open,
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = booke_wdt_write,
+ .ioctl = booke_wdt_ioctl,
+ .open = booke_wdt_open,
};
static struct miscdevice booke_wdt_miscdev = {
- .minor = WATCHDOG_MINOR,
- .name = "watchdog",
- .fops = &booke_wdt_fops,
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &booke_wdt_fops,
};
static void __exit booke_wdt_exit(void)
@@ -166,28 +159,27 @@ static void __exit booke_wdt_exit(void)
misc_deregister(&booke_wdt_miscdev);
}
-/*
- * booke_wdt_init:
- */
static int __init booke_wdt_init(void)
{
int ret = 0;
- printk (KERN_INFO "PowerPC Book-E Watchdog Timer Loaded\n");
+ printk(KERN_INFO "PowerPC Book-E Watchdog Timer Loaded\n");
ident.firmware_version = cur_cpu_spec->pvr_value;
ret = misc_register(&booke_wdt_miscdev);
if (ret) {
- printk (KERN_CRIT "Cannot register miscdev on minor=%d (err=%d)\n",
+ printk(KERN_CRIT "Cannot register miscdev on minor=%d: %d\n",
WATCHDOG_MINOR, ret);
return ret;
}
+ spin_lock(&booke_wdt_lock);
if (booke_wdt_enabled == 1) {
- printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
- booke_wdt_period);
- booke_wdt_enable();
+ printk(KERN_INFO "PowerPC Book-E Watchdog Timer Enabled "
+ "(wdt_period=%d)\n", booke_wdt_period);
+ on_each_cpu(__booke_wdt_enable, NULL, 0, 0);
}
+ spin_unlock(&booke_wdt_lock);
return ret;
}
diff --git a/drivers/watchdog/geodewdt.c b/drivers/watchdog/geodewdt.c
new file mode 100644
index 000000000000..30d09cbbad94
--- /dev/null
+++ b/drivers/watchdog/geodewdt.c
@@ -0,0 +1,308 @@
+/* Watchdog timer for the Geode GX/LX with the CS5535/CS5536 companion chip
+ *
+ * Copyright (C) 2006-2007, Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+
+#include <asm/uaccess.h>
+#include <asm/geode.h>
+
+#define GEODEWDT_HZ 500
+#define GEODEWDT_SCALE 6
+#define GEODEWDT_MAX_SECONDS 131
+
+#define WDT_FLAGS_OPEN 1
+#define WDT_FLAGS_ORPHAN 2
+
+#define DRV_NAME "geodewdt"
+#define WATCHDOG_NAME "Geode GX/LX WDT"
+#define WATCHDOG_TIMEOUT 60
+
+static int timeout = WATCHDOG_TIMEOUT;
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=131, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static struct platform_device *geodewdt_platform_device;
+static unsigned long wdt_flags;
+static int wdt_timer;
+static int safe_close;
+
+static void geodewdt_ping(void)
+{
+ /* Stop the counter */
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0);
+
+ /* Reset the counter */
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0);
+
+ /* Enable the counter */
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, MFGPT_SETUP_CNTEN);
+}
+
+static void geodewdt_disable(void)
+{
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0);
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0);
+}
+
+static int geodewdt_set_heartbeat(int val)
+{
+ if (val < 1 || val > GEODEWDT_MAX_SECONDS)
+ return -EINVAL;
+
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0);
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_CMP2, val * GEODEWDT_HZ);
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0);
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, MFGPT_SETUP_CNTEN);
+
+ timeout = val;
+ return 0;
+}
+
+static int
+geodewdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(WDT_FLAGS_OPEN, &wdt_flags))
+ return -EBUSY;
+
+ if (!test_and_clear_bit(WDT_FLAGS_ORPHAN, &wdt_flags))
+ __module_get(THIS_MODULE);
+
+ geodewdt_ping();
+ return nonseekable_open(inode, file);
+}
+
+static int
+geodewdt_release(struct inode *inode, struct file *file)
+{
+ if (safe_close) {
+ geodewdt_disable();
+ module_put(THIS_MODULE);
+ }
+ else {
+ printk(KERN_CRIT "Unexpected close - watchdog is not stopping.\n");
+ geodewdt_ping();
+
+ set_bit(WDT_FLAGS_ORPHAN, &wdt_flags);
+ }
+
+ clear_bit(WDT_FLAGS_OPEN, &wdt_flags);
+ safe_close = 0;
+ return 0;
+}
+
+static ssize_t
+geodewdt_write(struct file *file, const char __user *data, size_t len,
+ loff_t *ppos)
+{
+ if(len) {
+ if (!nowayout) {
+ size_t i;
+ safe_close = 0;
+
+ for (i = 0; i != len; i++) {
+ char c;
+
+ if (get_user(c, data + i))
+ return -EFAULT;
+
+ if (c == 'V')
+ safe_close = 1;
+ }
+ }
+
+ geodewdt_ping();
+ }
+ return len;
+}
+
+static int
+geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ int interval;
+
+ static struct watchdog_info ident = {
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING
+ | WDIOF_MAGICCLOSE,
+ .firmware_version = 1,
+ .identity = WATCHDOG_NAME,
+ };
+
+ switch(cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(argp, &ident,
+ sizeof(ident)) ? -EFAULT : 0;
+ break;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, p);
+
+ case WDIOC_KEEPALIVE:
+ geodewdt_ping();
+ return 0;
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(interval, p))
+ return -EFAULT;
+
+ if (geodewdt_set_heartbeat(interval))
+ return -EINVAL;
+
+/* Fall through */
+
+ case WDIOC_GETTIMEOUT:
+ return put_user(timeout, p);
+
+ case WDIOC_SETOPTIONS:
+ {
+ int options, ret = -EINVAL;
+
+ if (get_user(options, p))
+ return -EFAULT;
+
+ if (options & WDIOS_DISABLECARD) {
+ geodewdt_disable();
+ ret = 0;
+ }
+
+ if (options & WDIOS_ENABLECARD) {
+ geodewdt_ping();
+ ret = 0;
+ }
+
+ return ret;
+ }
+ default:
+ return -ENOTTY;
+ }
+
+ return 0;
+}
+
+static const struct file_operations geodewdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = geodewdt_write,
+ .ioctl = geodewdt_ioctl,
+ .open = geodewdt_open,
+ .release = geodewdt_release,
+};
+
+static struct miscdevice geodewdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &geodewdt_fops
+};
+
+static int __devinit
+geodewdt_probe(struct platform_device *dev)
+{
+ int ret, timer;
+
+ timer = geode_mfgpt_alloc_timer(MFGPT_TIMER_ANY, MFGPT_DOMAIN_WORKING);
+
+ if (timer == -1) {
+ printk(KERN_ERR "geodewdt: No timers were available\n");
+ return -ENODEV;
+ }
+
+ wdt_timer = timer;
+
+ /* Set up the timer */
+
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP,
+ GEODEWDT_SCALE | (3 << 8));
+
+ /* Set up comparator 2 to reset when the event fires */
+ geode_mfgpt_toggle_event(wdt_timer, MFGPT_CMP2, MFGPT_EVENT_RESET, 1);
+
+ /* Set up the initial timeout */
+
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_CMP2,
+ timeout * GEODEWDT_HZ);
+
+ ret = misc_register(&geodewdt_miscdev);
+
+ return ret;
+}
+
+static int __devexit
+geodewdt_remove(struct platform_device *dev)
+{
+ misc_deregister(&geodewdt_miscdev);
+ return 0;
+}
+
+static void
+geodewdt_shutdown(struct platform_device *dev)
+{
+ geodewdt_disable();
+}
+
+static struct platform_driver geodewdt_driver = {
+ .probe = geodewdt_probe,
+ .remove = __devexit_p(geodewdt_remove),
+ .shutdown = geodewdt_shutdown,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRV_NAME,
+ },
+};
+
+static int __init
+geodewdt_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&geodewdt_driver);
+ if (ret)
+ return ret;
+
+ geodewdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0);
+ if (IS_ERR(geodewdt_platform_device)) {
+ ret = PTR_ERR(geodewdt_platform_device);
+ goto err;
+ }
+
+ return 0;
+err:
+ platform_driver_unregister(&geodewdt_driver);
+ return ret;
+}
+
+static void __exit
+geodewdt_exit(void)
+{
+ platform_device_unregister(geodewdt_platform_device);
+ platform_driver_unregister(&geodewdt_driver);
+}
+
+module_init(geodewdt_init);
+module_exit(geodewdt_exit);
+
+MODULE_AUTHOR("Advanced Micro Devices, Inc");
+MODULE_DESCRIPTION("Geode GX/LX Watchdog Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index 6483d1066b95..6a63535fc04d 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -418,23 +418,20 @@ static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason,
static unsigned long rom_pl;
static int die_nmi_called;
- if (ulReason != DIE_NMI && ulReason != DIE_NMI_IPI)
- return NOTIFY_OK;
-
- spin_lock_irqsave(&rom_lock, rom_pl);
- if (!die_nmi_called)
- asminline_call(&cmn_regs, cru_rom_addr);
- die_nmi_called = 1;
- spin_unlock_irqrestore(&rom_lock, rom_pl);
- if (cmn_regs.u1.ral == 0) {
- printk(KERN_WARNING "hpwdt: An NMI occurred, "
- "but unable to determine source.\n");
- } else {
- panic("An NMI occurred, please see the Integrated "
- "Management Log for details.\n");
+ if (ulReason == DIE_NMI || ulReason == DIE_NMI_IPI) {
+ spin_lock_irqsave(&rom_lock, rom_pl);
+ if (!die_nmi_called)
+ asminline_call(&cmn_regs, cru_rom_addr);
+ die_nmi_called = 1;
+ spin_unlock_irqrestore(&rom_lock, rom_pl);
+ if (cmn_regs.u1.ral != 0) {
+ panic("An NMI occurred, please see the Integrated "
+ "Management Log for details.\n");
+ }
}
- return NOTIFY_STOP;
+ die_nmi_called = 0;
+ return NOTIFY_DONE;
}
/*
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index a0e6809e369f..95ba985bd341 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -41,9 +41,10 @@
* 82801HH (ICH8DH) : document number 313056-003, 313057-009,
* 82801HO (ICH8DO) : document number 313056-003, 313057-009,
* 82801HEM (ICH8M-E) : document number 313056-003, 313057-009,
- * 82801IB (ICH9) : document number 316972-001, 316973-001,
- * 82801IR (ICH9R) : document number 316972-001, 316973-001,
- * 82801IH (ICH9DH) : document number 316972-001, 316973-001,
+ * 82801IB (ICH9) : document number 316972-001, 316973-006,
+ * 82801IR (ICH9R) : document number 316972-001, 316973-006,
+ * 82801IH (ICH9DH) : document number 316972-001, 316973-006,
+ * 82801IO (ICH9DO) : document number 316972-001, 316973-006,
* 6300ESB (6300ESB) : document number 300641-003, 300884-010,
* 631xESB (631xESB) : document number 313082-001, 313075-005,
* 632xESB (632xESB) : document number 313082-001, 313075-005
@@ -55,8 +56,8 @@
/* Module and version information */
#define DRV_NAME "iTCO_wdt"
-#define DRV_VERSION "1.02"
-#define DRV_RELDATE "26-Jul-2007"
+#define DRV_VERSION "1.03"
+#define DRV_RELDATE "30-Apr-2008"
#define PFX DRV_NAME ": "
/* Includes */
@@ -104,6 +105,7 @@ enum iTCO_chipsets {
TCO_ICH9, /* ICH9 */
TCO_ICH9R, /* ICH9R */
TCO_ICH9DH, /* ICH9DH */
+ TCO_ICH9DO, /* ICH9DO */
TCO_631XESB, /* 631xESB/632xESB */
};
@@ -136,6 +138,7 @@ static struct {
{"ICH9", 2},
{"ICH9R", 2},
{"ICH9DH", 2},
+ {"ICH9DO", 2},
{"631xESB/632xESB", 2},
{NULL,0}
};
@@ -181,6 +184,7 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = {
{ ITCO_PCI_DEVICE(0x2918, TCO_ICH9 )},
{ ITCO_PCI_DEVICE(0x2916, TCO_ICH9R )},
{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_2, TCO_ICH9DH )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_4, TCO_ICH9DO )},
{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB2_0, TCO_631XESB)},
{ ITCO_PCI_DEVICE(0x2671, TCO_631XESB)},
{ ITCO_PCI_DEVICE(0x2672, TCO_631XESB)},
diff --git a/drivers/watchdog/w83697hf_wdt.c b/drivers/watchdog/w83697hf_wdt.c
index c622a0e6c9ae..528b882420b6 100644
--- a/drivers/watchdog/w83697hf_wdt.c
+++ b/drivers/watchdog/w83697hf_wdt.c
@@ -44,6 +44,7 @@
#define WATCHDOG_NAME "w83697hf/hg WDT"
#define PFX WATCHDOG_NAME ": "
#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */
+#define WATCHDOG_EARLY_DISABLE 1 /* Disable until userland kicks in */
static unsigned long wdt_is_open;
static char expect_close;
@@ -56,12 +57,16 @@ MODULE_PARM_DESC(wdt_io, "w83697hf/hg WDT io port (default 0x2e, 0 = autodetect)
static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255 (default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
static int nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+static int early_disable = WATCHDOG_EARLY_DISABLE;
+module_param(early_disable, int, 0);
+MODULE_PARM_DESC(early_disable, "Watchdog gets disabled at boot time (default=" __MODULE_STRING(WATCHDOG_EARLY_DISABLE) ")");
+
/*
* Kernel methods.
*/
@@ -140,7 +145,7 @@ w83697hf_init(void)
w83697hf_deselect_wdt();
}
-static int
+static void
wdt_ping(void)
{
spin_lock(&io_lock);
@@ -150,10 +155,9 @@ wdt_ping(void)
w83697hf_deselect_wdt();
spin_unlock(&io_lock);
- return 0;
}
-static int
+static void
wdt_enable(void)
{
spin_lock(&io_lock);
@@ -164,10 +168,9 @@ wdt_enable(void)
w83697hf_deselect_wdt();
spin_unlock(&io_lock);
- return 0;
}
-static int
+static void
wdt_disable(void)
{
spin_lock(&io_lock);
@@ -178,7 +181,22 @@ wdt_disable(void)
w83697hf_deselect_wdt();
spin_unlock(&io_lock);
- return 0;
+}
+
+static unsigned char
+wdt_running(void)
+{
+ unsigned char t;
+
+ spin_lock(&io_lock);
+ w83697hf_select_wdt();
+
+ t = w83697hf_get_reg(0xF4); /* Read timer */
+
+ w83697hf_deselect_wdt();
+ spin_unlock(&io_lock);
+
+ return t;
}
static int
@@ -397,7 +415,11 @@ wdt_init(void)
}
w83697hf_init();
- wdt_disable(); /* Disable watchdog until first use */
+ if (early_disable) {
+ if (wdt_running())
+ printk (KERN_WARNING PFX "Stopping previously enabled watchdog until userland kicks in\n");
+ wdt_disable();
+ }
if (wdt_set_heartbeat(timeout)) {
wdt_set_heartbeat(WATCHDOG_TIMEOUT);