summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2007-04-13 03:50:03 +1000
committerPaul Mackerras <paulus@samba.org>2007-04-13 03:50:03 +1000
commite049d1ca3094f3d1d94617f456a9961202f96e3a (patch)
treea30397ad22f2fbea268bd28fa69c60aad9dfa62a /drivers
parentedfac96a92b88d3b0b53e3f8231b74beee9ecd1d (diff)
parent80584ff3b99c36ead7e130e453b3a48b18072d18 (diff)
downloadlinux-e049d1ca3094f3d1d94617f456a9961202f96e3a.tar.gz
linux-e049d1ca3094f3d1d94617f456a9961202f96e3a.tar.bz2
linux-e049d1ca3094f3d1d94617f456a9961202f96e3a.zip
Merge branch 'linux-2.6' into for-2.6.22
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/Kconfig12
-rw-r--r--drivers/acpi/blacklist.c10
-rw-r--r--drivers/acpi/ec.c40
-rw-r--r--drivers/acpi/events/evmisc.c33
-rw-r--r--drivers/acpi/events/evregion.c15
-rw-r--r--drivers/acpi/events/evxface.c6
-rw-r--r--drivers/acpi/executer/excreate.c5
-rw-r--r--drivers/acpi/executer/exsystem.c30
-rw-r--r--drivers/acpi/executer/exutils.c104
-rw-r--r--drivers/acpi/hardware/hwsleep.c5
-rw-r--r--drivers/acpi/ibm_acpi.c47
-rw-r--r--drivers/acpi/namespace/nseval.c11
-rw-r--r--drivers/acpi/namespace/nsinit.c7
-rw-r--r--drivers/acpi/namespace/nsxfeval.c11
-rw-r--r--drivers/acpi/power.c20
-rw-r--r--drivers/acpi/processor_idle.c3
-rw-r--r--drivers/acpi/resources/rscreate.c25
-rw-r--r--drivers/acpi/tables.c57
-rw-r--r--drivers/acpi/video.c38
-rw-r--r--drivers/ata/Kconfig2
-rw-r--r--drivers/ata/ahci.c21
-rw-r--r--drivers/ata/ata_piix.c11
-rw-r--r--drivers/ata/libata-acpi.c32
-rw-r--r--drivers/ata/libata-core.c67
-rw-r--r--drivers/ata/libata-eh.c96
-rw-r--r--drivers/ata/libata-scsi.c2
-rw-r--r--drivers/ata/libata.h2
-rw-r--r--drivers/ata/pata_cs5520.c2
-rw-r--r--drivers/ata/pata_ixp4xx_cf.c3
-rw-r--r--drivers/ata/pata_mpc52xx.c2
-rw-r--r--drivers/ata/pata_pdc202xx_old.c2
-rw-r--r--drivers/ata/sata_inic162x.c4
-rw-r--r--drivers/ata/sata_nv.c8
-rw-r--r--drivers/ata/sata_sil24.c1
-rw-r--r--drivers/ata/sata_sis.c2
-rw-r--r--drivers/atm/zatm.c4
-rw-r--r--drivers/base/core.c73
-rw-r--r--drivers/base/driver.c9
-rw-r--r--drivers/base/power/main.c6
-rw-r--r--drivers/block/cciss.c11
-rw-r--r--drivers/block/paride/pd.c8
-rw-r--r--drivers/char/Kconfig33
-rw-r--r--drivers/char/agp/intel-agp.c17
-rw-r--r--drivers/char/drm/Makefile2
-rw-r--r--drivers/char/drm/ffb_context.c544
-rw-r--r--drivers/char/drm/ffb_drv.c355
-rw-r--r--drivers/char/drm/ffb_drv.h379
-rw-r--r--drivers/char/ds1286.c9
-rw-r--r--drivers/char/generic_serial.c7
-rw-r--r--drivers/char/lcd.c5
-rw-r--r--drivers/char/tty_io.c5
-rw-r--r--drivers/char/vt.c21
-rw-r--r--drivers/char/vt_ioctl.c18
-rw-r--r--drivers/char/watchdog/Kconfig1
-rw-r--r--drivers/char/watchdog/machzwd.c24
-rw-r--r--drivers/clocksource/acpi_pm.c2
-rw-r--r--drivers/connector/connector.c22
-rw-r--r--drivers/cpufreq/cpufreq.c4
-rw-r--r--drivers/dma/dmaengine.c18
-rw-r--r--drivers/eisa/pci_eisa.c4
-rw-r--r--drivers/hid/hid-core.c31
-rw-r--r--drivers/hwmon/Kconfig1
-rw-r--r--drivers/i2c/busses/i2c-amd8111.c3
-rw-r--r--drivers/i2c/busses/i2c-i801.c25
-rw-r--r--drivers/i2c/chips/ds1374.c4
-rw-r--r--drivers/ide/Kconfig54
-rw-r--r--drivers/ide/Makefile1
-rw-r--r--drivers/ide/arm/icside.c13
-rw-r--r--drivers/ide/ide-cd.c9
-rw-r--r--drivers/ide/ide-dma.c2
-rw-r--r--drivers/ide/ide-io.c38
-rw-r--r--drivers/ide/ide-iops.c13
-rw-r--r--drivers/ide/ide.c43
-rw-r--r--drivers/ide/mips/au1xxx-ide.c3
-rw-r--r--drivers/ide/pci/Makefile1
-rw-r--r--drivers/ide/pci/cmd64x.c45
-rw-r--r--drivers/ide/pci/jmicron.c29
-rw-r--r--drivers/ide/pci/pdc202xx_new.c3
-rw-r--r--drivers/ide/pci/scc_pata.c (renamed from drivers/ide/ppc/scc_pata.c)0
-rw-r--r--drivers/ide/setup-pci.c5
-rw-r--r--drivers/ieee1394/Kconfig6
-rw-r--r--drivers/ieee1394/dv1394.c4
-rw-r--r--drivers/ieee1394/eth1394.c3
-rw-r--r--drivers/infiniband/core/cma.c2
-rw-r--r--drivers/infiniband/core/ucma.c2
-rw-r--r--drivers/infiniband/hw/cxgb3/cxio_hal.c13
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cm.c19
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_ev.c12
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_provider.c45
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_provider.h33
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_qp.c2
-rw-r--r--drivers/infiniband/hw/ehca/ehca_classes.h6
-rw-r--r--drivers/infiniband/hw/ehca/ehca_cq.c16
-rw-r--r--drivers/infiniband/hw/ehca/ehca_irq.c67
-rw-r--r--drivers/infiniband/hw/ehca/ehca_main.c4
-rw-r--r--drivers/infiniband/hw/ipath/ipath_dma.c2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_fs.c16
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mr.c4
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c10
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c6
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c4
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c10
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c11
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_verbs.c13
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.h1
-rw-r--r--drivers/infiniband/ulp/iser/iser_initiator.c17
-rw-r--r--drivers/infiniband/ulp/iser/iser_verbs.c40
-rw-r--r--drivers/input/serio/i8042.c10
-rw-r--r--drivers/input/touchscreen/ucb1400_ts.c1
-rw-r--r--drivers/isdn/gigaset/bas-gigaset.c4
-rw-r--r--drivers/isdn/gigaset/common.c6
-rw-r--r--drivers/isdn/gigaset/ev-layer.c4
-rw-r--r--drivers/isdn/gigaset/isocdata.c4
-rw-r--r--drivers/isdn/gigaset/ser-gigaset.c2
-rw-r--r--drivers/isdn/gigaset/usb-gigaset.c4
-rw-r--r--drivers/isdn/hisax/isar.c2
-rw-r--r--drivers/kvm/kvm_main.c4
-rw-r--r--drivers/kvm/mmu.c52
-rw-r--r--drivers/kvm/vmx.c47
-rw-r--r--drivers/md/linear.c2
-rw-r--r--drivers/md/md.c58
-rw-r--r--drivers/md/raid5.c19
-rw-r--r--drivers/media/common/ir-functions.c6
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c12
-rw-r--r--drivers/media/dvb/dvb-core/dvb_demux.c21
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c9
-rw-r--r--drivers/media/dvb/frontends/isl6421.c1
-rw-r--r--drivers/media/dvb/frontends/nxt200x.c4
-rw-r--r--drivers/media/dvb/frontends/tda10086.c2
-rw-r--r--drivers/media/dvb/pluto2/pluto2.c22
-rw-r--r--drivers/media/radio/Kconfig2
-rw-r--r--drivers/media/video/msp3400-driver.c14
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c6
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-v4l2.c6
-rw-r--r--drivers/media/video/saa7115.c2
-rw-r--r--drivers/media/video/tuner-core.c10
-rw-r--r--drivers/message/fusion/mptsas.c7
-rw-r--r--drivers/message/i2o/i2o_block.c12
-rw-r--r--drivers/mfd/sm501.c2
-rw-r--r--drivers/misc/asus-laptop.c2
-rw-r--r--drivers/misc/sony-laptop.c2
-rw-r--r--drivers/mmc/imxmmc.c13
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0002.c2
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0020.c2
-rw-r--r--drivers/mtd/maps/dilnetpc.c4
-rw-r--r--drivers/mtd/maps/esb2rom.c11
-rw-r--r--drivers/mtd/mtdconcat.c1
-rw-r--r--drivers/mtd/mtdpart.c7
-rw-r--r--drivers/mtd/nand/diskonchip.c2
-rw-r--r--drivers/mtd/nand/nand_base.c1
-rw-r--r--drivers/mtd/onenand/onenand_base.c77
-rw-r--r--drivers/net/3c59x.c28
-rw-r--r--drivers/net/Kconfig25
-rw-r--r--drivers/net/atl1/atl1_hw.c1
-rw-r--r--drivers/net/atl1/atl1_main.c14
-rw-r--r--drivers/net/b44.c2
-rw-r--r--drivers/net/bnx2.c38
-rw-r--r--drivers/net/cxgb3/common.h27
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c121
-rw-r--r--drivers/net/cxgb3/cxgb3_offload.c18
-rw-r--r--drivers/net/cxgb3/mc5.c3
-rw-r--r--drivers/net/cxgb3/regs.h32
-rw-r--r--drivers/net/cxgb3/sge.c2
-rw-r--r--drivers/net/cxgb3/t3_hw.c39
-rw-r--r--drivers/net/cxgb3/version.h5
-rw-r--r--drivers/net/cxgb3/xgmac.c191
-rw-r--r--drivers/net/ewrk3.c3
-rw-r--r--drivers/net/forcedeth.c8
-rw-r--r--drivers/net/ifb.c35
-rw-r--r--drivers/net/irda/irda-usb.c2
-rw-r--r--drivers/net/irda/pxaficp_ir.c30
-rw-r--r--drivers/net/mv643xx_eth.c28
-rw-r--r--drivers/net/myri10ge/myri10ge.c88
-rw-r--r--drivers/net/natsemi.c58
-rw-r--r--drivers/net/netxen/netxen_nic.h1
-rw-r--r--drivers/net/netxen/netxen_nic_ethtool.c1
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c10
-rw-r--r--drivers/net/netxen/netxen_nic_init.c14
-rw-r--r--drivers/net/pci-skeleton.c4
-rw-r--r--drivers/net/pcmcia/ibmtr_cs.c4
-rw-r--r--drivers/net/ppp_generic.c3
-rwxr-xr-xdrivers/net/qla3xxx.c110
-rwxr-xr-xdrivers/net/qla3xxx.h3
-rw-r--r--drivers/net/r8169.c60
-rw-r--r--drivers/net/saa9730.c177
-rw-r--r--drivers/net/sb1250-mac.c2
-rw-r--r--drivers/net/sc92031.c20
-rw-r--r--drivers/net/sis190.c1
-rw-r--r--drivers/net/skge.c215
-rw-r--r--drivers/net/skge.h6
-rw-r--r--drivers/net/sky2.c36
-rw-r--r--drivers/net/sun3lance.c16
-rw-r--r--drivers/net/sungem.c30
-rw-r--r--drivers/net/tg3.c136
-rw-r--r--drivers/net/tg3.h5
-rw-r--r--drivers/net/tokenring/ibmtr.c25
-rw-r--r--drivers/net/tulip/dmfe.c6
-rw-r--r--drivers/net/ucc_geth.c3
-rw-r--r--drivers/net/via-rhine.c32
-rw-r--r--drivers/net/wan/lmc/lmc_media.h65
-rw-r--r--drivers/net/wan/z85230.c2
-rw-r--r--drivers/net/wireless/airo.c4
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c26
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_phy.c71
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_radio.c26
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_wx.c10
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.c12
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.h4
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_al2230.c6
-rw-r--r--drivers/oprofile/event_buffer.c5
-rw-r--r--drivers/oprofile/oprofilefs.c5
-rw-r--r--drivers/pci/msi.c151
-rw-r--r--drivers/pci/pci.c29
-rw-r--r--drivers/pci/pci.h2
-rw-r--r--drivers/pci/pcie/aer/aerdrv.c6
-rw-r--r--drivers/pci/pcie/portdrv_pci.c8
-rw-r--r--drivers/pci/quirks.c18
-rw-r--r--drivers/pci/search.c2
-rw-r--r--drivers/pcmcia/au1000_generic.c2
-rw-r--r--drivers/pcmcia/omap_cf.c41
-rw-r--r--drivers/pnp/manager.c6
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c120
-rw-r--r--drivers/pnp/system.c13
-rw-r--r--drivers/ps3/ps3av_cmd.c24
-rw-r--r--drivers/ps3/vuart.c4
-rw-r--r--drivers/rtc/rtc-cmos.c50
-rw-r--r--drivers/s390/block/dasd_diag.c10
-rw-r--r--drivers/s390/cio/ccwgroup.c18
-rw-r--r--drivers/s390/cio/device_status.c14
-rw-r--r--drivers/s390/cio/qdio.c26
-rw-r--r--drivers/s390/crypto/ap_bus.c58
-rw-r--r--drivers/s390/crypto/ap_bus.h1
-rw-r--r--drivers/s390/crypto/zcrypt_api.c12
-rw-r--r--drivers/s390/net/qeth.h2
-rw-r--r--drivers/scsi/gdth.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c5
-rw-r--r--drivers/scsi/scsi_error.c2
-rw-r--r--drivers/scsi/scsi_sysfs.c14
-rw-r--r--drivers/serial/8250_pnp.c3
-rw-r--r--drivers/serial/sh-sci.c11
-rw-r--r--drivers/serial/sn_console.c52
-rw-r--r--drivers/spi/at25.c2
-rw-r--r--drivers/spi/atmel_spi.c2
-rw-r--r--drivers/spi/spi.c10
-rw-r--r--drivers/spi/spi_bitbang.c26
-rw-r--r--drivers/spi/spi_s3c24xx.c2
-rw-r--r--drivers/tc/zs.c1
-rw-r--r--drivers/usb/class/cdc-acm.c8
-rw-r--r--drivers/usb/class/usblp.c6
-rw-r--r--drivers/usb/core/devio.c13
-rw-r--r--drivers/usb/core/hub.c9
-rw-r--r--drivers/usb/core/message.c9
-rw-r--r--drivers/usb/core/quirks.c3
-rw-r--r--drivers/usb/gadget/at91_udc.c6
-rw-r--r--drivers/usb/gadget/goku_udc.c29
-rw-r--r--drivers/usb/gadget/omap_udc.c103
-rw-r--r--drivers/usb/host/ehci-hcd.c1
-rw-r--r--drivers/usb/host/ehci-hub.c3
-rw-r--r--drivers/usb/host/uhci-debug.c26
-rw-r--r--drivers/usb/host/uhci-hcd.c3
-rw-r--r--drivers/usb/host/uhci-hub.c11
-rw-r--r--drivers/usb/host/uhci-q.c94
-rw-r--r--drivers/usb/misc/berry_charge.c2
-rw-r--r--drivers/usb/misc/ftdi-elan.c18
-rw-r--r--drivers/usb/net/dm9601.c12
-rw-r--r--drivers/usb/serial/airprime.c52
-rw-r--r--drivers/usb/serial/cp2101.c2
-rw-r--r--drivers/usb/serial/ftdi_sio.c96
-rw-r--r--drivers/usb/serial/ftdi_sio.h21
-rw-r--r--drivers/usb/serial/generic.c7
-rw-r--r--drivers/usb/serial/ipaq.c2
-rw-r--r--drivers/usb/serial/mos7720.c1
-rw-r--r--drivers/usb/serial/option.c15
-rw-r--r--drivers/usb/serial/usb-serial.c11
-rw-r--r--drivers/usb/storage/unusual_devs.h34
-rw-r--r--drivers/video/Kconfig6
-rw-r--r--drivers/video/backlight/locomolcd.c4
-rw-r--r--drivers/video/backlight/progear_bl.c4
-rw-r--r--drivers/video/bw2.c18
-rw-r--r--drivers/video/cg14.c5
-rw-r--r--drivers/video/cg3.c26
-rw-r--r--drivers/video/ffb.c84
-rw-r--r--drivers/video/riva/fbdev.c4
-rw-r--r--drivers/video/s3fb.c3
-rw-r--r--drivers/video/savage/savagefb_driver.c18
-rw-r--r--drivers/video/sstfb.c1
286 files changed, 3467 insertions, 3495 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 7c49e103cf8f..e2ce4a9c1c92 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -7,6 +7,7 @@ menu "ACPI (Advanced Configuration and Power Interface) Support"
depends on !X86_VISWS
depends on !IA64_HP_SIM
depends on IA64 || X86
+ depends on PM
config ACPI
bool "ACPI Support"
@@ -243,6 +244,17 @@ config ACPI_IBM_DOCK
If you are not sure, say N here.
+config ACPI_IBM_BAY
+ bool "Legacy Removable Bay Support"
+ depends on ACPI_IBM
+ default y
+ ---help---
+ Allows the ibm_acpi driver to handle removable bays. It will allow
+ disabling the device in the bay, and also generate notifications when
+ the bay lever is ejected or inserted.
+
+ If you are not sure, say Y here.
+
config ACPI_TOSHIBA
tristate "Toshiba Laptop Extras"
depends on X86
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index f289fd41e77d..3ec110ce00c8 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -79,11 +79,17 @@ static int __init blacklist_by_year(void)
{
int year = dmi_get_year(DMI_BIOS_DATE);
/* Doesn't exist? Likely an old system */
- if (year == -1)
+ if (year == -1) {
+ printk(KERN_ERR PREFIX "no DMI BIOS year, "
+ "acpi=force is required to enable ACPI\n" );
return 1;
+ }
/* 0? Likely a buggy new BIOS */
- if (year == 0)
+ if (year == 0) {
+ printk(KERN_ERR PREFIX "DMI BIOS year==0, "
+ "assuming ACPI-capable machine\n" );
return 0;
+ }
if (year < CONFIG_ACPI_BLACKLIST_YEAR) {
printk(KERN_ERR PREFIX "BIOS age (%d) fails cutoff (%d), "
"acpi=force is required to enable ACPI\n",
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index ab6888373795..a802962ff2b4 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -100,6 +100,7 @@ static struct acpi_ec {
unsigned long global_lock;
struct mutex lock;
atomic_t query_pending;
+ atomic_t event_count;
atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */
wait_queue_head_t wait;
} *ec_ecdt;
@@ -131,10 +132,12 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
outb(data, ec->data_addr);
}
-static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event)
+static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event,
+ unsigned old_count)
{
u8 status = acpi_ec_read_status(ec);
-
+ if (old_count == atomic_read(&ec->event_count))
+ return 0;
if (event == ACPI_EC_EVENT_OBF_1) {
if (status & ACPI_EC_FLAG_OBF)
return 1;
@@ -146,19 +149,19 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event)
return 0;
}
-static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event)
+static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, unsigned count)
{
if (acpi_ec_mode == EC_POLL) {
unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
while (time_before(jiffies, delay)) {
- if (acpi_ec_check_status(ec, event))
+ if (acpi_ec_check_status(ec, event, 0))
return 0;
}
} else {
if (wait_event_timeout(ec->wait,
- acpi_ec_check_status(ec, event),
+ acpi_ec_check_status(ec, event, count),
msecs_to_jiffies(ACPI_EC_DELAY)) ||
- acpi_ec_check_status(ec, event)) {
+ acpi_ec_check_status(ec, event, 0)) {
return 0;
} else {
printk(KERN_ERR PREFIX "acpi_ec_wait timeout,"
@@ -225,21 +228,22 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
u8 * rdata, unsigned rdata_len)
{
int result = 0;
-
+ unsigned count = atomic_read(&ec->event_count);
acpi_ec_write_cmd(ec, command);
for (; wdata_len > 0; --wdata_len) {
- result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
+ result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count);
if (result) {
printk(KERN_ERR PREFIX
"write_cmd timeout, command = %d\n", command);
goto end;
}
+ count = atomic_read(&ec->event_count);
acpi_ec_write_data(ec, *(wdata++));
}
if (!rdata_len) {
- result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
+ result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count);
if (result) {
printk(KERN_ERR PREFIX
"finish-write timeout, command = %d\n", command);
@@ -250,13 +254,13 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
}
for (; rdata_len > 0; --rdata_len) {
- result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1);
+ result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, count);
if (result) {
printk(KERN_ERR PREFIX "read timeout, command = %d\n",
command);
goto end;
}
-
+ count = atomic_read(&ec->event_count);
*(rdata++) = acpi_ec_read_data(ec);
}
end:
@@ -288,7 +292,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
/* Make sure GPE is enabled before doing transaction */
acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
- status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
+ status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0);
if (status) {
printk(KERN_DEBUG PREFIX
"input buffer is not empty, aborting transaction\n");
@@ -369,8 +373,8 @@ int ec_write(u8 addr, u8 val)
EXPORT_SYMBOL(ec_write);
int ec_transaction(u8 command,
- const u8 * wdata, unsigned wdata_len,
- u8 * rdata, unsigned rdata_len)
+ const u8 * wdata, unsigned wdata_len,
+ u8 * rdata, unsigned rdata_len)
{
struct acpi_ec *ec;
@@ -435,7 +439,7 @@ static u32 acpi_ec_gpe_handler(void *data)
acpi_status status = AE_OK;
u8 value;
struct acpi_ec *ec = (struct acpi_ec *)data;
-
+ atomic_inc(&ec->event_count);
if (acpi_ec_mode == EC_INTR) {
wake_up(&ec->wait);
}
@@ -633,6 +637,7 @@ static int acpi_ec_add(struct acpi_device *device)
ec->uid = -1;
mutex_init(&ec->lock);
atomic_set(&ec->query_pending, 0);
+ atomic_set(&ec->event_count, 1);
if (acpi_ec_mode == EC_INTR) {
atomic_set(&ec->leaving_burst, 1);
init_waitqueue_head(&ec->wait);
@@ -807,6 +812,7 @@ acpi_fake_ecdt_callback(acpi_handle handle,
acpi_status status;
mutex_init(&ec_ecdt->lock);
+ atomic_set(&ec_ecdt->event_count, 1);
if (acpi_ec_mode == EC_INTR) {
init_waitqueue_head(&ec_ecdt->wait);
}
@@ -888,6 +894,7 @@ static int __init acpi_ec_get_real_ecdt(void)
return -ENOMEM;
mutex_init(&ec_ecdt->lock);
+ atomic_set(&ec_ecdt->event_count, 1);
if (acpi_ec_mode == EC_INTR) {
init_waitqueue_head(&ec_ecdt->wait);
}
@@ -1016,8 +1023,7 @@ static int __init acpi_ec_set_intr_mode(char *str)
acpi_ec_mode = EC_POLL;
}
acpi_ec_driver.ops.add = acpi_ec_add;
- printk(KERN_NOTICE PREFIX "%s mode.\n",
- intr ? "interrupt" : "polling");
+ printk(KERN_NOTICE PREFIX "%s mode.\n", intr ? "interrupt" : "polling");
return 1;
}
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
index d572700197f3..cae786ca8600 100644
--- a/drivers/acpi/events/evmisc.c
+++ b/drivers/acpi/events/evmisc.c
@@ -196,11 +196,15 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
notify_info->notify.value = (u16) notify_value;
notify_info->notify.handler_obj = handler_obj;
- acpi_ex_relinquish_interpreter();
+ acpi_ex_exit_interpreter();
acpi_ev_notify_dispatch(notify_info);
- acpi_ex_reacquire_interpreter();
+ status = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
}
if (!handler_obj) {
@@ -423,6 +427,8 @@ static acpi_status acpi_ev_remove_global_lock_handler(void)
* the global lock appear as a standard mutex on the OS side.
*
*****************************************************************************/
+static acpi_thread_id acpi_ev_global_lock_thread_id;
+static int acpi_ev_global_lock_acquired;
acpi_status acpi_ev_acquire_global_lock(u16 timeout)
{
@@ -435,11 +441,24 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
* Only one thread can acquire the GL at a time, the global_lock_mutex
* enforces this. This interface releases the interpreter if we must wait.
*/
- status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, timeout);
+ status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, 0);
+ if (status == AE_TIME) {
+ if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) {
+ acpi_ev_global_lock_acquired++;
+ return AE_OK;
+ }
+ }
+
+ if (ACPI_FAILURE(status)) {
+ status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, timeout);
+ }
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
+ acpi_ev_global_lock_thread_id = acpi_os_get_thread_id();
+ acpi_ev_global_lock_acquired++;
+
/*
* Make sure that a global lock actually exists. If not, just treat
* the lock as a standard mutex.
@@ -506,6 +525,11 @@ acpi_status acpi_ev_release_global_lock(void)
return_ACPI_STATUS(AE_NOT_ACQUIRED);
}
+ acpi_ev_global_lock_acquired--;
+ if (acpi_ev_global_lock_acquired > 0) {
+ return AE_OK;
+ }
+
if (acpi_gbl_global_lock_present) {
/* Allow any thread to release the lock */
@@ -529,7 +553,8 @@ acpi_status acpi_ev_release_global_lock(void)
acpi_gbl_global_lock_acquired = FALSE;
/* Release the local GL mutex */
-
+ acpi_ev_global_lock_thread_id = NULL;
+ acpi_ev_global_lock_acquired = 0;
acpi_os_release_mutex(acpi_gbl_global_lock_mutex);
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c
index e99f0c435a47..96b0e8431748 100644
--- a/drivers/acpi/events/evregion.c
+++ b/drivers/acpi/events/evregion.c
@@ -291,6 +291,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
u32 bit_width, acpi_integer * value)
{
acpi_status status;
+ acpi_status status2;
acpi_adr_space_handler handler;
acpi_adr_space_setup region_setup;
union acpi_operand_object *handler_desc;
@@ -344,7 +345,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
* setup will potentially execute control methods
* (e.g., _REG method for this region)
*/
- acpi_ex_relinquish_interpreter();
+ acpi_ex_exit_interpreter();
status = region_setup(region_obj, ACPI_REGION_ACTIVATE,
handler_desc->address_space.context,
@@ -352,7 +353,10 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
/* Re-enter the interpreter */
- acpi_ex_reacquire_interpreter();
+ status2 = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
+ }
/* Check for failure of the Region Setup */
@@ -405,7 +409,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
* exit the interpreter because the handler *might* block -- we don't
* know what it will do, so we can't hold the lock on the intepreter.
*/
- acpi_ex_relinquish_interpreter();
+ acpi_ex_exit_interpreter();
}
/* Call the handler */
@@ -426,7 +430,10 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
* We just returned from a non-default handler, we must re-enter the
* interpreter
*/
- acpi_ex_reacquire_interpreter();
+ status2 = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
+ }
}
return_ACPI_STATUS(status);
diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c
index 685a103a3587..a3379bafa676 100644
--- a/drivers/acpi/events/evxface.c
+++ b/drivers/acpi/events/evxface.c
@@ -768,9 +768,11 @@ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
return (AE_BAD_PARAMETER);
}
- /* Must lock interpreter to prevent race conditions */
+ status = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
- acpi_ex_enter_interpreter();
status = acpi_ev_acquire_global_lock(timeout);
acpi_ex_exit_interpreter();
diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c
index 7c38528a7e83..ae97812681a3 100644
--- a/drivers/acpi/executer/excreate.c
+++ b/drivers/acpi/executer/excreate.c
@@ -583,7 +583,10 @@ acpi_ex_create_method(u8 * aml_start,
* Get the sync_level. If method is serialized, a mutex will be
* created for this method when it is parsed.
*/
- if (method_flags & AML_METHOD_SERIALIZED) {
+ if (acpi_gbl_all_methods_serialized) {
+ obj_desc->method.sync_level = 0;
+ obj_desc->method.method_flags |= AML_METHOD_SERIALIZED;
+ } else if (method_flags & AML_METHOD_SERIALIZED) {
/*
* ACPI 1.0: sync_level = 0
* ACPI 2.0: sync_level = sync_level in method declaration
diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c
index 9460baff3032..b2edf620ba89 100644
--- a/drivers/acpi/executer/exsystem.c
+++ b/drivers/acpi/executer/exsystem.c
@@ -66,6 +66,7 @@ ACPI_MODULE_NAME("exsystem")
acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout)
{
acpi_status status;
+ acpi_status status2;
ACPI_FUNCTION_TRACE(ex_system_wait_semaphore);
@@ -78,7 +79,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout)
/* We must wait, so unlock the interpreter */
- acpi_ex_relinquish_interpreter();
+ acpi_ex_exit_interpreter();
status = acpi_os_wait_semaphore(semaphore, 1, timeout);
@@ -88,7 +89,13 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout)
/* Reacquire the interpreter */
- acpi_ex_reacquire_interpreter();
+ status2 = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status2)) {
+
+ /* Report fatal error, could not acquire interpreter */
+
+ return_ACPI_STATUS(status2);
+ }
}
return_ACPI_STATUS(status);
@@ -112,6 +119,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout)
acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout)
{
acpi_status status;
+ acpi_status status2;
ACPI_FUNCTION_TRACE(ex_system_wait_mutex);
@@ -124,7 +132,7 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout)
/* We must wait, so unlock the interpreter */
- acpi_ex_relinquish_interpreter();
+ acpi_ex_exit_interpreter();
status = acpi_os_acquire_mutex(mutex, timeout);
@@ -134,7 +142,13 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout)
/* Reacquire the interpreter */
- acpi_ex_reacquire_interpreter();
+ status2 = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status2)) {
+
+ /* Report fatal error, could not acquire interpreter */
+
+ return_ACPI_STATUS(status2);
+ }
}
return_ACPI_STATUS(status);
@@ -195,18 +209,20 @@ acpi_status acpi_ex_system_do_stall(u32 how_long)
acpi_status acpi_ex_system_do_suspend(acpi_integer how_long)
{
+ acpi_status status;
+
ACPI_FUNCTION_ENTRY();
/* Since this thread will sleep, we must release the interpreter */
- acpi_ex_relinquish_interpreter();
+ acpi_ex_exit_interpreter();
acpi_os_sleep(how_long);
/* And now we must get the interpreter again */
- acpi_ex_reacquire_interpreter();
- return (AE_OK);
+ status = acpi_ex_enter_interpreter();
+ return (status);
}
/*******************************************************************************
diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c
index 6b0aeccbb69b..aea461f3a48c 100644
--- a/drivers/acpi/executer/exutils.c
+++ b/drivers/acpi/executer/exutils.c
@@ -76,15 +76,14 @@ static u32 acpi_ex_digits_needed(acpi_integer value, u32 base);
*
* PARAMETERS: None
*
- * RETURN: None
+ * RETURN: Status
*
- * DESCRIPTION: Enter the interpreter execution region. Failure to enter
- * the interpreter region is a fatal system error. Used in
- * conjunction with exit_interpreter.
+ * DESCRIPTION: Enter the interpreter execution region. Failure to enter
+ * the interpreter region is a fatal system error
*
******************************************************************************/
-void acpi_ex_enter_interpreter(void)
+acpi_status acpi_ex_enter_interpreter(void)
{
acpi_status status;
@@ -92,42 +91,10 @@ void acpi_ex_enter_interpreter(void)
status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
if (ACPI_FAILURE(status)) {
- ACPI_ERROR((AE_INFO,
- "Could not acquire AML Interpreter mutex"));
+ ACPI_ERROR((AE_INFO, "Could not acquire interpreter mutex"));
}
- return_VOID;
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ex_reacquire_interpreter
- *
- * PARAMETERS: None
- *
- * RETURN: None
- *
- * DESCRIPTION: Reacquire the interpreter execution region from within the
- * interpreter code. Failure to enter the interpreter region is a
- * fatal system error. Used in conjuction with
- * relinquish_interpreter
- *
- ******************************************************************************/
-
-void acpi_ex_reacquire_interpreter(void)
-{
- ACPI_FUNCTION_TRACE(ex_reacquire_interpreter);
-
- /*
- * If the global serialized flag is set, do not release the interpreter,
- * since it was not actually released by acpi_ex_relinquish_interpreter.
- * This forces the interpreter to be single threaded.
- */
- if (!acpi_gbl_all_methods_serialized) {
- acpi_ex_enter_interpreter();
- }
-
- return_VOID;
+ return_ACPI_STATUS(status);
}
/*******************************************************************************
@@ -138,9 +105,17 @@ void acpi_ex_reacquire_interpreter(void)
*
* RETURN: None
*
- * DESCRIPTION: Exit the interpreter execution region. This is the top level
- * routine used to exit the interpreter when all processing has
- * been completed.
+ * DESCRIPTION: Exit the interpreter execution region
+ *
+ * Cases where the interpreter is unlocked:
+ * 1) Completion of the execution of a control method
+ * 2) Method blocked on a Sleep() AML opcode
+ * 3) Method blocked on an Acquire() AML opcode
+ * 4) Method blocked on a Wait() AML opcode
+ * 5) Method blocked to acquire the global lock
+ * 6) Method blocked to execute a serialized control method that is
+ * already executing
+ * 7) About to invoke a user-installed opregion handler
*
******************************************************************************/
@@ -152,46 +127,7 @@ void acpi_ex_exit_interpreter(void)
status = acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
if (ACPI_FAILURE(status)) {
- ACPI_ERROR((AE_INFO,
- "Could not release AML Interpreter mutex"));
- }
-
- return_VOID;
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ex_relinquish_interpreter
- *
- * PARAMETERS: None
- *
- * RETURN: None
- *
- * DESCRIPTION: Exit the interpreter execution region, from within the
- * interpreter - before attempting an operation that will possibly
- * block the running thread.
- *
- * Cases where the interpreter is unlocked internally
- * 1) Method to be blocked on a Sleep() AML opcode
- * 2) Method to be blocked on an Acquire() AML opcode
- * 3) Method to be blocked on a Wait() AML opcode
- * 4) Method to be blocked to acquire the global lock
- * 5) Method to be blocked waiting to execute a serialized control method
- * that is currently executing
- * 6) About to invoke a user-installed opregion handler
- *
- ******************************************************************************/
-
-void acpi_ex_relinquish_interpreter(void)
-{
- ACPI_FUNCTION_TRACE(ex_relinquish_interpreter);
-
- /*
- * If the global serialized flag is set, do not release the interpreter.
- * This forces the interpreter to be single threaded.
- */
- if (!acpi_gbl_all_methods_serialized) {
- acpi_ex_exit_interpreter();
+ ACPI_ERROR((AE_INFO, "Could not release interpreter mutex"));
}
return_VOID;
@@ -205,8 +141,8 @@ void acpi_ex_relinquish_interpreter(void)
*
* RETURN: none
*
- * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is
- * 32-bit, as determined by the revision of the DSDT.
+ * DESCRIPTION: Truncate a number to 32-bits if the currently executing method
+ * belongs to a 32-bit ACPI table.
*
******************************************************************************/
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
index 8fa93125fd4c..c84b1faba28c 100644
--- a/drivers/acpi/hardware/hwsleep.c
+++ b/drivers/acpi/hardware/hwsleep.c
@@ -300,6 +300,11 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
/*
* 2) Enable all wakeup GPEs
*/
+ status = acpi_hw_disable_all_gpes();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
acpi_gbl_system_awake_and_running = FALSE;
status = acpi_hw_enable_all_wakeup_gpes();
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c
index 4cc534e36e81..dc1096608f43 100644
--- a/drivers/acpi/ibm_acpi.c
+++ b/drivers/acpi/ibm_acpi.c
@@ -86,6 +86,7 @@
#include <linux/proc_fs.h>
#include <linux/backlight.h>
+#include <linux/fb.h>
#include <asm/uaccess.h>
#include <linux/dmi.h>
@@ -157,6 +158,7 @@ IBM_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */
"\\_SB.PCI.ISA.SLCE", /* 570 */
); /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */
#endif
+#ifdef CONFIG_ACPI_IBM_BAY
IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST", /* 570 */
"\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */
"\\_SB.PCI0.SATA.SCND.MSTR", /* T60, X60, Z60 */
@@ -174,6 +176,7 @@ IBM_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV", /* A3x, R32 */
IBM_HANDLE(bay2_ej, bay2, "_EJ3", /* 600e/x, 770e, A3x */
"_EJ0", /* 770x */
); /* all others */
+#endif /* CONFIG_ACPI_IBM_BAY */
/* don't list other alternatives as we install a notify handler on the 570 */
IBM_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */
@@ -1044,6 +1047,7 @@ static int light_write(char *buf)
return 0;
}
+#if defined(CONFIG_ACPI_IBM_DOCK) || defined(CONFIG_ACPI_IBM_BAY)
static int _sta(acpi_handle handle)
{
int status;
@@ -1053,6 +1057,7 @@ static int _sta(acpi_handle handle)
return status;
}
+#endif
#ifdef CONFIG_ACPI_IBM_DOCK
#define dock_docked() (_sta(dock_handle) & 1)
@@ -1119,6 +1124,7 @@ static void dock_notify(struct ibm_struct *ibm, u32 event)
}
#endif
+#ifdef CONFIG_ACPI_IBM_BAY
static int bay_status_supported;
static int bay_status2_supported;
static int bay_eject_supported;
@@ -1194,6 +1200,7 @@ static void bay_notify(struct ibm_struct *ibm, u32 event)
{
acpi_bus_generate_event(ibm->device, event, 0);
}
+#endif /* CONFIG_ACPI_IBM_BAY */
static int cmos_read(char *p)
{
@@ -1701,7 +1708,10 @@ static int brightness_write(char *buf)
static int brightness_update_status(struct backlight_device *bd)
{
- return brightness_set(bd->props.brightness);
+ return brightness_set(
+ (bd->props.fb_blank == FB_BLANK_UNBLANK &&
+ bd->props.power == FB_BLANK_UNBLANK) ?
+ bd->props.brightness : 0);
}
static struct backlight_ops ibm_backlight_data = {
@@ -1711,6 +1721,12 @@ static struct backlight_ops ibm_backlight_data = {
static int brightness_init(void)
{
+ int b;
+
+ b = brightness_get(NULL);
+ if (b < 0)
+ return b;
+
ibm_backlight_device = backlight_device_register("ibm", NULL, NULL,
&ibm_backlight_data);
if (IS_ERR(ibm_backlight_device)) {
@@ -1718,7 +1734,9 @@ static int brightness_init(void)
return PTR_ERR(ibm_backlight_device);
}
- ibm_backlight_device->props.max_brightness = 7;
+ ibm_backlight_device->props.max_brightness = 7;
+ ibm_backlight_device->props.brightness = b;
+ backlight_update_status(ibm_backlight_device);
return 0;
}
@@ -2353,6 +2371,7 @@ static struct ibm_struct ibms[] = {
.type = ACPI_SYSTEM_NOTIFY,
},
#endif
+#ifdef CONFIG_ACPI_IBM_BAY
{
.name = "bay",
.init = bay_init,
@@ -2362,6 +2381,7 @@ static struct ibm_struct ibms[] = {
.handle = &bay_handle,
.type = ACPI_SYSTEM_NOTIFY,
},
+#endif /* CONFIG_ACPI_IBM_BAY */
{
.name = "cmos",
.read = cmos_read,
@@ -2487,7 +2507,7 @@ static int __init setup_notify(struct ibm_struct *ibm)
ret = acpi_bus_get_device(*ibm->handle, &ibm->device);
if (ret < 0) {
printk(IBM_ERR "%s device not present\n", ibm->name);
- return 0;
+ return -ENODEV;
}
acpi_driver_data(ibm->device) = ibm;
@@ -2496,8 +2516,13 @@ static int __init setup_notify(struct ibm_struct *ibm)
status = acpi_install_notify_handler(*ibm->handle, ibm->type,
dispatch_notify, ibm);
if (ACPI_FAILURE(status)) {
- printk(IBM_ERR "acpi_install_notify_handler(%s) failed: %d\n",
- ibm->name, status);
+ if (status == AE_ALREADY_EXISTS) {
+ printk(IBM_NOTICE "another device driver is already handling %s events\n",
+ ibm->name);
+ } else {
+ printk(IBM_ERR "acpi_install_notify_handler(%s) failed: %d\n",
+ ibm->name, status);
+ }
return -ENODEV;
}
ibm->notify_installed = 1;
@@ -2533,6 +2558,8 @@ static int __init register_driver(struct ibm_struct *ibm)
return ret;
}
+static void ibm_exit(struct ibm_struct *ibm);
+
static int __init ibm_init(struct ibm_struct *ibm)
{
int ret;
@@ -2574,6 +2601,12 @@ static int __init ibm_init(struct ibm_struct *ibm)
if (ibm->notify) {
ret = setup_notify(ibm);
+ if (ret == -ENODEV) {
+ printk(IBM_NOTICE "disabling subdriver %s\n",
+ ibm->name);
+ ibm_exit(ibm);
+ return 0;
+ }
if (ret < 0)
return ret;
}
@@ -2647,7 +2680,9 @@ IBM_PARAM(light);
#ifdef CONFIG_ACPI_IBM_DOCK
IBM_PARAM(dock);
#endif
+#ifdef CONFIG_ACPI_IBM_BAY
IBM_PARAM(bay);
+#endif /* CONFIG_ACPI_IBM_BAY */
IBM_PARAM(cmos);
IBM_PARAM(led);
IBM_PARAM(beep);
@@ -2723,12 +2758,14 @@ static int __init acpi_ibm_init(void)
IBM_HANDLE_INIT(dock);
#endif
IBM_HANDLE_INIT(pci);
+#ifdef CONFIG_ACPI_IBM_BAY
IBM_HANDLE_INIT(bay);
if (bay_handle)
IBM_HANDLE_INIT(bay_ej);
IBM_HANDLE_INIT(bay2);
if (bay2_handle)
IBM_HANDLE_INIT(bay2_ej);
+#endif /* CONFIG_ACPI_IBM_BAY */
IBM_HANDLE_INIT(beep);
IBM_HANDLE_INIT(ecrd);
IBM_HANDLE_INIT(ecwr);
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
index aa6370c67ec1..26fd0dd6953d 100644
--- a/drivers/acpi/namespace/nseval.c
+++ b/drivers/acpi/namespace/nseval.c
@@ -154,7 +154,11 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info)
* Execute the method via the interpreter. The interpreter is locked
* here before calling into the AML parser
*/
- acpi_ex_enter_interpreter();
+ status = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
status = acpi_ps_execute_method(info);
acpi_ex_exit_interpreter();
} else {
@@ -178,7 +182,10 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info)
* resolution, we must lock it because we could access an opregion.
* The opregion access code assumes that the interpreter is locked.
*/
- acpi_ex_enter_interpreter();
+ status = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
/* Function has a strange interface */
diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c
index 33db2241044e..c4ab615f77fe 100644
--- a/drivers/acpi/namespace/nsinit.c
+++ b/drivers/acpi/namespace/nsinit.c
@@ -214,7 +214,7 @@ acpi_ns_init_one_object(acpi_handle obj_handle,
u32 level, void *context, void **return_value)
{
acpi_object_type type;
- acpi_status status = AE_OK;
+ acpi_status status;
struct acpi_init_walk_info *info =
(struct acpi_init_walk_info *)context;
struct acpi_namespace_node *node =
@@ -268,7 +268,10 @@ acpi_ns_init_one_object(acpi_handle obj_handle,
/*
* Must lock the interpreter before executing AML code
*/
- acpi_ex_enter_interpreter();
+ status = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
/*
* Each of these types can contain executable AML code within the
diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c
index 7ac6ace50059..8904d0fae6a2 100644
--- a/drivers/acpi/namespace/nsxfeval.c
+++ b/drivers/acpi/namespace/nsxfeval.c
@@ -170,6 +170,7 @@ acpi_evaluate_object(acpi_handle handle,
struct acpi_buffer *return_buffer)
{
acpi_status status;
+ acpi_status status2;
struct acpi_evaluate_info *info;
acpi_size buffer_space_needed;
u32 i;
@@ -328,12 +329,14 @@ acpi_evaluate_object(acpi_handle handle,
* Delete the internal return object. NOTE: Interpreter must be
* locked to avoid race condition.
*/
- acpi_ex_enter_interpreter();
+ status2 = acpi_ex_enter_interpreter();
+ if (ACPI_SUCCESS(status2)) {
- /* Remove one reference on the return object (should delete it) */
+ /* Remove one reference on the return object (should delete it) */
- acpi_ut_remove_reference(info->return_object);
- acpi_ex_exit_interpreter();
+ acpi_ut_remove_reference(info->return_object);
+ acpi_ex_exit_interpreter();
+ }
}
cleanup:
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 1ef338545dfe..4ffecd179702 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -436,8 +436,6 @@ int acpi_power_transition(struct acpi_device *device, int state)
cl = &device->power.states[device->power.state].resources;
tl = &device->power.states[state].resources;
- device->power.state = ACPI_STATE_UNKNOWN;
-
if (!cl->count && !tl->count) {
result = -ENODEV;
goto end;
@@ -468,12 +466,15 @@ int acpi_power_transition(struct acpi_device *device, int state)
goto end;
}
- /* We shouldn't change the state till all above operations succeed */
- device->power.state = state;
- end:
- if (result)
+ end:
+ if (result) {
+ device->power.state = ACPI_STATE_UNKNOWN;
printk(KERN_WARNING PREFIX "Transitioning device [%s] to D%d\n",
device->pnp.bus_id, state);
+ } else {
+ /* We shouldn't change the state till all above operations succeed */
+ device->power.state = state;
+ }
return result;
}
@@ -687,13 +688,6 @@ static int acpi_power_resume(struct acpi_device *device)
return result;
mutex_lock(&resource->resource_lock);
- if ((resource->state == ACPI_POWER_RESOURCE_STATE_ON) &&
- list_empty(&resource->reference)) {
- mutex_unlock(&resource->resource_lock);
- result = acpi_power_off_device(device->handle, NULL);
- return result;
- }
-
if ((resource->state == ACPI_POWER_RESOURCE_STATE_OFF) &&
!list_empty(&resource->reference)) {
ref = container_of(resource->reference.next, struct acpi_power_reference, node);
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 60773005b8af..cdf78943af4d 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -268,6 +268,7 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr,
struct acpi_processor_cx *cx)
{
struct acpi_processor_power *pwr = &pr->power;
+ u8 type = local_apic_timer_c2_ok ? ACPI_STATE_C3 : ACPI_STATE_C2;
/*
* Check, if one of the previous states already marked the lapic
@@ -276,7 +277,7 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr,
if (pwr->timer_broadcast_on_state < state)
return;
- if (cx->type >= ACPI_STATE_C2)
+ if (cx->type >= type)
pr->power.timer_broadcast_on_state = state;
}
diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c
index 1358c06a969c..cc48ab05676c 100644
--- a/drivers/acpi/resources/rscreate.c
+++ b/drivers/acpi/resources/rscreate.c
@@ -191,6 +191,9 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);
for (index = 0; index < number_of_elements; index++) {
+ int source_name_index = 2;
+ int source_index_index = 3;
+
/*
* Point user_prt past this current structure
*
@@ -261,10 +264,28 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
}
/*
+ * If BIOS erroneously reversed the _PRT source_name and source_index,
+ * then reverse them back.
+ */
+ if (ACPI_GET_OBJECT_TYPE (sub_object_list[3]) != ACPI_TYPE_INTEGER) {
+ if (acpi_gbl_enable_interpreter_slack) {
+ source_name_index = 3;
+ source_index_index = 2;
+ printk(KERN_WARNING "ACPI: Handling Garbled _PRT entry\n");
+ } else {
+ ACPI_ERROR((AE_INFO,
+ "(PRT[%X].source_index) Need Integer, found %s",
+ index,
+ acpi_ut_get_object_type_name(sub_object_list[3])));
+ return_ACPI_STATUS(AE_BAD_DATA);
+ }
+ }
+
+ /*
* 3) Third subobject: Dereference the PRT.source_name
* The name may be unresolved (slack mode), so allow a null object
*/
- obj_desc = sub_object_list[2];
+ obj_desc = sub_object_list[source_name_index];
if (obj_desc) {
switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_LOCAL_REFERENCE:
@@ -339,7 +360,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
/* 4) Fourth subobject: Dereference the PRT.source_index */
- obj_desc = sub_object_list[3];
+ obj_desc = sub_object_list[source_index_index];
if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
user_prt->source_index = (u32) obj_desc->integer.value;
} else {
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 849e2c361804..c3419182c9a7 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -42,7 +42,9 @@ static char *mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" };
static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata;
-void acpi_table_print_madt_entry(struct acpi_subtable_header * header)
+static int acpi_apic_instance __initdata;
+
+void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
{
if (!header)
return;
@@ -183,8 +185,10 @@ acpi_table_parse_entries(char *id,
if (!handler)
return -EINVAL;
- /* Locate the table (if exists). There should only be one. */
- acpi_get_table(id, 0, &table_header);
+ if (strncmp(id, ACPI_SIG_MADT, 4) == 0)
+ acpi_get_table(id, acpi_apic_instance, &table_header);
+ else
+ acpi_get_table(id, 0, &table_header);
if (!table_header) {
printk(KERN_WARNING PREFIX "%4.4s not present\n", id);
@@ -237,10 +241,15 @@ acpi_table_parse_madt(enum acpi_madt_type id,
int __init acpi_table_parse(char *id, acpi_table_handler handler)
{
struct acpi_table_header *table = NULL;
+
if (!handler)
return -EINVAL;
- acpi_get_table(id, 0, &table);
+ if (strncmp(id, ACPI_SIG_MADT, 4) == 0)
+ acpi_get_table(id, acpi_apic_instance, &table);
+ else
+ acpi_get_table(id, 0, &table);
+
if (table) {
handler(table);
return 0;
@@ -248,6 +257,31 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler)
return 1;
}
+/*
+ * The BIOS is supposed to supply a single APIC/MADT,
+ * but some report two. Provide a knob to use either.
+ * (don't you wish instance 0 and 1 were not the same?)
+ */
+static void __init check_multiple_madt(void)
+{
+ struct acpi_table_header *table = NULL;
+
+ acpi_get_table(ACPI_SIG_MADT, 2, &table);
+ if (table) {
+ printk(KERN_WARNING PREFIX
+ "BIOS bug: multiple APIC/MADT found,"
+ " using %d\n", acpi_apic_instance);
+ printk(KERN_WARNING PREFIX
+ "If \"acpi_apic_instance=%d\" works better, "
+ "notify linux-acpi@vger.kernel.org\n",
+ acpi_apic_instance ? 0 : 2);
+
+ } else
+ acpi_apic_instance = 0;
+
+ return;
+}
+
/*
* acpi_table_init()
*
@@ -257,9 +291,22 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler)
* result: sdt_entry[] is initialized
*/
-
int __init acpi_table_init(void)
{
acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
+ check_multiple_madt();
+ return 0;
+}
+
+static int __init acpi_parse_apic_instance(char *str)
+{
+
+ acpi_apic_instance = simple_strtoul(str, NULL, 0);
+
+ printk(KERN_NOTICE PREFIX "Shall use APIC/MADT table %d\n",
+ acpi_apic_instance);
+
return 0;
}
+
+early_param("acpi_apic_instance", acpi_parse_apic_instance);
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 0771b434feb2..00d25b347255 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -102,9 +102,9 @@ struct acpi_video_bus_cap {
struct acpi_video_device_attrib {
u32 display_index:4; /* A zero-based instance of the Display */
- u32 display_port_attachment:4; /*This field differenates displays type */
+ u32 display_port_attachment:4; /*This field differentiates the display type */
u32 display_type:4; /*Describe the specific type in use */
- u32 vendor_specific:4; /*Chipset Vendor Specifi */
+ u32 vendor_specific:4; /*Chipset Vendor Specific */
u32 bios_can_detect:1; /*BIOS can detect the device */
u32 depend_on_vga:1; /*Non-VGA output device whose power is related to
the VGA device. */
@@ -484,16 +484,16 @@ acpi_video_bus_POST_options(struct acpi_video_bus *video,
* 0. The system BIOS should NOT automatically switch(toggle)
* the active display output.
* 1. The system BIOS should automatically switch (toggle) the
- * active display output. No swich event.
+ * active display output. No switch event.
* 2. The _DGS value should be locked.
* 3. The system BIOS should not automatically switch (toggle) the
* active display output, but instead generate the display switch
* event notify code.
* lcd_flag :
* 0. The system BIOS should automatically control the brightness level
- * of the LCD, when the power changes from AC to DC
+ * of the LCD when the power changes from AC to DC
* 1. The system BIOS should NOT automatically control the brightness
- * level of the LCD, when the power changes from AC to DC.
+ * level of the LCD when the power changes from AC to DC.
* Return Value:
* -1 wrong arg.
*/
@@ -525,7 +525,7 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
* Return Value:
* None
*
- * Find out all required AML method defined under the output
+ * Find out all required AML methods defined under the output
* device.
*/
@@ -636,7 +636,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
* Return Value:
* None
*
- * Find out all required AML method defined under the video bus device.
+ * Find out all required AML methods defined under the video bus device.
*/
static void acpi_video_bus_find_cap(struct acpi_video_bus *video)
@@ -681,19 +681,19 @@ static int acpi_video_bus_check(struct acpi_video_bus *video)
* to check well known required nodes.
*/
- /* Does this device able to support video switching ? */
+ /* Does this device support video switching? */
if (video->cap._DOS) {
video->flags.multihead = 1;
status = 0;
}
- /* Does this device able to retrieve a retrieve a video ROM ? */
+ /* Does this device support retrieving a video ROM? */
if (video->cap._ROM) {
video->flags.rom = 1;
status = 0;
}
- /* Does this device able to configure which video device to POST ? */
+ /* Does this device support configuring which video device to POST? */
if (video->cap._GPD && video->cap._SPD && video->cap._VPO) {
video->flags.post = 1;
status = 0;
@@ -860,7 +860,7 @@ acpi_video_device_write_brightness(struct file *file,
if (level > 100)
return -EFAULT;
- /* validate though the list of available levels */
+ /* validate through the list of available levels */
for (i = 0; i < dev->brightness->count; i++)
if (level == dev->brightness->levels[i]) {
if (ACPI_SUCCESS
@@ -1065,10 +1065,10 @@ static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
printk(KERN_WARNING PREFIX
"The motherboard VGA device is not listed as a possible POST device.\n");
printk(KERN_WARNING PREFIX
- "This indicate a BIOS bug. Please contact the manufacturer.\n");
+ "This indicates a BIOS bug. Please contact the manufacturer.\n");
}
printk("%lx\n", options);
- seq_printf(seq, "can POST: <intgrated video>");
+ seq_printf(seq, "can POST: <integrated video>");
if (options & 2)
seq_printf(seq, " <PCI video>");
if (options & 4)
@@ -1102,7 +1102,7 @@ static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset)
seq_printf(seq, "<not supported>\n");
goto end;
}
- seq_printf(seq, "device posted is <%s>\n", device_decode[id & 3]);
+ seq_printf(seq, "device POSTed is <%s>\n", device_decode[id & 3]);
end:
return 0;
@@ -1156,7 +1156,7 @@ acpi_video_bus_write_POST(struct file *file,
if (opt > 3)
return -EFAULT;
- /* just in case an OEM 'forget' the motherboard... */
+ /* just in case an OEM 'forgot' the motherboard... */
options |= 1;
if (options & (1ul << opt)) {
@@ -1527,13 +1527,13 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
/*
* Arg:
* video : video bus device
- * event : Nontify Event
+ * event : notify event
*
* Return:
* < 0 : error
*
* 1. Find out the current active output device.
- * 2. Identify the next output device to switch
+ * 2. Identify the next output device to switch to.
* 3. call _DSS to do actual switch.
*/
@@ -1723,12 +1723,12 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
device = video->device;
switch (event) {
- case ACPI_VIDEO_NOTIFY_SWITCH: /* User request that a switch occur,
+ case ACPI_VIDEO_NOTIFY_SWITCH: /* User requested a switch,
* most likely via hotkey. */
acpi_bus_generate_event(device, event, 0);
break;
- case ACPI_VIDEO_NOTIFY_PROBE: /* User plug or remove a video
+ case ACPI_VIDEO_NOTIFY_PROBE: /* User plugged in or removed a video
* connector. */
acpi_video_device_enumerate(video);
acpi_video_device_rebind(video);
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index d16b5b0c8b76..7bdbe5a914d0 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -564,7 +564,7 @@ config PATA_IXP4XX_CF
config PATA_SCC
tristate "Toshiba's Cell Reference Set IDE support"
- depends on PCI && PPC_IBM_CELL_BLADE
+ depends on PCI && PPC_CELLEB
help
This option enables support for the built-in IDE controller on
Toshiba Cell Reference Board.
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index dc7b56225923..fd27227771b4 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -80,6 +80,7 @@ enum {
board_ahci_pi = 1,
board_ahci_vt8251 = 2,
board_ahci_ign_iferr = 3,
+ board_ahci_sb600 = 4,
/* global controller registers */
HOST_CAP = 0x00, /* host capabilities */
@@ -168,6 +169,7 @@ enum {
AHCI_FLAG_NO_NCQ = (1 << 24),
AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 25), /* ignore IRQ_IF_ERR */
AHCI_FLAG_HONOR_PI = (1 << 26), /* honor PORTS_IMPL */
+ AHCI_FLAG_IGN_SERR_INTERNAL = (1 << 27), /* ignore SERR_INTERNAL */
};
struct ahci_cmd_hdr {
@@ -362,6 +364,18 @@ static const struct ata_port_info ahci_port_info[] = {
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &ahci_ops,
},
+ /* board_ahci_sb600 */
+ {
+ .sht = &ahci_sht,
+ .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+ ATA_FLAG_SKIP_D2H_BSY |
+ AHCI_FLAG_IGN_SERR_INTERNAL,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .port_ops = &ahci_ops,
+ },
+
};
static const struct pci_device_id ahci_pci_tbl[] = {
@@ -399,7 +413,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
/* ATI */
- { PCI_VDEVICE(ATI, 0x4380), board_ahci }, /* ATI SB600 non-raid */
+ { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 non-raid */
{ PCI_VDEVICE(ATI, 0x4381), board_ahci }, /* ATI SB600 raid */
/* VIA */
@@ -1067,8 +1081,11 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
if (ap->flags & AHCI_FLAG_IGN_IRQ_IF_ERR)
irq_stat &= ~PORT_IRQ_IF_ERR;
- if (irq_stat & PORT_IRQ_TF_ERR)
+ if (irq_stat & PORT_IRQ_TF_ERR) {
err_mask |= AC_ERR_DEV;
+ if (ap->flags & AHCI_FLAG_IGN_SERR_INTERNAL)
+ serror &= ~SERR_INTERNAL;
+ }
if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
err_mask |= AC_ERR_HOST_BUS;
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index dc42ba1b46f7..b952c584338f 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -93,7 +93,7 @@
#include <linux/libata.h>
#define DRV_NAME "ata_piix"
-#define DRV_VERSION "2.10"
+#define DRV_VERSION "2.10ac1"
enum {
PIIX_IOCFG = 0x54, /* IDE I/O configuration register */
@@ -667,14 +667,9 @@ static int ich_pata_prereset(struct ata_port *ap)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no])) {
- ata_port_printk(ap, KERN_INFO, "port disabled. ignoring.\n");
- ap->eh_context.i.action &= ~ATA_EH_RESET_MASK;
- return 0;
- }
-
+ if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no]))
+ return -ENOENT;
ich_pata_cbl_detect(ap);
-
return ata_std_prereset(ap);
}
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index d14a48e75f1b..03a0acff6cfa 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -34,6 +34,13 @@ struct taskfile_array {
u8 tfa[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */
};
+/*
+ * Helper - belongs in the PCI layer somewhere eventually
+ */
+static int is_pci_dev(struct device *dev)
+{
+ return (dev->bus == &pci_bus_type);
+}
/**
* sata_get_dev_handle - finds acpi_handle and PCI device.function
@@ -53,6 +60,9 @@ static int sata_get_dev_handle(struct device *dev, acpi_handle *handle,
struct pci_dev *pci_dev;
acpi_integer addr;
+ if (!is_pci_dev(dev))
+ return -ENODEV;
+
pci_dev = to_pci_dev(dev); /* NOTE: PCI-specific */
/* Please refer to the ACPI spec for the syntax of _ADR. */
addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
@@ -84,7 +94,12 @@ static int pata_get_dev_handle(struct device *dev, acpi_handle *handle,
acpi_status status;
struct acpi_device_info *dinfo = NULL;
int ret = -ENODEV;
- struct pci_dev *pdev = to_pci_dev(dev);
+ struct pci_dev *pdev;
+
+ if (!is_pci_dev(dev))
+ return -ENODEV;
+
+ pdev = to_pci_dev(dev);
bus = pdev->bus->number;
devnum = PCI_SLOT(pdev->devfn);
@@ -290,7 +305,7 @@ static int do_drive_get_GTF(struct ata_port *ap, int ix,
*gtf_address = 0UL;
*obj_loc = 0UL;
- if (noacpi)
+ if (libata_noacpi)
return 0;
if (ata_msg_probe(ap))
@@ -516,7 +531,7 @@ static int do_drive_set_taskfiles(struct ata_port *ap,
ata_dev_printk(atadev, KERN_DEBUG, "%s: ENTER: port#: %d\n",
__FUNCTION__, ap->port_no);
- if (noacpi || !(ap->cbl == ATA_CBL_SATA))
+ if (libata_noacpi || !(ap->cbl == ATA_CBL_SATA))
return 0;
if (!ata_dev_enabled(atadev) || (ap->flags & ATA_FLAG_DISABLED))
@@ -559,7 +574,14 @@ int ata_acpi_exec_tfs(struct ata_port *ap)
unsigned long gtf_address;
unsigned long obj_loc;
- if (noacpi)
+ if (libata_noacpi)
+ return 0;
+ /*
+ * TBD - implement PATA support. For now,
+ * we should not run GTF on PATA devices since some
+ * PATA require execution of GTM/STM before GTF.
+ */
+ if (!(ap->cbl == ATA_CBL_SATA))
return 0;
for (ix = 0; ix < ATA_MAX_DEVICES; ix++) {
@@ -614,7 +636,7 @@ int ata_acpi_push_id(struct ata_port *ap, unsigned int ix)
struct acpi_object_list input;
union acpi_object in_params[1];
- if (noacpi)
+ if (libata_noacpi)
return 0;
if (ata_msg_probe(ap))
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index dc362fa01ca4..0abd72d0dec2 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -93,8 +93,8 @@ static int ata_probe_timeout = ATA_TMOUT_INTERNAL / HZ;
module_param(ata_probe_timeout, int, 0444);
MODULE_PARM_DESC(ata_probe_timeout, "Set ATA probing timeout (seconds)");
-int noacpi;
-module_param(noacpi, int, 0444);
+int libata_noacpi = 1;
+module_param_named(noacpi, libata_noacpi, int, 0444);
MODULE_PARM_DESC(noacpi, "Disables the use of ACPI in suspend/resume when set");
MODULE_AUTHOR("Jeff Garzik");
@@ -826,7 +826,7 @@ static u64 ata_id_n_sectors(const u16 *id)
/**
* ata_id_to_dma_mode - Identify DMA mode from id block
* @dev: device to identify
- * @mode: mode to assume if we cannot tell
+ * @unknown: mode to assume if we cannot tell
*
* Set up the timing values for the device based upon the identify
* reported values for the DMA mode. This function is used by drivers
@@ -1784,6 +1784,13 @@ int ata_dev_configure(struct ata_device *dev)
dev->max_sectors = ATA_MAX_SECTORS;
}
+ if (ata_device_blacklisted(dev) & ATA_HORKAGE_MAX_SEC_128)
+ dev->max_sectors = min(ATA_MAX_SECTORS_128, dev->max_sectors);
+
+ /* limit ATAPI DMA to R/W commands only */
+ if (ata_device_blacklisted(dev) & ATA_HORKAGE_DMA_RW_ONLY)
+ dev->horkage |= ATA_HORKAGE_DMA_RW_ONLY;
+
if (ap->ops->dev_config)
ap->ops->dev_config(ap, dev);
@@ -3352,6 +3359,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "_NEC DV5800A", NULL, ATA_HORKAGE_NODMA },
{ "SAMSUNG CD-ROM SN-124","N001", ATA_HORKAGE_NODMA },
+ /* Weird ATAPI devices */
+ { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 |
+ ATA_HORKAGE_DMA_RW_ONLY },
+
/* Devices we expect to fail diagnostics */
/* Devices where NCQ should be avoided */
@@ -3359,6 +3370,15 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "WDC WD740ADFD-00", NULL, ATA_HORKAGE_NONCQ },
/* http://thread.gmane.org/gmane.linux.ide/14907 */
{ "FUJITSU MHT2060BH", NULL, ATA_HORKAGE_NONCQ },
+ /* NCQ is broken */
+ { "Maxtor 6L250S0", "BANC1G10", ATA_HORKAGE_NONCQ },
+ /* NCQ hard hangs device under heavier load, needs hard power cycle */
+ { "Maxtor 6B250S0", "BANC1B70", ATA_HORKAGE_NONCQ },
+ /* Blacklist entries taken from Silicon Image 3124/3132
+ Windows driver .inf file - also several Linux problem reports */
+ { "HTS541060G9SA00", "MB3OC60D", ATA_HORKAGE_NONCQ, },
+ { "HTS541080G9SA00", "MB4OC60D", ATA_HORKAGE_NONCQ, },
+ { "HTS541010G9SA00", "MBZOC60D", ATA_HORKAGE_NONCQ, },
/* Devices with NCQ limits */
@@ -3455,7 +3475,8 @@ static void ata_dev_xfermask(struct ata_device *dev)
"device is on DMA blacklist, disabling DMA\n");
}
- if ((host->flags & ATA_HOST_SIMPLEX) && host->simplex_claimed != ap) {
+ if ((host->flags & ATA_HOST_SIMPLEX) &&
+ host->simplex_claimed && host->simplex_claimed != ap) {
xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
ata_dev_printk(dev, KERN_WARNING, "simplex DMA is claimed by "
"other device, disabling DMA\n");
@@ -3669,6 +3690,26 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc)
struct ata_port *ap = qc->ap;
int rc = 0; /* Assume ATAPI DMA is OK by default */
+ /* some drives can only do ATAPI DMA on read/write */
+ if (unlikely(qc->dev->horkage & ATA_HORKAGE_DMA_RW_ONLY)) {
+ struct scsi_cmnd *cmd = qc->scsicmd;
+ u8 *scsicmd = cmd->cmnd;
+
+ switch (scsicmd[0]) {
+ case READ_10:
+ case WRITE_10:
+ case READ_12:
+ case WRITE_12:
+ case READ_6:
+ case WRITE_6:
+ /* atapi dma maybe ok */
+ break;
+ default:
+ /* turn off atapi dma */
+ return 1;
+ }
+ }
+
if (ap->ops->check_atapi_dma)
rc = ap->ops->check_atapi_dma(qc);
@@ -4712,8 +4753,8 @@ static void fill_result_tf(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
- ap->ops->tf_read(ap, &qc->result_tf);
qc->result_tf.flags = qc->tf.flags;
+ ap->ops->tf_read(ap, &qc->result_tf);
}
/**
@@ -5684,18 +5725,22 @@ static void ata_host_release(struct device *gendev, void *res)
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i];
- if (!ap)
- continue;
-
- if (ap->ops->port_stop)
+ if (ap && ap->ops->port_stop)
ap->ops->port_stop(ap);
-
- scsi_host_put(ap->scsi_host);
}
if (host->ops->host_stop)
host->ops->host_stop(host);
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+
+ if (ap)
+ scsi_host_put(ap->scsi_host);
+
+ host->ports[i] = NULL;
+ }
+
dev_set_drvdata(gendev, NULL);
}
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 7349c3dbf774..39f556c02992 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -982,26 +982,27 @@ static int ata_eh_read_log_10h(struct ata_device *dev,
* RETURNS:
* 0 on success, AC_ERR_* mask on failure
*/
-static unsigned int atapi_eh_request_sense(struct ata_device *dev,
- unsigned char *sense_buf)
+static unsigned int atapi_eh_request_sense(struct ata_queued_cmd *qc)
{
+ struct ata_device *dev = qc->dev;
+ unsigned char *sense_buf = qc->scsicmd->sense_buffer;
struct ata_port *ap = dev->ap;
struct ata_taskfile tf;
u8 cdb[ATAPI_CDB_LEN];
DPRINTK("ATAPI request sense\n");
- ata_tf_init(dev, &tf);
-
/* FIXME: is this needed? */
memset(sense_buf, 0, SCSI_SENSE_BUFFERSIZE);
- /* XXX: why tf_read here? */
- ap->ops->tf_read(ap, &tf);
-
- /* fill these in, for the case where they are -not- overwritten */
+ /* initialize sense_buf with the error register,
+ * for the case where they are -not- overwritten
+ */
sense_buf[0] = 0x70;
- sense_buf[2] = tf.feature >> 4;
+ sense_buf[2] = qc->result_tf.feature >> 4;
+
+ /* some devices time out if garbage left in tf */
+ ata_tf_init(dev, &tf);
memset(cdb, 0, ATAPI_CDB_LEN);
cdb[0] = REQUEST_SENSE;
@@ -1165,8 +1166,7 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
case ATA_DEV_ATAPI:
if (!(qc->ap->pflags & ATA_PFLAG_FROZEN)) {
- tmp = atapi_eh_request_sense(qc->dev,
- qc->scsicmd->sense_buffer);
+ tmp = atapi_eh_request_sense(qc);
if (!tmp) {
/* ATA_QCFLAG_SENSE_VALID is used to
* tell atapi_qc_complete() that sense
@@ -1625,8 +1625,14 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
rc = prereset(ap);
if (rc) {
if (rc == -ENOENT) {
- ata_port_printk(ap, KERN_DEBUG, "port disabled. ignoring.\n");
+ ata_port_printk(ap, KERN_DEBUG,
+ "port disabled. ignoring.\n");
ap->eh_context.i.action &= ~ATA_EH_RESET_MASK;
+
+ for (i = 0; i < ATA_MAX_DEVICES; i++)
+ classes[i] = ATA_DEV_NONE;
+
+ rc = 0;
} else
ata_port_printk(ap, KERN_ERR,
"prereset failed (errno=%d)\n", rc);
@@ -1737,12 +1743,17 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
{
struct ata_eh_context *ehc = &ap->eh_context;
struct ata_device *dev;
+ unsigned int new_mask = 0;
unsigned long flags;
int i, rc = 0;
DPRINTK("ENTER\n");
- for (i = 0; i < ATA_MAX_DEVICES; i++) {
+ /* For PATA drive side cable detection to work, IDENTIFY must
+ * be done backwards such that PDIAG- is released by the slave
+ * device before the master device is identified.
+ */
+ for (i = ATA_MAX_DEVICES - 1; i >= 0; i--) {
unsigned int action, readid_flags = 0;
dev = &ap->device[i];
@@ -1754,13 +1765,13 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
if (action & ATA_EH_REVALIDATE && ata_dev_ready(dev)) {
if (ata_port_offline(ap)) {
rc = -EIO;
- break;
+ goto err;
}
ata_eh_about_to_do(ap, dev, ATA_EH_REVALIDATE);
rc = ata_dev_revalidate(dev, readid_flags);
if (rc)
- break;
+ goto err;
ata_eh_done(ap, dev, ATA_EH_REVALIDATE);
@@ -1778,40 +1789,53 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
rc = ata_dev_read_id(dev, &dev->class, readid_flags,
dev->id);
- if (rc == 0) {
- ehc->i.flags |= ATA_EHI_PRINTINFO;
- rc = ata_dev_configure(dev);
- ehc->i.flags &= ~ATA_EHI_PRINTINFO;
- } else if (rc == -ENOENT) {
+ switch (rc) {
+ case 0:
+ new_mask |= 1 << i;
+ break;
+ case -ENOENT:
/* IDENTIFY was issued to non-existent
* device. No need to reset. Just
* thaw and kill the device.
*/
ata_eh_thaw_port(ap);
dev->class = ATA_DEV_UNKNOWN;
- rc = 0;
- }
-
- if (rc) {
- dev->class = ATA_DEV_UNKNOWN;
break;
+ default:
+ dev->class = ATA_DEV_UNKNOWN;
+ goto err;
}
+ }
+ }
- if (ata_dev_enabled(dev)) {
- spin_lock_irqsave(ap->lock, flags);
- ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
- spin_unlock_irqrestore(ap->lock, flags);
+ /* Configure new devices forward such that user doesn't see
+ * device detection messages backwards.
+ */
+ for (i = 0; i < ATA_MAX_DEVICES; i++) {
+ dev = &ap->device[i];
- /* new device discovered, configure xfermode */
- ehc->i.flags |= ATA_EHI_SETMODE;
- }
- }
+ if (!(new_mask & (1 << i)))
+ continue;
+
+ ehc->i.flags |= ATA_EHI_PRINTINFO;
+ rc = ata_dev_configure(dev);
+ ehc->i.flags &= ~ATA_EHI_PRINTINFO;
+ if (rc)
+ goto err;
+
+ spin_lock_irqsave(ap->lock, flags);
+ ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
+ spin_unlock_irqrestore(ap->lock, flags);
+
+ /* new device discovered, configure xfermode */
+ ehc->i.flags |= ATA_EHI_SETMODE;
}
- if (rc)
- *r_failed_dev = dev;
+ return 0;
- DPRINTK("EXIT\n");
+ err:
+ *r_failed_dev = dev;
+ DPRINTK("EXIT rc=%d\n", rc);
return rc;
}
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 6cc817a10204..e9364434182c 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -333,7 +333,7 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
scsi_cmd[8] = args[3];
scsi_cmd[10] = args[4];
scsi_cmd[12] = args[5];
- scsi_cmd[13] = args[6] & 0x0f;
+ scsi_cmd[13] = args[6] & 0x4f;
scsi_cmd[14] = args[0];
/* Good values for timeout and retries? Values below
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index c42671493e8c..1f1e3a51f859 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -56,7 +56,7 @@ extern struct workqueue_struct *ata_aux_wq;
extern int atapi_enabled;
extern int atapi_dmadir;
extern int libata_fua;
-extern int noacpi;
+extern int libata_noacpi;
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
u64 block, u32 n_block, unsigned int tf_flags,
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
index 7ef834250a43..55cc293e7487 100644
--- a/drivers/ata/pata_cs5520.c
+++ b/drivers/ata/pata_cs5520.c
@@ -208,7 +208,7 @@ static struct ata_port_operations cs5520_port_ops = {
static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
u8 pcicfg;
- void *iomap[5];
+ void __iomem *iomap[5];
static struct ata_probe_ent probe[2];
int ports = 0;
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
index 9a0523b5c947..c6f0e1927551 100644
--- a/drivers/ata/pata_ixp4xx_cf.c
+++ b/drivers/ata/pata_ixp4xx_cf.c
@@ -193,7 +193,7 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq)
- set_irq_type(irq, IRQT_HIGH);
+ set_irq_type(irq, IRQT_RISING);
/* Setup expansion bus chip selects */
*data->cs0_cfg = data->cs0_bits;
@@ -232,7 +232,6 @@ static __devexit int ixp4xx_pata_remove(struct platform_device *dev)
struct ata_host *host = platform_get_drvdata(dev);
ata_host_detach(host);
- platform_set_drvdata(dev, NULL);
return 0;
}
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
index f5d88729ca79..882c36eaf293 100644
--- a/drivers/ata/pata_mpc52xx.c
+++ b/drivers/ata/pata_mpc52xx.c
@@ -329,7 +329,7 @@ mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv)
ae->dev = dev;
ae->irq = priv->ata_irq;
- aio->cmd_addr = 0; /* Don't have a classic reg block */
+ aio->cmd_addr = NULL; /* Don't have a classic reg block */
aio->altstatus_addr = &priv->ata_regs->tf_control;
aio->ctl_addr = &priv->ata_regs->tf_control;
aio->data_addr = &priv->ata_regs->tf_data;
diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c
index acdc52cbe38a..0a1493398913 100644
--- a/drivers/ata/pata_pdc202xx_old.c
+++ b/drivers/ata/pata_pdc202xx_old.c
@@ -195,7 +195,7 @@ static void pdc2026x_bmdma_start(struct ata_queued_cmd *qc)
/* Cases the state machine will not complete correctly without help */
if ((tf->flags & ATA_TFLAG_LBA48) || tf->protocol == ATA_PROT_ATAPI_DMA)
{
- len = qc->nbytes;
+ len = qc->nbytes / 2;
if (tf->flags & ATA_TFLAG_WRITE)
len |= 0x06000000;
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
index 3193a603d1a1..1e21688bfcf2 100644
--- a/drivers/ata/sata_inic162x.c
+++ b/drivers/ata/sata_inic162x.c
@@ -672,10 +672,6 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
return rc;
- rc = pci_request_regions(pdev, DRV_NAME);
- if (rc)
- return rc;
-
rc = pcim_iomap_regions(pdev, 0x3f, DRV_NAME);
if (rc)
return rc;
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 388d07fab5f7..9d9670a9b117 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -874,8 +874,14 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
if (status & (NV_ADMA_STAT_DONE |
NV_ADMA_STAT_CPBERR)) {
- u32 check_commands = notifier | notifier_error;
+ u32 check_commands;
int pos, error = 0;
+
+ if(ata_tag_valid(ap->active_tag))
+ check_commands = 1 << ap->active_tag;
+ else
+ check_commands = ap->sactive;
+
/** Check CPBs for completed commands */
while ((pos = ffs(check_commands)) && !error) {
pos--;
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index 75d961599651..5614df8c1ce2 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -346,6 +346,7 @@ static const struct pci_device_id sil24_pci_tbl[] = {
{ PCI_VDEVICE(CMD, 0x3124), BID_SIL3124 },
{ PCI_VDEVICE(INTEL, 0x3124), BID_SIL3124 },
{ PCI_VDEVICE(CMD, 0x3132), BID_SIL3132 },
+ { PCI_VDEVICE(CMD, 0x0242), BID_SIL3132 },
{ PCI_VDEVICE(CMD, 0x3131), BID_SIL3131 },
{ PCI_VDEVICE(CMD, 0x3531), BID_SIL3131 },
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
index 1879e0cd56aa..a787f0d4a5ba 100644
--- a/drivers/ata/sata_sis.c
+++ b/drivers/ata/sata_sis.c
@@ -354,7 +354,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
return -ENOMEM;
if (!(probe_ent->port_flags & SIS_FLAG_CFGSCR)) {
- void *mmio;
+ void __iomem *mmio;
mmio = pcim_iomap(pdev, SIS_SCR_PCI_BAR, 0);
if (!mmio)
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c
index 0d7091e2077f..2ad2527cf5b3 100644
--- a/drivers/atm/zatm.c
+++ b/drivers/atm/zatm.c
@@ -1177,7 +1177,7 @@ static void __devinit eprom_get_esi(struct atm_dev *dev)
/*--------------------------------- entries ---------------------------------*/
-static int __init zatm_init(struct atm_dev *dev)
+static int __devinit zatm_init(struct atm_dev *dev)
{
struct zatm_dev *zatm_dev;
struct pci_dev *pci_dev;
@@ -1256,7 +1256,7 @@ static int __init zatm_init(struct atm_dev *dev)
}
-static int __init zatm_start(struct atm_dev *dev)
+static int __devinit zatm_start(struct atm_dev *dev)
{
struct zatm_dev *zatm_dev = ZATM_DEV(dev);
struct pci_dev *pdev = zatm_dev->pci_dev;
diff --git a/drivers/base/core.c b/drivers/base/core.c
index cf2a398aaaa1..d7fcf823a42a 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -28,20 +28,6 @@ int (*platform_notify)(struct device * dev) = NULL;
int (*platform_notify_remove)(struct device * dev) = NULL;
/*
- * Detect the LANANA-assigned LOCAL/EXPERIMENTAL majors
- */
-bool is_lanana_major(unsigned int major)
-{
- if (major >= 60 && major <= 63)
- return 1;
- if (major >= 120 && major <= 127)
- return 1;
- if (major >= 240 && major <= 254)
- return 1;
- return 0;
-}
-
-/*
* sysfs bindings for devices.
*/
@@ -407,6 +393,35 @@ void device_remove_bin_file(struct device *dev, struct bin_attribute *attr)
}
EXPORT_SYMBOL_GPL(device_remove_bin_file);
+/**
+ * device_schedule_callback - helper to schedule a callback for a device
+ * @dev: device.
+ * @func: callback function to invoke later.
+ *
+ * Attribute methods must not unregister themselves or their parent device
+ * (which would amount to the same thing). Attempts to do so will deadlock,
+ * since unregistration is mutually exclusive with driver callbacks.
+ *
+ * Instead methods can call this routine, which will attempt to allocate
+ * and schedule a workqueue request to call back @func with @dev as its
+ * argument in the workqueue's process context. @dev will be pinned until
+ * @func returns.
+ *
+ * Returns 0 if the request was submitted, -ENOMEM if storage could not
+ * be allocated.
+ *
+ * NOTE: This routine won't work if CONFIG_SYSFS isn't set! It uses an
+ * underlying sysfs routine (since it is intended for use by attribute
+ * methods), and if sysfs isn't available you'll get nothing but -ENOSYS.
+ */
+int device_schedule_callback(struct device *dev,
+ void (*func)(struct device *))
+{
+ return sysfs_schedule_callback(&dev->kobj,
+ (void (*)(void *)) func, dev);
+}
+EXPORT_SYMBOL_GPL(device_schedule_callback);
+
static void klist_children_get(struct klist_node *n)
{
struct device *dev = container_of(n, struct device, knode_parent);
@@ -584,17 +599,17 @@ int device_add(struct device *dev)
if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
sysfs_create_link(&dev->class->subsys.kset.kobj,
&dev->kobj, dev->bus_id);
-#ifdef CONFIG_SYSFS_DEPRECATED
if (parent) {
sysfs_create_link(&dev->kobj, &dev->parent->kobj,
"device");
+#ifdef CONFIG_SYSFS_DEPRECATED
class_name = make_class_name(dev->class->name,
&dev->kobj);
if (class_name)
sysfs_create_link(&dev->parent->kobj,
&dev->kobj, class_name);
- }
#endif
+ }
}
if ((error = device_add_attrs(dev)))
@@ -651,17 +666,17 @@ int device_add(struct device *dev)
if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
sysfs_remove_link(&dev->class->subsys.kset.kobj,
dev->bus_id);
-#ifdef CONFIG_SYSFS_DEPRECATED
if (parent) {
+#ifdef CONFIG_SYSFS_DEPRECATED
char *class_name = make_class_name(dev->class->name,
&dev->kobj);
if (class_name)
sysfs_remove_link(&dev->parent->kobj,
class_name);
kfree(class_name);
+#endif
sysfs_remove_link(&dev->kobj, "device");
}
-#endif
down(&dev->class->sem);
/* notify any interfaces that the device is now gone */
@@ -761,17 +776,17 @@ void device_del(struct device * dev)
if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
sysfs_remove_link(&dev->class->subsys.kset.kobj,
dev->bus_id);
-#ifdef CONFIG_SYSFS_DEPRECATED
if (parent) {
+#ifdef CONFIG_SYSFS_DEPRECATED
char *class_name = make_class_name(dev->class->name,
&dev->kobj);
if (class_name)
sysfs_remove_link(&dev->parent->kobj,
class_name);
kfree(class_name);
+#endif
sysfs_remove_link(&dev->kobj, "device");
}
-#endif
down(&dev->class->sem);
/* notify any interfaces that the device is now gone */
@@ -787,6 +802,13 @@ void device_del(struct device * dev)
device_remove_attrs(dev);
bus_remove_device(dev);
+ /*
+ * Some platform devices are driven without driver attached
+ * and managed resources may have been acquired. Make sure
+ * all resources are released.
+ */
+ devres_release_all(dev);
+
/* Notify the platform of the removal, in case they
* need to do anything...
*/
@@ -1058,14 +1080,14 @@ int device_rename(struct device *dev, char *new_name)
return error;
}
-
+EXPORT_SYMBOL_GPL(device_rename);
static int device_move_class_links(struct device *dev,
struct device *old_parent,
struct device *new_parent)
{
+ int error = 0;
#ifdef CONFIG_SYSFS_DEPRECATED
- int error;
char *class_name;
class_name = make_class_name(dev->class->name, &dev->kobj);
@@ -1093,7 +1115,12 @@ out:
kfree(class_name);
return error;
#else
- return 0;
+ if (old_parent)
+ sysfs_remove_link(&dev->kobj, "device");
+ if (new_parent)
+ error = sysfs_create_link(&dev->kobj, &new_parent->kobj,
+ "device");
+ return error;
#endif
}
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 1214cbd17d86..082bfded3854 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -183,7 +183,14 @@ int driver_register(struct device_driver * drv)
void driver_unregister(struct device_driver * drv)
{
bus_remove_driver(drv);
- wait_for_completion(&drv->unloaded);
+ /*
+ * If the driver is a module, we are probably in
+ * the module unload path, and we want to wait
+ * for everything to unload before we can actually
+ * finish the unload.
+ */
+ if (drv->owner)
+ wait_for_completion(&drv->unloaded);
}
/**
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index fdfa3d0cf6af..bbbb973a9d3c 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -54,7 +54,8 @@ int device_pm_add(struct device * dev)
int error;
pr_debug("PM: Adding info for %s:%s\n",
- dev->bus ? dev->bus->name : "No Bus", dev->kobj.name);
+ dev->bus ? dev->bus->name : "No Bus",
+ kobject_name(&dev->kobj));
down(&dpm_list_sem);
list_add_tail(&dev->power.entry, &dpm_active);
device_pm_set_parent(dev, dev->parent);
@@ -67,7 +68,8 @@ int device_pm_add(struct device * dev)
void device_pm_remove(struct device * dev)
{
pr_debug("PM: Removing info for %s:%s\n",
- dev->bus ? dev->bus->name : "No Bus", dev->kobj.name);
+ dev->bus ? dev->bus->name : "No Bus",
+ kobject_name(&dev->kobj));
down(&dpm_list_sem);
dpm_sysfs_remove(dev);
put_device(dev->power.pm_parent);
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 0c716ee905d7..14d780666c0a 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1439,7 +1439,7 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
if (return_code == IO_OK) {
listlength =
- be32_to_cpu(*(__u32 *) ld_buff->LUNListLength);
+ be32_to_cpu(*(__be32 *) ld_buff->LUNListLength);
} else { /* reading number of logical volumes failed */
printk(KERN_WARNING "cciss: report logical volume"
" command failed\n");
@@ -1915,6 +1915,7 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
"does not support reading geometry\n");
drv->heads = 255;
drv->sectors = 32; // Sectors per track
+ drv->cylinders = total_size + 1;
drv->raid_level = RAID_UNKNOWN;
} else {
drv->heads = inq_buff->data_byte[6];
@@ -1961,8 +1962,8 @@ cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size,
ctlr, buf, sizeof(ReadCapdata_struct),
1, logvol, 0, NULL, TYPE_CMD);
if (return_code == IO_OK) {
- *total_size = be32_to_cpu(*(__u32 *) buf->total_size);
- *block_size = be32_to_cpu(*(__u32 *) buf->block_size);
+ *total_size = be32_to_cpu(*(__be32 *) buf->total_size);
+ *block_size = be32_to_cpu(*(__be32 *) buf->block_size);
} else { /* read capacity command failed */
printk(KERN_WARNING "cciss: read capacity failed\n");
*total_size = 0;
@@ -1997,8 +1998,8 @@ cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size,
1, logvol, 0, NULL, TYPE_CMD);
}
if (return_code == IO_OK) {
- *total_size = be64_to_cpu(*(__u64 *) buf->total_size);
- *block_size = be32_to_cpu(*(__u32 *) buf->block_size);
+ *total_size = be64_to_cpu(*(__be64 *) buf->total_size);
+ *block_size = be32_to_cpu(*(__be32 *) buf->block_size);
} else { /* read capacity command failed */
printk(KERN_WARNING "cciss: read capacity failed\n");
*total_size = 0;
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 99e2c8ce1cc4..31e01488eb51 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -663,11 +663,11 @@ static enum action pd_identify(struct pd_unit *disk)
return Fail;
pi_read_block(disk->pi, pd_scratch, 512);
disk->can_lba = pd_scratch[99] & 2;
- disk->sectors = le16_to_cpu(*(u16 *) (pd_scratch + 12));
- disk->heads = le16_to_cpu(*(u16 *) (pd_scratch + 6));
- disk->cylinders = le16_to_cpu(*(u16 *) (pd_scratch + 2));
+ disk->sectors = le16_to_cpu(*(__le16 *) (pd_scratch + 12));
+ disk->heads = le16_to_cpu(*(__le16 *) (pd_scratch + 6));
+ disk->cylinders = le16_to_cpu(*(__le16 *) (pd_scratch + 2));
if (disk->can_lba)
- disk->capacity = le32_to_cpu(*(u32 *) (pd_scratch + 120));
+ disk->capacity = le32_to_cpu(*(__le32 *) (pd_scratch + 120));
else
disk->capacity = disk->sectors * disk->heads * disk->cylinders;
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 3429ece4ef92..d0c978fbc204 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -386,6 +386,39 @@ config AU1000_SERIAL_CONSOLE
If you have an Alchemy AU1000 processor (MIPS based) and you want
to use a console on a serial port, say Y. Otherwise, say N.
+config SERIAL_DEC
+ bool "DECstation serial support"
+ depends on MACH_DECSTATION
+ default y
+ help
+ This selects whether you want to be asked about drivers for
+ DECstation serial ports.
+
+ Note that the answer to this question won't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about DECstation serial ports.
+
+config SERIAL_DEC_CONSOLE
+ bool "Support for console on a DECstation serial port"
+ depends on SERIAL_DEC
+ default y
+ help
+ If you say Y here, it will be possible to use a serial port as the
+ system console (the system console is the device which receives all
+ kernel messages and warnings and which allows logins in single user
+ mode). Note that the firmware uses ttyS0 as the serial console on
+ the Maxine and ttyS2 on the others.
+
+ If unsure, say Y.
+
+config ZS
+ bool "Z85C30 Serial Support"
+ depends on SERIAL_DEC
+ default y
+ help
+ Documentation on the Zilog 85C350 serial communications controller
+ is downloadable at <http://www.zilog.com/pdfs/serial/z85c30.pdf>
+
config A2232
tristate "Commodore A2232 serial support (EXPERIMENTAL)"
depends on EXPERIMENTAL && ZORRO && BROKEN_ON_SMP
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index e542a628f1c7..55392a45a14b 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -18,11 +18,14 @@
#define PCI_DEVICE_ID_INTEL_82965Q_IG 0x2992
#define PCI_DEVICE_ID_INTEL_82965G_HB 0x29A0
#define PCI_DEVICE_ID_INTEL_82965G_IG 0x29A2
+#define PCI_DEVICE_ID_INTEL_82965GM_HB 0x2A00
+#define PCI_DEVICE_ID_INTEL_82965GM_IG 0x2A02
#define IS_I965 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82946GZ_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_1_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB)
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB)
extern int agp_memory_reserved;
@@ -428,9 +431,8 @@ static void intel_i830_init_gtt_entries(void)
if (IS_I965) {
u32 pgetbl_ctl;
+ pgetbl_ctl = readl(intel_i830_private.registers+I810_PGETBL_CTL);
- pci_read_config_dword(agp_bridge->dev, I810_PGETBL_CTL,
- &pgetbl_ctl);
/* The 965 has a field telling us the size of the GTT,
* which may be larger than what is necessary to map the
* aperture.
@@ -1921,7 +1923,13 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
bridge->driver = &intel_845_driver;
name = "965G";
break;
-
+ case PCI_DEVICE_ID_INTEL_82965GM_HB:
+ if (find_i830(PCI_DEVICE_ID_INTEL_82965GM_IG))
+ bridge->driver = &intel_i965_driver;
+ else
+ bridge->driver = &intel_845_driver;
+ name = "965GM";
+ break;
case PCI_DEVICE_ID_INTEL_7505_0:
bridge->driver = &intel_7505_driver;
name = "E7505";
@@ -2080,6 +2088,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
ID(PCI_DEVICE_ID_INTEL_82965G_1_HB),
ID(PCI_DEVICE_ID_INTEL_82965Q_HB),
ID(PCI_DEVICE_ID_INTEL_82965G_HB),
+ ID(PCI_DEVICE_ID_INTEL_82965GM_HB),
{ }
};
diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile
index 3ad0f648c6b2..6915a0599dfb 100644
--- a/drivers/char/drm/Makefile
+++ b/drivers/char/drm/Makefile
@@ -15,7 +15,6 @@ i810-objs := i810_drv.o i810_dma.o
i830-objs := i830_drv.o i830_dma.o i830_irq.o
i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o
radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o
-ffb-objs := ffb_drv.o ffb_context.o
sis-objs := sis_drv.o sis_mm.o
savage-objs := savage_drv.o savage_bci.o savage_state.o
via-objs := via_irq.o via_drv.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o via_dmablit.o
@@ -36,7 +35,6 @@ obj-$(CONFIG_DRM_MGA) += mga.o
obj-$(CONFIG_DRM_I810) += i810.o
obj-$(CONFIG_DRM_I830) += i830.o
obj-$(CONFIG_DRM_I915) += i915.o
-obj-$(CONFIG_DRM_FFB) += ffb.o
obj-$(CONFIG_DRM_SIS) += sis.o
obj-$(CONFIG_DRM_SAVAGE)+= savage.o
obj-$(CONFIG_DRM_VIA) +=via.o
diff --git a/drivers/char/drm/ffb_context.c b/drivers/char/drm/ffb_context.c
deleted file mode 100644
index ac9ab40d57aa..000000000000
--- a/drivers/char/drm/ffb_context.c
+++ /dev/null
@@ -1,544 +0,0 @@
-/* $Id: ffb_context.c,v 1.5 2001/08/09 17:47:51 davem Exp $
- * ffb_context.c: Creator/Creator3D DRI/DRM context switching.
- *
- * Copyright (C) 2000 David S. Miller (davem@redhat.com)
- *
- * Almost entirely stolen from tdfx_context.c, see there
- * for authors.
- */
-
-#include <asm/upa.h>
-
-#include "ffb.h"
-#include "drmP.h"
-
-#include "ffb_drv.h"
-
-static int DRM(alloc_queue) (drm_device_t * dev, int is_2d_only) {
- ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
- int i;
-
- for (i = 0; i < FFB_MAX_CTXS; i++) {
- if (fpriv->hw_state[i] == NULL)
- break;
- }
- if (i == FFB_MAX_CTXS)
- return -1;
-
- fpriv->hw_state[i] = kmalloc(sizeof(struct ffb_hw_context), GFP_KERNEL);
- if (fpriv->hw_state[i] == NULL)
- return -1;
-
- fpriv->hw_state[i]->is_2d_only = is_2d_only;
-
- /* Plus one because 0 is the special DRM_KERNEL_CONTEXT. */
- return i + 1;
-}
-
-static void ffb_save_context(ffb_dev_priv_t * fpriv, int idx)
-{
- ffb_fbcPtr ffb = fpriv->regs;
- struct ffb_hw_context *ctx;
- int i;
-
- ctx = fpriv->hw_state[idx - 1];
- if (idx == 0 || ctx == NULL)
- return;
-
- if (ctx->is_2d_only) {
- /* 2D applications only care about certain pieces
- * of state.
- */
- ctx->drawop = upa_readl(&ffb->drawop);
- ctx->ppc = upa_readl(&ffb->ppc);
- ctx->wid = upa_readl(&ffb->wid);
- ctx->fg = upa_readl(&ffb->fg);
- ctx->bg = upa_readl(&ffb->bg);
- ctx->xclip = upa_readl(&ffb->xclip);
- ctx->fbc = upa_readl(&ffb->fbc);
- ctx->rop = upa_readl(&ffb->rop);
- ctx->cmp = upa_readl(&ffb->cmp);
- ctx->matchab = upa_readl(&ffb->matchab);
- ctx->magnab = upa_readl(&ffb->magnab);
- ctx->pmask = upa_readl(&ffb->pmask);
- ctx->xpmask = upa_readl(&ffb->xpmask);
- ctx->lpat = upa_readl(&ffb->lpat);
- ctx->fontxy = upa_readl(&ffb->fontxy);
- ctx->fontw = upa_readl(&ffb->fontw);
- ctx->fontinc = upa_readl(&ffb->fontinc);
-
- /* stencil/stencilctl only exists on FFB2+ and later
- * due to the introduction of 3DRAM-III.
- */
- if (fpriv->ffb_type == ffb2_vertical_plus ||
- fpriv->ffb_type == ffb2_horizontal_plus) {
- ctx->stencil = upa_readl(&ffb->stencil);
- ctx->stencilctl = upa_readl(&ffb->stencilctl);
- }
-
- for (i = 0; i < 32; i++)
- ctx->area_pattern[i] = upa_readl(&ffb->pattern[i]);
- ctx->ucsr = upa_readl(&ffb->ucsr);
- return;
- }
-
- /* Fetch drawop. */
- ctx->drawop = upa_readl(&ffb->drawop);
-
- /* If we were saving the vertex registers, this is where
- * we would do it. We would save 32 32-bit words starting
- * at ffb->suvtx.
- */
-
- /* Capture rendering attributes. */
-
- ctx->ppc = upa_readl(&ffb->ppc); /* Pixel Processor Control */
- ctx->wid = upa_readl(&ffb->wid); /* Current WID */
- ctx->fg = upa_readl(&ffb->fg); /* Constant FG color */
- ctx->bg = upa_readl(&ffb->bg); /* Constant BG color */
- ctx->consty = upa_readl(&ffb->consty); /* Constant Y */
- ctx->constz = upa_readl(&ffb->constz); /* Constant Z */
- ctx->xclip = upa_readl(&ffb->xclip); /* X plane clip */
- ctx->dcss = upa_readl(&ffb->dcss); /* Depth Cue Scale Slope */
- ctx->vclipmin = upa_readl(&ffb->vclipmin); /* Primary XY clip, minimum */
- ctx->vclipmax = upa_readl(&ffb->vclipmax); /* Primary XY clip, maximum */
- ctx->vclipzmin = upa_readl(&ffb->vclipzmin); /* Primary Z clip, minimum */
- ctx->vclipzmax = upa_readl(&ffb->vclipzmax); /* Primary Z clip, maximum */
- ctx->dcsf = upa_readl(&ffb->dcsf); /* Depth Cue Scale Front Bound */
- ctx->dcsb = upa_readl(&ffb->dcsb); /* Depth Cue Scale Back Bound */
- ctx->dczf = upa_readl(&ffb->dczf); /* Depth Cue Scale Z Front */
- ctx->dczb = upa_readl(&ffb->dczb); /* Depth Cue Scale Z Back */
- ctx->blendc = upa_readl(&ffb->blendc); /* Alpha Blend Control */
- ctx->blendc1 = upa_readl(&ffb->blendc1); /* Alpha Blend Color 1 */
- ctx->blendc2 = upa_readl(&ffb->blendc2); /* Alpha Blend Color 2 */
- ctx->fbc = upa_readl(&ffb->fbc); /* Frame Buffer Control */
- ctx->rop = upa_readl(&ffb->rop); /* Raster Operation */
- ctx->cmp = upa_readl(&ffb->cmp); /* Compare Controls */
- ctx->matchab = upa_readl(&ffb->matchab); /* Buffer A/B Match Ops */
- ctx->matchc = upa_readl(&ffb->matchc); /* Buffer C Match Ops */
- ctx->magnab = upa_readl(&ffb->magnab); /* Buffer A/B Magnitude Ops */
- ctx->magnc = upa_readl(&ffb->magnc); /* Buffer C Magnitude Ops */
- ctx->pmask = upa_readl(&ffb->pmask); /* RGB Plane Mask */
- ctx->xpmask = upa_readl(&ffb->xpmask); /* X Plane Mask */
- ctx->ypmask = upa_readl(&ffb->ypmask); /* Y Plane Mask */
- ctx->zpmask = upa_readl(&ffb->zpmask); /* Z Plane Mask */
-
- /* Auxiliary Clips. */
- ctx->auxclip0min = upa_readl(&ffb->auxclip[0].min);
- ctx->auxclip0max = upa_readl(&ffb->auxclip[0].max);
- ctx->auxclip1min = upa_readl(&ffb->auxclip[1].min);
- ctx->auxclip1max = upa_readl(&ffb->auxclip[1].max);
- ctx->auxclip2min = upa_readl(&ffb->auxclip[2].min);
- ctx->auxclip2max = upa_readl(&ffb->auxclip[2].max);
- ctx->auxclip3min = upa_readl(&ffb->auxclip[3].min);
- ctx->auxclip3max = upa_readl(&ffb->auxclip[3].max);
-
- ctx->lpat = upa_readl(&ffb->lpat); /* Line Pattern */
- ctx->fontxy = upa_readl(&ffb->fontxy); /* XY Font Coordinate */
- ctx->fontw = upa_readl(&ffb->fontw); /* Font Width */
- ctx->fontinc = upa_readl(&ffb->fontinc); /* Font X/Y Increment */
-
- /* These registers/features only exist on FFB2 and later chips. */
- if (fpriv->ffb_type >= ffb2_prototype) {
- ctx->dcss1 = upa_readl(&ffb->dcss1); /* Depth Cue Scale Slope 1 */
- ctx->dcss2 = upa_readl(&ffb->dcss2); /* Depth Cue Scale Slope 2 */
- ctx->dcss2 = upa_readl(&ffb->dcss3); /* Depth Cue Scale Slope 3 */
- ctx->dcs2 = upa_readl(&ffb->dcs2); /* Depth Cue Scale 2 */
- ctx->dcs3 = upa_readl(&ffb->dcs3); /* Depth Cue Scale 3 */
- ctx->dcs4 = upa_readl(&ffb->dcs4); /* Depth Cue Scale 4 */
- ctx->dcd2 = upa_readl(&ffb->dcd2); /* Depth Cue Depth 2 */
- ctx->dcd3 = upa_readl(&ffb->dcd3); /* Depth Cue Depth 3 */
- ctx->dcd4 = upa_readl(&ffb->dcd4); /* Depth Cue Depth 4 */
-
- /* And stencil/stencilctl only exists on FFB2+ and later
- * due to the introduction of 3DRAM-III.
- */
- if (fpriv->ffb_type == ffb2_vertical_plus ||
- fpriv->ffb_type == ffb2_horizontal_plus) {
- ctx->stencil = upa_readl(&ffb->stencil);
- ctx->stencilctl = upa_readl(&ffb->stencilctl);
- }
- }
-
- /* Save the 32x32 area pattern. */
- for (i = 0; i < 32; i++)
- ctx->area_pattern[i] = upa_readl(&ffb->pattern[i]);
-
- /* Finally, stash away the User Constol/Status Register. */
- ctx->ucsr = upa_readl(&ffb->ucsr);
-}
-
-static void ffb_restore_context(ffb_dev_priv_t * fpriv, int old, int idx)
-{
- ffb_fbcPtr ffb = fpriv->regs;
- struct ffb_hw_context *ctx;
- int i;
-
- ctx = fpriv->hw_state[idx - 1];
- if (idx == 0 || ctx == NULL)
- return;
-
- if (ctx->is_2d_only) {
- /* 2D applications only care about certain pieces
- * of state.
- */
- upa_writel(ctx->drawop, &ffb->drawop);
-
- /* If we were restoring the vertex registers, this is where
- * we would do it. We would restore 32 32-bit words starting
- * at ffb->suvtx.
- */
-
- upa_writel(ctx->ppc, &ffb->ppc);
- upa_writel(ctx->wid, &ffb->wid);
- upa_writel(ctx->fg, &ffb->fg);
- upa_writel(ctx->bg, &ffb->bg);
- upa_writel(ctx->xclip, &ffb->xclip);
- upa_writel(ctx->fbc, &ffb->fbc);
- upa_writel(ctx->rop, &ffb->rop);
- upa_writel(ctx->cmp, &ffb->cmp);
- upa_writel(ctx->matchab, &ffb->matchab);
- upa_writel(ctx->magnab, &ffb->magnab);
- upa_writel(ctx->pmask, &ffb->pmask);
- upa_writel(ctx->xpmask, &ffb->xpmask);
- upa_writel(ctx->lpat, &ffb->lpat);
- upa_writel(ctx->fontxy, &ffb->fontxy);
- upa_writel(ctx->fontw, &ffb->fontw);
- upa_writel(ctx->fontinc, &ffb->fontinc);
-
- /* stencil/stencilctl only exists on FFB2+ and later
- * due to the introduction of 3DRAM-III.
- */
- if (fpriv->ffb_type == ffb2_vertical_plus ||
- fpriv->ffb_type == ffb2_horizontal_plus) {
- upa_writel(ctx->stencil, &ffb->stencil);
- upa_writel(ctx->stencilctl, &ffb->stencilctl);
- upa_writel(0x80000000, &ffb->fbc);
- upa_writel((ctx->stencilctl | 0x80000),
- &ffb->rawstencilctl);
- upa_writel(ctx->fbc, &ffb->fbc);
- }
-
- for (i = 0; i < 32; i++)
- upa_writel(ctx->area_pattern[i], &ffb->pattern[i]);
- upa_writel((ctx->ucsr & 0xf0000), &ffb->ucsr);
- return;
- }
-
- /* Restore drawop. */
- upa_writel(ctx->drawop, &ffb->drawop);
-
- /* If we were restoring the vertex registers, this is where
- * we would do it. We would restore 32 32-bit words starting
- * at ffb->suvtx.
- */
-
- /* Restore rendering attributes. */
-
- upa_writel(ctx->ppc, &ffb->ppc); /* Pixel Processor Control */
- upa_writel(ctx->wid, &ffb->wid); /* Current WID */
- upa_writel(ctx->fg, &ffb->fg); /* Constant FG color */
- upa_writel(ctx->bg, &ffb->bg); /* Constant BG color */
- upa_writel(ctx->consty, &ffb->consty); /* Constant Y */
- upa_writel(ctx->constz, &ffb->constz); /* Constant Z */
- upa_writel(ctx->xclip, &ffb->xclip); /* X plane clip */
- upa_writel(ctx->dcss, &ffb->dcss); /* Depth Cue Scale Slope */
- upa_writel(ctx->vclipmin, &ffb->vclipmin); /* Primary XY clip, minimum */
- upa_writel(ctx->vclipmax, &ffb->vclipmax); /* Primary XY clip, maximum */
- upa_writel(ctx->vclipzmin, &ffb->vclipzmin); /* Primary Z clip, minimum */
- upa_writel(ctx->vclipzmax, &ffb->vclipzmax); /* Primary Z clip, maximum */
- upa_writel(ctx->dcsf, &ffb->dcsf); /* Depth Cue Scale Front Bound */
- upa_writel(ctx->dcsb, &ffb->dcsb); /* Depth Cue Scale Back Bound */
- upa_writel(ctx->dczf, &ffb->dczf); /* Depth Cue Scale Z Front */
- upa_writel(ctx->dczb, &ffb->dczb); /* Depth Cue Scale Z Back */
- upa_writel(ctx->blendc, &ffb->blendc); /* Alpha Blend Control */
- upa_writel(ctx->blendc1, &ffb->blendc1); /* Alpha Blend Color 1 */
- upa_writel(ctx->blendc2, &ffb->blendc2); /* Alpha Blend Color 2 */
- upa_writel(ctx->fbc, &ffb->fbc); /* Frame Buffer Control */
- upa_writel(ctx->rop, &ffb->rop); /* Raster Operation */
- upa_writel(ctx->cmp, &ffb->cmp); /* Compare Controls */
- upa_writel(ctx->matchab, &ffb->matchab); /* Buffer A/B Match Ops */
- upa_writel(ctx->matchc, &ffb->matchc); /* Buffer C Match Ops */
- upa_writel(ctx->magnab, &ffb->magnab); /* Buffer A/B Magnitude Ops */
- upa_writel(ctx->magnc, &ffb->magnc); /* Buffer C Magnitude Ops */
- upa_writel(ctx->pmask, &ffb->pmask); /* RGB Plane Mask */
- upa_writel(ctx->xpmask, &ffb->xpmask); /* X Plane Mask */
- upa_writel(ctx->ypmask, &ffb->ypmask); /* Y Plane Mask */
- upa_writel(ctx->zpmask, &ffb->zpmask); /* Z Plane Mask */
-
- /* Auxiliary Clips. */
- upa_writel(ctx->auxclip0min, &ffb->auxclip[0].min);
- upa_writel(ctx->auxclip0max, &ffb->auxclip[0].max);
- upa_writel(ctx->auxclip1min, &ffb->auxclip[1].min);
- upa_writel(ctx->auxclip1max, &ffb->auxclip[1].max);
- upa_writel(ctx->auxclip2min, &ffb->auxclip[2].min);
- upa_writel(ctx->auxclip2max, &ffb->auxclip[2].max);
- upa_writel(ctx->auxclip3min, &ffb->auxclip[3].min);
- upa_writel(ctx->auxclip3max, &ffb->auxclip[3].max);
-
- upa_writel(ctx->lpat, &ffb->lpat); /* Line Pattern */
- upa_writel(ctx->fontxy, &ffb->fontxy); /* XY Font Coordinate */
- upa_writel(ctx->fontw, &ffb->fontw); /* Font Width */
- upa_writel(ctx->fontinc, &ffb->fontinc); /* Font X/Y Increment */
-
- /* These registers/features only exist on FFB2 and later chips. */
- if (fpriv->ffb_type >= ffb2_prototype) {
- upa_writel(ctx->dcss1, &ffb->dcss1); /* Depth Cue Scale Slope 1 */
- upa_writel(ctx->dcss2, &ffb->dcss2); /* Depth Cue Scale Slope 2 */
- upa_writel(ctx->dcss3, &ffb->dcss2); /* Depth Cue Scale Slope 3 */
- upa_writel(ctx->dcs2, &ffb->dcs2); /* Depth Cue Scale 2 */
- upa_writel(ctx->dcs3, &ffb->dcs3); /* Depth Cue Scale 3 */
- upa_writel(ctx->dcs4, &ffb->dcs4); /* Depth Cue Scale 4 */
- upa_writel(ctx->dcd2, &ffb->dcd2); /* Depth Cue Depth 2 */
- upa_writel(ctx->dcd3, &ffb->dcd3); /* Depth Cue Depth 3 */
- upa_writel(ctx->dcd4, &ffb->dcd4); /* Depth Cue Depth 4 */
-
- /* And stencil/stencilctl only exists on FFB2+ and later
- * due to the introduction of 3DRAM-III.
- */
- if (fpriv->ffb_type == ffb2_vertical_plus ||
- fpriv->ffb_type == ffb2_horizontal_plus) {
- /* Unfortunately, there is a hardware bug on
- * the FFB2+ chips which prevents a normal write
- * to the stencil control register from working
- * as it should.
- *
- * The state controlled by the FFB stencilctl register
- * really gets transferred to the per-buffer instances
- * of the stencilctl register in the 3DRAM chips.
- *
- * The bug is that FFB does not update buffer C correctly,
- * so we have to do it by hand for them.
- */
-
- /* This will update buffers A and B. */
- upa_writel(ctx->stencil, &ffb->stencil);
- upa_writel(ctx->stencilctl, &ffb->stencilctl);
-
- /* Force FFB to use buffer C 3dram regs. */
- upa_writel(0x80000000, &ffb->fbc);
- upa_writel((ctx->stencilctl | 0x80000),
- &ffb->rawstencilctl);
-
- /* Now restore the correct FBC controls. */
- upa_writel(ctx->fbc, &ffb->fbc);
- }
- }
-
- /* Restore the 32x32 area pattern. */
- for (i = 0; i < 32; i++)
- upa_writel(ctx->area_pattern[i], &ffb->pattern[i]);
-
- /* Finally, stash away the User Constol/Status Register.
- * The only state we really preserve here is the picking
- * control.
- */
- upa_writel((ctx->ucsr & 0xf0000), &ffb->ucsr);
-}
-
-#define FFB_UCSR_FB_BUSY 0x01000000
-#define FFB_UCSR_RP_BUSY 0x02000000
-#define FFB_UCSR_ALL_BUSY (FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY)
-
-static void FFBWait(ffb_fbcPtr ffb)
-{
- int limit = 100000;
-
- do {
- u32 regval = upa_readl(&ffb->ucsr);
-
- if ((regval & FFB_UCSR_ALL_BUSY) == 0)
- break;
- } while (--limit);
-}
-
-int ffb_driver_context_switch(drm_device_t * dev, int old, int new)
-{
- ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
-
-#ifdef DRM_DMA_HISTOGRAM
- dev->ctx_start = get_cycles();
-#endif
-
- DRM_DEBUG("Context switch from %d to %d\n", old, new);
-
- if (new == dev->last_context || dev->last_context == 0) {
- dev->last_context = new;
- return 0;
- }
-
- FFBWait(fpriv->regs);
- ffb_save_context(fpriv, old);
- ffb_restore_context(fpriv, old, new);
- FFBWait(fpriv->regs);
-
- dev->last_context = new;
-
- return 0;
-}
-
-int ffb_driver_resctx(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
-{
- drm_ctx_res_t res;
- drm_ctx_t ctx;
- int i;
-
- DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
- if (copy_from_user(&res, (drm_ctx_res_t __user *) arg, sizeof(res)))
- return -EFAULT;
- if (res.count >= DRM_RESERVED_CONTEXTS) {
- memset(&ctx, 0, sizeof(ctx));
- for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
- ctx.handle = i;
- if (copy_to_user(&res.contexts[i], &i, sizeof(i)))
- return -EFAULT;
- }
- }
- res.count = DRM_RESERVED_CONTEXTS;
- if (copy_to_user((drm_ctx_res_t __user *) arg, &res, sizeof(res)))
- return -EFAULT;
- return 0;
-}
-
-int ffb_driver_addctx(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_ctx_t ctx;
- int idx;
-
- if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
- return -EFAULT;
- idx = DRM(alloc_queue) (dev, (ctx.flags & _DRM_CONTEXT_2DONLY));
- if (idx < 0)
- return -ENFILE;
-
- DRM_DEBUG("%d\n", ctx.handle);
- ctx.handle = idx;
- if (copy_to_user((drm_ctx_t __user *) arg, &ctx, sizeof(ctx)))
- return -EFAULT;
- return 0;
-}
-
-int ffb_driver_modctx(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
- struct ffb_hw_context *hwctx;
- drm_ctx_t ctx;
- int idx;
-
- if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
- return -EFAULT;
-
- idx = ctx.handle;
- if (idx <= 0 || idx >= FFB_MAX_CTXS)
- return -EINVAL;
-
- hwctx = fpriv->hw_state[idx - 1];
- if (hwctx == NULL)
- return -EINVAL;
-
- if ((ctx.flags & _DRM_CONTEXT_2DONLY) == 0)
- hwctx->is_2d_only = 0;
- else
- hwctx->is_2d_only = 1;
-
- return 0;
-}
-
-int ffb_driver_getctx(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
- struct ffb_hw_context *hwctx;
- drm_ctx_t ctx;
- int idx;
-
- if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
- return -EFAULT;
-
- idx = ctx.handle;
- if (idx <= 0 || idx >= FFB_MAX_CTXS)
- return -EINVAL;
-
- hwctx = fpriv->hw_state[idx - 1];
- if (hwctx == NULL)
- return -EINVAL;
-
- if (hwctx->is_2d_only != 0)
- ctx.flags = _DRM_CONTEXT_2DONLY;
- else
- ctx.flags = 0;
-
- if (copy_to_user((drm_ctx_t __user *) arg, &ctx, sizeof(ctx)))
- return -EFAULT;
-
- return 0;
-}
-
-int ffb_driver_switchctx(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_ctx_t ctx;
-
- if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
- return -EFAULT;
- DRM_DEBUG("%d\n", ctx.handle);
- return ffb_driver_context_switch(dev, dev->last_context, ctx.handle);
-}
-
-int ffb_driver_newctx(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
-{
- drm_ctx_t ctx;
-
- if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
- return -EFAULT;
- DRM_DEBUG("%d\n", ctx.handle);
-
- return 0;
-}
-
-int ffb_driver_rmctx(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
-{
- drm_ctx_t ctx;
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
- int idx;
-
- if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
- return -EFAULT;
- DRM_DEBUG("%d\n", ctx.handle);
-
- idx = ctx.handle - 1;
- if (idx < 0 || idx >= FFB_MAX_CTXS)
- return -EINVAL;
-
- kfree(fpriv->hw_state[idx]);
- fpriv->hw_state[idx] = NULL;
- return 0;
-}
-
-void ffb_set_context_ioctls(void)
-{
- DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)].func = ffb_driver_addctx;
- DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)].func = ffb_driver_rmctx;
- DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)].func = ffb_driver_modctx;
- DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)].func = ffb_driver_getctx;
- DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)].func =
- ffb_driver_switchctx;
- DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)].func = ffb_driver_newctx;
- DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)].func = ffb_driver_resctx;
-
-}
diff --git a/drivers/char/drm/ffb_drv.c b/drivers/char/drm/ffb_drv.c
deleted file mode 100644
index 9a19879e3b68..000000000000
--- a/drivers/char/drm/ffb_drv.c
+++ /dev/null
@@ -1,355 +0,0 @@
-/* $Id: ffb_drv.c,v 1.16 2001/10/18 16:00:24 davem Exp $
- * ffb_drv.c: Creator/Creator3D direct rendering driver.
- *
- * Copyright (C) 2000 David S. Miller (davem@redhat.com)
- */
-
-#include "ffb.h"
-#include "drmP.h"
-
-#include "ffb_drv.h"
-
-#include <linux/smp_lock.h>
-#include <asm/shmparam.h>
-#include <asm/oplib.h>
-#include <asm/upa.h>
-
-#define DRIVER_AUTHOR "David S. Miller"
-
-#define DRIVER_NAME "ffb"
-#define DRIVER_DESC "Creator/Creator3D"
-#define DRIVER_DATE "20000517"
-
-#define DRIVER_MAJOR 0
-#define DRIVER_MINOR 0
-#define DRIVER_PATCHLEVEL 1
-
-typedef struct _ffb_position_t {
- int node;
- int root;
-} ffb_position_t;
-
-static ffb_position_t *ffb_position;
-
-static void get_ffb_type(ffb_dev_priv_t * ffb_priv, int instance)
-{
- volatile unsigned char *strap_bits;
- unsigned char val;
-
- strap_bits = (volatile unsigned char *)
- (ffb_priv->card_phys_base + 0x00200000UL);
-
- /* Don't ask, you have to read the value twice for whatever
- * reason to get correct contents.
- */
- val = upa_readb(strap_bits);
- val = upa_readb(strap_bits);
- switch (val & 0x78) {
- case (0x0 << 5) | (0x0 << 3):
- ffb_priv->ffb_type = ffb1_prototype;
- printk("ffb%d: Detected FFB1 pre-FCS prototype\n", instance);
- break;
- case (0x0 << 5) | (0x1 << 3):
- ffb_priv->ffb_type = ffb1_standard;
- printk("ffb%d: Detected FFB1\n", instance);
- break;
- case (0x0 << 5) | (0x3 << 3):
- ffb_priv->ffb_type = ffb1_speedsort;
- printk("ffb%d: Detected FFB1-SpeedSort\n", instance);
- break;
- case (0x1 << 5) | (0x0 << 3):
- ffb_priv->ffb_type = ffb2_prototype;
- printk("ffb%d: Detected FFB2/vertical pre-FCS prototype\n",
- instance);
- break;
- case (0x1 << 5) | (0x1 << 3):
- ffb_priv->ffb_type = ffb2_vertical;
- printk("ffb%d: Detected FFB2/vertical\n", instance);
- break;
- case (0x1 << 5) | (0x2 << 3):
- ffb_priv->ffb_type = ffb2_vertical_plus;
- printk("ffb%d: Detected FFB2+/vertical\n", instance);
- break;
- case (0x2 << 5) | (0x0 << 3):
- ffb_priv->ffb_type = ffb2_horizontal;
- printk("ffb%d: Detected FFB2/horizontal\n", instance);
- break;
- case (0x2 << 5) | (0x2 << 3):
- ffb_priv->ffb_type = ffb2_horizontal;
- printk("ffb%d: Detected FFB2+/horizontal\n", instance);
- break;
- default:
- ffb_priv->ffb_type = ffb2_vertical;
- printk("ffb%d: Unknown boardID[%08x], assuming FFB2\n",
- instance, val);
- break;
- };
-}
-
-static void ffb_apply_upa_parent_ranges(int parent,
- struct linux_prom64_registers *regs)
-{
- struct linux_prom64_ranges ranges[PROMREG_MAX];
- char name[128];
- int len, i;
-
- prom_getproperty(parent, "name", name, sizeof(name));
- if (strcmp(name, "upa") != 0)
- return;
-
- len =
- prom_getproperty(parent, "ranges", (void *)ranges, sizeof(ranges));
- if (len <= 0)
- return;
-
- len /= sizeof(struct linux_prom64_ranges);
- for (i = 0; i < len; i++) {
- struct linux_prom64_ranges *rng = &ranges[i];
- u64 phys_addr = regs->phys_addr;
-
- if (phys_addr >= rng->ot_child_base &&
- phys_addr < (rng->ot_child_base + rng->or_size)) {
- regs->phys_addr -= rng->ot_child_base;
- regs->phys_addr += rng->ot_parent_base;
- return;
- }
- }
-
- return;
-}
-
-static int ffb_init_one(drm_device_t * dev, int prom_node, int parent_node,
- int instance)
-{
- struct linux_prom64_registers regs[2 * PROMREG_MAX];
- ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *) dev->dev_private;
- int i;
-
- ffb_priv->prom_node = prom_node;
- if (prom_getproperty(ffb_priv->prom_node, "reg",
- (void *)regs, sizeof(regs)) <= 0) {
- return -EINVAL;
- }
- ffb_apply_upa_parent_ranges(parent_node, &regs[0]);
- ffb_priv->card_phys_base = regs[0].phys_addr;
- ffb_priv->regs = (ffb_fbcPtr)
- (regs[0].phys_addr + 0x00600000UL);
- get_ffb_type(ffb_priv, instance);
- for (i = 0; i < FFB_MAX_CTXS; i++)
- ffb_priv->hw_state[i] = NULL;
-
- return 0;
-}
-
-static drm_map_t *ffb_find_map(struct file *filp, unsigned long off)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev;
- drm_map_list_t *r_list;
- struct list_head *list;
- drm_map_t *map;
-
- if (!priv || (dev = priv->dev) == NULL)
- return NULL;
-
- list_for_each(list, &dev->maplist->head) {
- r_list = (drm_map_list_t *) list;
- map = r_list->map;
- if (!map)
- continue;
- if (r_list->user_token == off)
- return map;
- }
-
- return NULL;
-}
-
-unsigned long ffb_get_unmapped_area(struct file *filp,
- unsigned long hint,
- unsigned long len,
- unsigned long pgoff, unsigned long flags)
-{
- drm_map_t *map = ffb_find_map(filp, pgoff << PAGE_SHIFT);
- unsigned long addr = -ENOMEM;
-
- if (!map)
- return get_unmapped_area(NULL, hint, len, pgoff, flags);
-
- if (map->type == _DRM_FRAME_BUFFER || map->type == _DRM_REGISTERS) {
-#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
- addr = get_fb_unmapped_area(filp, hint, len, pgoff, flags);
-#else
- addr = get_unmapped_area(NULL, hint, len, pgoff, flags);
-#endif
- } else if (map->type == _DRM_SHM && SHMLBA > PAGE_SIZE) {
- unsigned long slack = SHMLBA - PAGE_SIZE;
-
- addr = get_unmapped_area(NULL, hint, len + slack, pgoff, flags);
- if (!(addr & ~PAGE_MASK)) {
- unsigned long kvirt = (unsigned long)map->handle;
-
- if ((kvirt & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) {
- unsigned long koff, aoff;
-
- koff = kvirt & (SHMLBA - 1);
- aoff = addr & (SHMLBA - 1);
- if (koff < aoff)
- koff += SHMLBA;
-
- addr += (koff - aoff);
- }
- }
- } else {
- addr = get_unmapped_area(NULL, hint, len, pgoff, flags);
- }
-
- return addr;
-}
-
-static int ffb_presetup(drm_device_t * dev)
-{
- ffb_dev_priv_t *ffb_priv;
- int ret = 0;
- int i = 0;
-
- /* Check for the case where no device was found. */
- if (ffb_position == NULL)
- return -ENODEV;
-
- /* code used to use numdevs no numdevs anymore */
- ffb_priv = kmalloc(sizeof(ffb_dev_priv_t), GFP_KERNEL);
- if (!ffb_priv)
- return -ENOMEM;
- memset(ffb_priv, 0, sizeof(*ffb_priv));
- dev->dev_private = ffb_priv;
-
- ret = ffb_init_one(dev, ffb_position[i].node, ffb_position[i].root, i);
- return ret;
-}
-
-static void ffb_driver_release(drm_device_t * dev, struct file *filp)
-{
- ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
- int context = _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock);
- int idx;
-
- idx = context - 1;
- if (fpriv &&
- context != DRM_KERNEL_CONTEXT && fpriv->hw_state[idx] != NULL) {
- kfree(fpriv->hw_state[idx]);
- fpriv->hw_state[idx] = NULL;
- }
-}
-
-static void ffb_driver_pretakedown(drm_device_t * dev)
-{
- kfree(dev->dev_private);
-}
-
-static int ffb_driver_postcleanup(drm_device_t * dev)
-{
- kfree(ffb_position);
- return 0;
-}
-
-static void ffb_driver_kernel_context_switch_unlock(struct drm_device *dev,
- drm_lock_t * lock)
-{
- dev->lock.filp = 0;
- {
- __volatile__ unsigned int *plock = &dev->lock.hw_lock->lock;
- unsigned int old, new, prev, ctx;
-
- ctx = lock->context;
- do {
- old = *plock;
- new = ctx;
- prev = cmpxchg(plock, old, new);
- } while (prev != old);
- }
- wake_up_interruptible(&dev->lock.lock_queue);
-}
-
-static unsigned long ffb_driver_get_map_ofs(drm_map_t * map)
-{
- return (map->offset & 0xffffffff);
-}
-
-static unsigned long ffb_driver_get_reg_ofs(drm_device_t * dev)
-{
- ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *) dev->dev_private;
-
- if (ffb_priv)
- return ffb_priv->card_phys_base;
-
- return 0;
-}
-
-static int postinit(struct drm_device *dev, unsigned long flags)
-{
- DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
- DRIVER_NAME,
- DRIVER_MAJOR,
- DRIVER_MINOR, DRIVER_PATCHLEVEL, DRIVER_DATE, dev->minor);
- return 0;
-}
-
-static int version(drm_version_t * version)
-{
- int len;
-
- version->version_major = DRIVER_MAJOR;
- version->version_minor = DRIVER_MINOR;
- version->version_patchlevel = DRIVER_PATCHLEVEL;
- DRM_COPY(version->name, DRIVER_NAME);
- DRM_COPY(version->date, DRIVER_DATE);
- DRM_COPY(version->desc, DRIVER_DESC);
- return 0;
-}
-
-static drm_ioctl_desc_t ioctls[] = {
-
-};
-
-static struct drm_driver driver = {
- .driver_features = 0,
- .dev_priv_size = sizeof(u32),
- .release = ffb_driver_release,
- .presetup = ffb_presetup,
- .pretakedown = ffb_driver_pretakedown,
- .postcleanup = ffb_driver_postcleanup,
- .kernel_context_switch = ffb_driver_context_switch,
- .kernel_context_switch_unlock = ffb_driver_kernel_context_switch_unlock,
- .get_map_ofs = ffb_driver_get_map_ofs,
- .get_reg_ofs = ffb_driver_get_reg_ofs,
- .postinit = postinit,
- .version = version,
- .ioctls = ioctls,
- .num_ioctls = DRM_ARRAY_SIZE(ioctls),
- .fops = {
- .owner = THIS_MODULE,
- .open = drm_open,
- .release = drm_release,
- .ioctl = drm_ioctl,
- .mmap = drm_mmap,
- .poll = drm_poll,
- .fasync = drm_fasync,
- }
- ,
-};
-
-static int __init ffb_init(void)
-{
- return -ENODEV;
-}
-
-static void __exit ffb_exit(void)
-{
-}
-
-module_init(ffb_init);
-module_exit(ffb_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/ffb_drv.h b/drivers/char/drm/ffb_drv.h
deleted file mode 100644
index 582afa6dd2b4..000000000000
--- a/drivers/char/drm/ffb_drv.h
+++ /dev/null
@@ -1,379 +0,0 @@
-/* $Id: ffb_drv.h,v 1.1 2000/06/01 04:24:39 davem Exp $
- * ffb_drv.h: Creator/Creator3D direct rendering driver.
- *
- * Copyright (C) 2000 David S. Miller (davem@redhat.com)
- */
-
-/* Auxilliary clips. */
-typedef struct {
- volatile unsigned int min;
- volatile unsigned int max;
-} ffb_auxclip, *ffb_auxclipPtr;
-
-/* FFB register set. */
-typedef struct _ffb_fbc {
- /* Next vertex registers, on the right we list which drawops
- * use said register and the logical name the register has in
- * that context.
- *//* DESCRIPTION DRAWOP(NAME) */
- /*0x00*/ unsigned int pad1[3];
- /* Reserved */
- /*0x0c*/ volatile unsigned int alpha;
- /* ALPHA Transparency */
- /*0x10*/ volatile unsigned int red;
- /* RED */
- /*0x14*/ volatile unsigned int green;
- /* GREEN */
- /*0x18*/ volatile unsigned int blue;
- /* BLUE */
- /*0x1c*/ volatile unsigned int z;
- /* DEPTH */
- /*0x20*/ volatile unsigned int y;
- /* Y triangle(DOYF) */
- /* aadot(DYF) */
- /* ddline(DYF) */
- /* aaline(DYF) */
- /*0x24*/ volatile unsigned int x;
- /* X triangle(DOXF) */
- /* aadot(DXF) */
- /* ddline(DXF) */
- /* aaline(DXF) */
- /*0x28*/ unsigned int pad2[2];
- /* Reserved */
- /*0x30*/ volatile unsigned int ryf;
- /* Y (alias to DOYF) ddline(RYF) */
- /* aaline(RYF) */
- /* triangle(RYF) */
- /*0x34*/ volatile unsigned int rxf;
- /* X ddline(RXF) */
- /* aaline(RXF) */
- /* triangle(RXF) */
- /*0x38*/ unsigned int pad3[2];
- /* Reserved */
- /*0x40*/ volatile unsigned int dmyf;
- /* Y (alias to DOYF) triangle(DMYF) */
- /*0x44*/ volatile unsigned int dmxf;
- /* X triangle(DMXF) */
- /*0x48*/ unsigned int pad4[2];
- /* Reserved */
- /*0x50*/ volatile unsigned int ebyi;
- /* Y (alias to RYI) polygon(EBYI) */
- /*0x54*/ volatile unsigned int ebxi;
- /* X polygon(EBXI) */
- /*0x58*/ unsigned int pad5[2];
- /* Reserved */
- /*0x60*/ volatile unsigned int by;
- /* Y brline(RYI) */
- /* fastfill(OP) */
- /* polygon(YI) */
- /* rectangle(YI) */
- /* bcopy(SRCY) */
- /* vscroll(SRCY) */
- /*0x64*/ volatile unsigned int bx;
- /* X brline(RXI) */
- /* polygon(XI) */
- /* rectangle(XI) */
- /* bcopy(SRCX) */
- /* vscroll(SRCX) */
- /* fastfill(GO) */
- /*0x68*/ volatile unsigned int dy;
- /* destination Y fastfill(DSTY) */
- /* bcopy(DSRY) */
- /* vscroll(DSRY) */
- /*0x6c*/ volatile unsigned int dx;
- /* destination X fastfill(DSTX) */
- /* bcopy(DSTX) */
- /* vscroll(DSTX) */
- /*0x70*/ volatile unsigned int bh;
- /* Y (alias to RYI) brline(DYI) */
- /* dot(DYI) */
- /* polygon(ETYI) */
- /* Height fastfill(H) */
- /* bcopy(H) */
- /* vscroll(H) */
- /* Y count fastfill(NY) */
- /*0x74*/ volatile unsigned int bw;
- /* X dot(DXI) */
- /* brline(DXI) */
- /* polygon(ETXI) */
- /* fastfill(W) */
- /* bcopy(W) */
- /* vscroll(W) */
- /* fastfill(NX) */
- /*0x78*/ unsigned int pad6[2];
- /* Reserved */
- /*0x80*/ unsigned int pad7[32];
- /* Reserved */
-
- /* Setup Unit's vertex state register */
-/*100*/ volatile unsigned int suvtx;
- /*104*/ unsigned int pad8[63];
- /* Reserved */
-
- /* Frame Buffer Control Registers */
- /*200*/ volatile unsigned int ppc;
- /* Pixel Processor Control */
- /*204*/ volatile unsigned int wid;
- /* Current WID */
- /*208*/ volatile unsigned int fg;
- /* FG data */
- /*20c*/ volatile unsigned int bg;
- /* BG data */
- /*210*/ volatile unsigned int consty;
- /* Constant Y */
- /*214*/ volatile unsigned int constz;
- /* Constant Z */
- /*218*/ volatile unsigned int xclip;
- /* X Clip */
- /*21c*/ volatile unsigned int dcss;
- /* Depth Cue Scale Slope */
- /*220*/ volatile unsigned int vclipmin;
- /* Viewclip XY Min Bounds */
- /*224*/ volatile unsigned int vclipmax;
- /* Viewclip XY Max Bounds */
- /*228*/ volatile unsigned int vclipzmin;
- /* Viewclip Z Min Bounds */
- /*22c*/ volatile unsigned int vclipzmax;
- /* Viewclip Z Max Bounds */
- /*230*/ volatile unsigned int dcsf;
- /* Depth Cue Scale Front Bound */
- /*234*/ volatile unsigned int dcsb;
- /* Depth Cue Scale Back Bound */
- /*238*/ volatile unsigned int dczf;
- /* Depth Cue Z Front */
- /*23c*/ volatile unsigned int dczb;
- /* Depth Cue Z Back */
- /*240*/ unsigned int pad9;
- /* Reserved */
- /*244*/ volatile unsigned int blendc;
- /* Alpha Blend Control */
- /*248*/ volatile unsigned int blendc1;
- /* Alpha Blend Color 1 */
- /*24c*/ volatile unsigned int blendc2;
- /* Alpha Blend Color 2 */
- /*250*/ volatile unsigned int fbramitc;
- /* FB RAM Interleave Test Control */
- /*254*/ volatile unsigned int fbc;
- /* Frame Buffer Control */
- /*258*/ volatile unsigned int rop;
- /* Raster OPeration */
- /*25c*/ volatile unsigned int cmp;
- /* Frame Buffer Compare */
- /*260*/ volatile unsigned int matchab;
- /* Buffer AB Match Mask */
- /*264*/ volatile unsigned int matchc;
- /* Buffer C(YZ) Match Mask */
- /*268*/ volatile unsigned int magnab;
- /* Buffer AB Magnitude Mask */
- /*26c*/ volatile unsigned int magnc;
- /* Buffer C(YZ) Magnitude Mask */
- /*270*/ volatile unsigned int fbcfg0;
- /* Frame Buffer Config 0 */
- /*274*/ volatile unsigned int fbcfg1;
- /* Frame Buffer Config 1 */
- /*278*/ volatile unsigned int fbcfg2;
- /* Frame Buffer Config 2 */
- /*27c*/ volatile unsigned int fbcfg3;
- /* Frame Buffer Config 3 */
- /*280*/ volatile unsigned int ppcfg;
- /* Pixel Processor Config */
- /*284*/ volatile unsigned int pick;
- /* Picking Control */
- /*288*/ volatile unsigned int fillmode;
- /* FillMode */
- /*28c*/ volatile unsigned int fbramwac;
- /* FB RAM Write Address Control */
- /*290*/ volatile unsigned int pmask;
- /* RGB PlaneMask */
- /*294*/ volatile unsigned int xpmask;
- /* X PlaneMask */
- /*298*/ volatile unsigned int ypmask;
- /* Y PlaneMask */
- /*29c*/ volatile unsigned int zpmask;
- /* Z PlaneMask */
- /*2a0*/ ffb_auxclip auxclip[4];
- /* Auxilliary Viewport Clip */
-
- /* New 3dRAM III support regs */
-/*2c0*/ volatile unsigned int rawblend2;
-/*2c4*/ volatile unsigned int rawpreblend;
-/*2c8*/ volatile unsigned int rawstencil;
-/*2cc*/ volatile unsigned int rawstencilctl;
-/*2d0*/ volatile unsigned int threedram1;
-/*2d4*/ volatile unsigned int threedram2;
-/*2d8*/ volatile unsigned int passin;
-/*2dc*/ volatile unsigned int rawclrdepth;
-/*2e0*/ volatile unsigned int rawpmask;
-/*2e4*/ volatile unsigned int rawcsrc;
-/*2e8*/ volatile unsigned int rawmatch;
-/*2ec*/ volatile unsigned int rawmagn;
-/*2f0*/ volatile unsigned int rawropblend;
-/*2f4*/ volatile unsigned int rawcmp;
-/*2f8*/ volatile unsigned int rawwac;
-/*2fc*/ volatile unsigned int fbramid;
-
- /*300*/ volatile unsigned int drawop;
- /* Draw OPeration */
- /*304*/ unsigned int pad10[2];
- /* Reserved */
- /*30c*/ volatile unsigned int lpat;
- /* Line Pattern control */
- /*310*/ unsigned int pad11;
- /* Reserved */
- /*314*/ volatile unsigned int fontxy;
- /* XY Font coordinate */
- /*318*/ volatile unsigned int fontw;
- /* Font Width */
- /*31c*/ volatile unsigned int fontinc;
- /* Font Increment */
- /*320*/ volatile unsigned int font;
- /* Font bits */
- /*324*/ unsigned int pad12[3];
- /* Reserved */
-/*330*/ volatile unsigned int blend2;
-/*334*/ volatile unsigned int preblend;
-/*338*/ volatile unsigned int stencil;
-/*33c*/ volatile unsigned int stencilctl;
-
- /*340*/ unsigned int pad13[4];
- /* Reserved */
- /*350*/ volatile unsigned int dcss1;
- /* Depth Cue Scale Slope 1 */
- /*354*/ volatile unsigned int dcss2;
- /* Depth Cue Scale Slope 2 */
- /*358*/ volatile unsigned int dcss3;
- /* Depth Cue Scale Slope 3 */
-/*35c*/ volatile unsigned int widpmask;
-/*360*/ volatile unsigned int dcs2;
-/*364*/ volatile unsigned int dcs3;
-/*368*/ volatile unsigned int dcs4;
- /*36c*/ unsigned int pad14;
- /* Reserved */
-/*370*/ volatile unsigned int dcd2;
-/*374*/ volatile unsigned int dcd3;
-/*378*/ volatile unsigned int dcd4;
- /*37c*/ unsigned int pad15;
- /* Reserved */
- /*380*/ volatile unsigned int pattern[32];
- /* area Pattern */
- /*400*/ unsigned int pad16[8];
- /* Reserved */
- /*420*/ volatile unsigned int reset;
- /* chip RESET */
- /*424*/ unsigned int pad17[247];
- /* Reserved */
- /*800*/ volatile unsigned int devid;
- /* Device ID */
- /*804*/ unsigned int pad18[63];
- /* Reserved */
- /*900*/ volatile unsigned int ucsr;
- /* User Control & Status Register */
- /*904*/ unsigned int pad19[31];
- /* Reserved */
- /*980*/ volatile unsigned int mer;
- /* Mode Enable Register */
- /*984*/ unsigned int pad20[1439];
- /* Reserved */
-} ffb_fbc, *ffb_fbcPtr;
-
-struct ffb_hw_context {
- int is_2d_only;
-
- unsigned int ppc;
- unsigned int wid;
- unsigned int fg;
- unsigned int bg;
- unsigned int consty;
- unsigned int constz;
- unsigned int xclip;
- unsigned int dcss;
- unsigned int vclipmin;
- unsigned int vclipmax;
- unsigned int vclipzmin;
- unsigned int vclipzmax;
- unsigned int dcsf;
- unsigned int dcsb;
- unsigned int dczf;
- unsigned int dczb;
- unsigned int blendc;
- unsigned int blendc1;
- unsigned int blendc2;
- unsigned int fbc;
- unsigned int rop;
- unsigned int cmp;
- unsigned int matchab;
- unsigned int matchc;
- unsigned int magnab;
- unsigned int magnc;
- unsigned int pmask;
- unsigned int xpmask;
- unsigned int ypmask;
- unsigned int zpmask;
- unsigned int auxclip0min;
- unsigned int auxclip0max;
- unsigned int auxclip1min;
- unsigned int auxclip1max;
- unsigned int auxclip2min;
- unsigned int auxclip2max;
- unsigned int auxclip3min;
- unsigned int auxclip3max;
- unsigned int drawop;
- unsigned int lpat;
- unsigned int fontxy;
- unsigned int fontw;
- unsigned int fontinc;
- unsigned int area_pattern[32];
- unsigned int ucsr;
- unsigned int stencil;
- unsigned int stencilctl;
- unsigned int dcss1;
- unsigned int dcss2;
- unsigned int dcss3;
- unsigned int dcs2;
- unsigned int dcs3;
- unsigned int dcs4;
- unsigned int dcd2;
- unsigned int dcd3;
- unsigned int dcd4;
- unsigned int mer;
-};
-
-#define FFB_MAX_CTXS 32
-
-enum ffb_chip_type {
- ffb1_prototype = 0, /* Early pre-FCS FFB */
- ffb1_standard, /* First FCS FFB, 100Mhz UPA, 66MHz gclk */
- ffb1_speedsort, /* Second FCS FFB, 100Mhz UPA, 75MHz gclk */
- ffb2_prototype, /* Early pre-FCS vertical FFB2 */
- ffb2_vertical, /* First FCS FFB2/vertical, 100Mhz UPA, 100MHZ gclk,
- 75(SingleBuffer)/83(DoubleBuffer) MHz fclk */
- ffb2_vertical_plus, /* Second FCS FFB2/vertical, same timings */
- ffb2_horizontal, /* First FCS FFB2/horizontal, same timings as FFB2/vert */
- ffb2_horizontal_plus, /* Second FCS FFB2/horizontal, same timings */
- afb_m3, /* FCS Elite3D, 3 float chips */
- afb_m6 /* FCS Elite3D, 6 float chips */
-};
-
-typedef struct ffb_dev_priv {
- /* Misc software state. */
- int prom_node;
- enum ffb_chip_type ffb_type;
- u64 card_phys_base;
- struct miscdevice miscdev;
-
- /* Controller registers. */
- ffb_fbcPtr regs;
-
- /* Context table. */
- struct ffb_hw_context *hw_state[FFB_MAX_CTXS];
-} ffb_dev_priv_t;
-
-extern unsigned long ffb_get_unmapped_area(struct file *filp,
- unsigned long hint,
- unsigned long len,
- unsigned long pgoff,
- unsigned long flags);
-extern void ffb_set_context_ioctls(void);
-extern drm_ioctl_desc_t DRM(ioctls)[];
-
-extern int ffb_driver_context_switch(drm_device_t * dev, int old, int new);
diff --git a/drivers/char/ds1286.c b/drivers/char/ds1286.c
index 6d58b0370802..59146e3365ba 100644
--- a/drivers/char/ds1286.c
+++ b/drivers/char/ds1286.c
@@ -197,6 +197,7 @@ static int ds1286_ioctl(struct inode *inode, struct file *file,
hrs = alm_tm.tm_hour;
min = alm_tm.tm_min;
+ sec = alm_tm.tm_sec;
if (hrs >= 24)
hrs = 0xff;
@@ -204,9 +205,11 @@ static int ds1286_ioctl(struct inode *inode, struct file *file,
if (min >= 60)
min = 0xff;
- BIN_TO_BCD(sec);
- BIN_TO_BCD(min);
- BIN_TO_BCD(hrs);
+ if (sec != 0)
+ return -EINVAL;
+
+ min = BIN2BCD(min);
+ min = BIN2BCD(hrs);
spin_lock(&ds1286_lock);
rtc_write(hrs, RTC_HOURS_ALARM);
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
index 337bbcdcf13d..8ea02755b1c9 100644
--- a/drivers/char/generic_serial.c
+++ b/drivers/char/generic_serial.c
@@ -710,12 +710,6 @@ void gs_close(struct tty_struct * tty, struct file * filp)
}
-static unsigned int gs_baudrates[] = {
- 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
- 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
-};
-
-
void gs_set_termios (struct tty_struct * tty,
struct ktermios * old_termios)
{
@@ -771,7 +765,6 @@ void gs_set_termios (struct tty_struct * tty,
baudrate = tty_get_baud_rate(tty);
- baudrate = gs_baudrates[baudrate];
if ((tiosp->c_cflag & CBAUD) == B38400) {
if ( (port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
baudrate = 57600;
diff --git a/drivers/char/lcd.c b/drivers/char/lcd.c
index 5f4fdcf7c96e..1f0962616ee5 100644
--- a/drivers/char/lcd.c
+++ b/drivers/char/lcd.c
@@ -11,9 +11,6 @@
* March 2001: Ported from 2.0.34 by Liam Davies
*
*/
-
-#define RTC_IO_EXTENT 0x10 /*Only really two ports, but... */
-
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
@@ -32,8 +29,6 @@
#include "lcd.h"
-static DEFINE_SPINLOCK(lcd_lock);
-
static int lcd_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index e45326856680..7a32df594907 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1376,6 +1376,8 @@ static void do_tty_hangup(struct work_struct *work)
read_unlock(&tasklist_lock);
tty->flags = 0;
+ put_pid(tty->session);
+ put_pid(tty->pgrp);
tty->session = NULL;
tty->pgrp = NULL;
tty->ctrl_status = 0;
@@ -3841,6 +3843,9 @@ static struct pid *__proc_set_tty(struct task_struct *tsk, struct tty_struct *tt
{
struct pid *old_pgrp;
if (tty) {
+ /* We should not have a session or pgrp to here but.... */
+ put_pid(tty->session);
+ put_pid(tty->pgrp);
tty->session = get_pid(task_session(tsk));
tty->pgrp = get_pid(task_pgrp(tsk));
}
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index c3f8e383933b..1bbb45b937fd 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -724,6 +724,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
return -ENOMEM;
memset(vc, 0, sizeof(*vc));
vc_cons[currcons].d = vc;
+ INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
visual_init(vc, currcons, 1);
if (!*vc->vc_uni_pagedir_loc)
con_set_default_unimap(vc);
@@ -2185,10 +2186,28 @@ static void console_callback(struct work_struct *ignored)
release_console_sem();
}
-void set_console(int nr)
+int set_console(int nr)
{
+ struct vc_data *vc = vc_cons[fg_console].d;
+
+ if (!vc_cons_allocated(nr) || vt_dont_switch ||
+ (vc->vt_mode.mode == VT_AUTO && vc->vc_mode == KD_GRAPHICS)) {
+
+ /*
+ * Console switch will fail in console_callback() or
+ * change_console() so there is no point scheduling
+ * the callback
+ *
+ * Existing set_console() users don't check the return
+ * value so this shouldn't break anything
+ */
+ return -EINVAL;
+ }
+
want_console = nr;
schedule_console_callback();
+
+ return 0;
}
struct tty_driver *console_driver;
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 3a5d301e783b..c9f2dd620e87 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -34,7 +34,7 @@
#include <linux/kbd_diacr.h>
#include <linux/selection.h>
-static char vt_dont_switch;
+char vt_dont_switch;
extern struct tty_driver *console_driver;
#define VT_IS_IN_USE(i) (console_driver->ttys[i] && console_driver->ttys[i]->count)
@@ -1039,10 +1039,22 @@ int vt_waitactive(int vt)
add_wait_queue(&vt_activate_queue, &wait);
for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
retval = 0;
- if (vt == fg_console)
+
+ /*
+ * Synchronize with redraw_screen(). By acquiring the console
+ * semaphore we make sure that the console switch is completed
+ * before we return. If we didn't wait for the semaphore, we
+ * could return at a point where fg_console has already been
+ * updated, but the console switch hasn't been completed.
+ */
+ acquire_console_sem();
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (vt == fg_console) {
+ release_console_sem();
break;
+ }
+ release_console_sem();
retval = -EINTR;
if (signal_pending(current))
break;
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index ea09d0c974ea..e812aa129e28 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -301,6 +301,7 @@ config I6300ESB_WDT
config I8XX_TCO
tristate "Intel i8xx TCO Timer/Watchdog"
depends on WATCHDOG && (X86 || IA64) && PCI
+ default n
---help---
Hardware driver for the TCO timer built into the Intel 82801
I/O Controller Hub family. The TCO (Total Cost of Ownership)
diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c
index 4a328ba0d262..76c7fa37fa6c 100644
--- a/drivers/char/watchdog/machzwd.c
+++ b/drivers/char/watchdog/machzwd.c
@@ -314,21 +314,21 @@ static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
{
void __user *argp = (void __user *)arg;
int __user *p = argp;
- switch(cmd){
- case WDIOC_GETSUPPORT:
- if (copy_to_user(argp, &zf_info, sizeof(zf_info)))
- return -EFAULT;
- break;
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ if (copy_to_user(argp, &zf_info, sizeof(zf_info)))
+ return -EFAULT;
+ break;
- case WDIOC_GETSTATUS:
- return put_user(0, p);
+ case WDIOC_GETSTATUS:
+ return put_user(0, p);
- case WDIOC_KEEPALIVE:
- zf_ping(0);
- break;
+ case WDIOC_KEEPALIVE:
+ zf_ping(0);
+ break;
- default:
- return -ENOTTY;
+ default:
+ return -ENOTTY;
}
return 0;
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c
index d42060ede930..5ac309ee7f05 100644
--- a/drivers/clocksource/acpi_pm.c
+++ b/drivers/clocksource/acpi_pm.c
@@ -90,7 +90,7 @@ __setup("acpi_pm_good", acpi_pm_good_setup);
static inline void acpi_pm_need_workaround(void)
{
clocksource_acpi_pm.read = acpi_pm_read_slow;
- clocksource_acpi_pm.rating = 110;
+ clocksource_acpi_pm.rating = 120;
}
/*
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index a44db75bc25b..a905f7820331 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -128,7 +128,7 @@ EXPORT_SYMBOL_GPL(cn_netlink_send);
*/
static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), void *data)
{
- struct cn_callback_entry *__cbq;
+ struct cn_callback_entry *__cbq, *__new_cbq;
struct cn_dev *dev = &cdev;
int err = -ENODEV;
@@ -148,27 +148,27 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v
} else {
struct cn_callback_data *d;
- __cbq = kzalloc(sizeof(*__cbq), GFP_ATOMIC);
- if (__cbq) {
- d = &__cbq->data;
+ err = -ENOMEM;
+ __new_cbq = kzalloc(sizeof(struct cn_callback_entry), GFP_ATOMIC);
+ if (__new_cbq) {
+ d = &__new_cbq->data;
d->callback_priv = msg;
d->callback = __cbq->data.callback;
d->ddata = data;
d->destruct_data = destruct_data;
- d->free = __cbq;
+ d->free = __new_cbq;
- INIT_WORK(&__cbq->work,
+ INIT_WORK(&__new_cbq->work,
&cn_queue_wrapper);
-
+
if (queue_work(dev->cbdev->cn_queue,
- &__cbq->work))
+ &__new_cbq->work))
err = 0;
else {
- kfree(__cbq);
+ kfree(__new_cbq);
err = -EINVAL;
}
- } else
- err = -ENOMEM;
+ }
}
break;
}
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index f52facc570f5..3162010900c9 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1015,6 +1015,10 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
{
unsigned int cpu = sys_dev->id;
int retval;
+
+ if (cpu_is_offline(cpu))
+ return 0;
+
if (unlikely(lock_policy_rwsem_write(cpu)))
BUG();
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 15278044295c..322ee2984e3d 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -176,6 +176,7 @@ void dma_chan_cleanup(struct kref *kref)
chan->client = NULL;
kref_put(&chan->device->refcount, dma_async_device_cleanup);
}
+EXPORT_SYMBOL(dma_chan_cleanup);
static void dma_chan_free_rcu(struct rcu_head *rcu)
{
@@ -261,6 +262,7 @@ struct dma_client *dma_async_client_register(dma_event_callback event_callback)
return client;
}
+EXPORT_SYMBOL(dma_async_client_register);
/**
* dma_async_client_unregister - unregister a client and free the &dma_client
@@ -287,6 +289,7 @@ void dma_async_client_unregister(struct dma_client *client)
kfree(client);
dma_chans_rebalance();
}
+EXPORT_SYMBOL(dma_async_client_unregister);
/**
* dma_async_client_chan_request - request DMA channels
@@ -304,6 +307,7 @@ void dma_async_client_chan_request(struct dma_client *client,
client->chans_desired = number;
dma_chans_rebalance();
}
+EXPORT_SYMBOL(dma_async_client_chan_request);
/**
* dma_async_device_register - registers DMA devices found
@@ -346,6 +350,7 @@ int dma_async_device_register(struct dma_device *device)
return 0;
}
+EXPORT_SYMBOL(dma_async_device_register);
/**
* dma_async_device_cleanup - function called when all references are released
@@ -390,23 +395,12 @@ void dma_async_device_unregister(struct dma_device *device)
kref_put(&device->refcount, dma_async_device_cleanup);
wait_for_completion(&device->done);
}
+EXPORT_SYMBOL(dma_async_device_unregister);
static int __init dma_bus_init(void)
{
mutex_init(&dma_list_mutex);
return class_register(&dma_devclass);
}
-
subsys_initcall(dma_bus_init);
-EXPORT_SYMBOL(dma_async_client_register);
-EXPORT_SYMBOL(dma_async_client_unregister);
-EXPORT_SYMBOL(dma_async_client_chan_request);
-EXPORT_SYMBOL(dma_async_memcpy_buf_to_buf);
-EXPORT_SYMBOL(dma_async_memcpy_buf_to_pg);
-EXPORT_SYMBOL(dma_async_memcpy_pg_to_pg);
-EXPORT_SYMBOL(dma_async_memcpy_complete);
-EXPORT_SYMBOL(dma_async_memcpy_issue_pending);
-EXPORT_SYMBOL(dma_async_device_register);
-EXPORT_SYMBOL(dma_async_device_unregister);
-EXPORT_SYMBOL(dma_chan_cleanup);
diff --git a/drivers/eisa/pci_eisa.c b/drivers/eisa/pci_eisa.c
index 9e913629ef39..74edb1d0110f 100644
--- a/drivers/eisa/pci_eisa.c
+++ b/drivers/eisa/pci_eisa.c
@@ -19,8 +19,8 @@
/* There is only *one* pci_eisa device per machine, right ? */
static struct eisa_root_device pci_eisa_root;
-static int __devinit pci_eisa_init (struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int __init pci_eisa_init(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
int rc;
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index f4ee1afe488f..1cca32f46947 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -26,6 +26,7 @@
#include <asm/byteorder.h>
#include <linux/input.h>
#include <linux/wait.h>
+#include <linux/vmalloc.h>
#include <linux/hid.h>
#include <linux/hiddev.h>
@@ -654,12 +655,13 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
memcpy(device->rdesc, start, size);
device->rsize = size;
- if (!(parser = kzalloc(sizeof(struct hid_parser), GFP_KERNEL))) {
+ if (!(parser = vmalloc(sizeof(struct hid_parser)))) {
kfree(device->rdesc);
kfree(device->collection);
kfree(device);
return NULL;
}
+ memset(parser, 0, sizeof(struct hid_parser));
parser->device = device;
end = start + size;
@@ -668,7 +670,7 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
if (item.format != HID_ITEM_FORMAT_SHORT) {
dbg("unexpected long global item");
hid_free_device(device);
- kfree(parser);
+ vfree(parser);
return NULL;
}
@@ -676,7 +678,7 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
dbg("item %u %u %u %u parsing failed\n",
item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
hid_free_device(device);
- kfree(parser);
+ vfree(parser);
return NULL;
}
@@ -684,23 +686,23 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
if (parser->collection_stack_ptr) {
dbg("unbalanced collection at end of report description");
hid_free_device(device);
- kfree(parser);
+ vfree(parser);
return NULL;
}
if (parser->local.delimiter_depth) {
dbg("unbalanced delimiter at end of report description");
hid_free_device(device);
- kfree(parser);
+ vfree(parser);
return NULL;
}
- kfree(parser);
+ vfree(parser);
return device;
}
}
dbg("item fetching failed at offset %d\n", (int)(end - start));
hid_free_device(device);
- kfree(parser);
+ vfree(parser);
return NULL;
}
EXPORT_SYMBOL_GPL(hid_parse_report);
@@ -753,8 +755,7 @@ static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
report += offset >> 3; /* adjust byte index */
offset &= 7; /* now only need bit offset into one byte */
- x = get_unaligned((u64 *) report);
- x = le64_to_cpu(x);
+ x = le64_to_cpu(get_unaligned((__le64 *) report));
x = (x >> offset) & ((1ULL << n) - 1); /* extract bit field */
return (u32) x;
}
@@ -769,7 +770,7 @@ static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
*/
static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
{
- u64 x;
+ __le64 x;
u64 m = (1ULL << n) - 1;
WARN_ON(n > 32);
@@ -780,10 +781,10 @@ static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u3
report += offset >> 3;
offset &= 7;
- x = get_unaligned((u64 *)report);
+ x = get_unaligned((__le64 *)report);
x &= cpu_to_le64(~(m << offset));
x |= cpu_to_le64(((u64) value) << offset);
- put_unaligned(x, (u64 *) report);
+ put_unaligned(x, (__le64 *) report);
}
/*
@@ -873,10 +874,6 @@ static void hid_output_field(struct hid_field *field, __u8 *data)
unsigned size = field->report_size;
unsigned n;
- /* make sure the unused bits in the last byte are zeros */
- if (count > 0 && size > 0)
- data[(offset+count*size-1)/8] = 0;
-
for (n = 0; n < count; n++) {
if (field->logical_minimum < 0) /* signed values */
implement(data, offset + n * size, size, s32ton(field->value[n], size));
@@ -972,7 +969,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
if (size < rsize) {
dbg("report %d is too short, (%d < %d)", report->id, size, rsize);
- return -1;
+ memset(data + size, 0, rsize - size);
}
if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index c3d4856fb618..6d105a1d41b1 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -527,6 +527,7 @@ config SENSORS_W83792D
config SENSORS_W83793
tristate "Winbond W83793"
depends on HWMON && I2C && EXPERIMENTAL
+ select HWMON_VID
help
If you say yes here you get support for the Winbond W83793
hardware monitoring chip.
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index e15f9e37716a..0c70f8293341 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -254,7 +254,8 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,
break;
case I2C_SMBUS_BLOCK_PROC_CALL:
- len = min_t(u8, data->block[0], 31);
+ len = min_t(u8, data->block[0],
+ I2C_SMBUS_BLOCK_MAX - 1);
amd_ec_write(smbus, AMD_SMB_CMD, command);
amd_ec_write(smbus, AMD_SMB_BCNT, len);
for (i = 0; i < len; i++)
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 6569a36985bd..a320e7d82c1f 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -97,6 +97,7 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
int command, int hwpec);
static unsigned long i801_smba;
+static unsigned char i801_original_hstcfg;
static struct pci_driver i801_driver;
static struct pci_dev *I801_dev;
static int isich4;
@@ -510,6 +511,7 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
}
pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
+ i801_original_hstcfg = temp;
temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */
if (!(temp & SMBHSTCFG_HST_EN)) {
dev_info(&dev->dev, "Enabling SMBus device\n");
@@ -543,6 +545,7 @@ exit:
static void __devexit i801_remove(struct pci_dev *dev)
{
i2c_del_adapter(&i801_adapter);
+ pci_write_config_byte(I801_dev, SMBHSTCFG, i801_original_hstcfg);
pci_release_region(dev, SMBBAR);
/*
* do not call pci_disable_device(dev) since it can cause hard hangs on
@@ -550,11 +553,33 @@ static void __devexit i801_remove(struct pci_dev *dev)
*/
}
+#ifdef CONFIG_PM
+static int i801_suspend(struct pci_dev *dev, pm_message_t mesg)
+{
+ pci_save_state(dev);
+ pci_write_config_byte(dev, SMBHSTCFG, i801_original_hstcfg);
+ pci_set_power_state(dev, pci_choose_state(dev, mesg));
+ return 0;
+}
+
+static int i801_resume(struct pci_dev *dev)
+{
+ pci_set_power_state(dev, PCI_D0);
+ pci_restore_state(dev);
+ return pci_enable_device(dev);
+}
+#else
+#define i801_suspend NULL
+#define i801_resume NULL
+#endif
+
static struct pci_driver i801_driver = {
.name = "i801_smbus",
.id_table = i801_ids,
.probe = i801_probe,
.remove = __devexit_p(i801_remove),
+ .suspend = i801_suspend,
+ .resume = i801_resume,
};
static int __init i2c_i801_init(void)
diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c
index 15edf40828b4..8a2ff0c114d9 100644
--- a/drivers/i2c/chips/ds1374.c
+++ b/drivers/i2c/chips/ds1374.c
@@ -207,6 +207,10 @@ static int ds1374_probe(struct i2c_adapter *adap, int addr, int kind)
client->driver = &ds1374_driver;
ds1374_workqueue = create_singlethread_workqueue("ds1374");
+ if (!ds1374_workqueue) {
+ kfree(client);
+ return -ENOMEM; /* most expected reason */
+ }
if ((rc = i2c_attach_client(client)) != 0) {
kfree(client);
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 5d134bb75ba1..ca2e4f830c39 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -103,8 +103,10 @@ config BLK_DEV_IDE_SATA
---help---
There are two drivers for Serial ATA controllers.
- The main driver, "libata", exists inside the SCSI subsystem
- and supports most modern SATA controllers.
+ The main driver, "libata", uses the SCSI subsystem
+ and supports most modern SATA controllers. In order to use it
+ you may take a look at "Serial ATA (prod) and Parallel ATA
+ (experimental) drivers".
The IDE driver (which you are currently configuring) supports
a few first-generation SATA controllers.
@@ -434,24 +436,8 @@ config BLK_DEV_IDEDMA_FORCED
Generally say N here.
-config IDEDMA_PCI_AUTO
- bool "Use PCI DMA by default when available"
- ---help---
- Prior to kernel version 2.1.112, Linux used to automatically use
- DMA for IDE drives and chipsets which support it. Due to concerns
- about a couple of cases where buggy hardware may have caused damage,
- the default is now to NOT use DMA automatically. To revert to the
- previous behaviour, say Y to this question.
-
- If you suspect your hardware is at all flakey, say N here.
- Do NOT email the IDE kernel people regarding this issue!
-
- It is normally safe to answer Y to this question unless your
- motherboard uses a VIA VP2 chipset, in which case you should say N.
-
config IDEDMA_ONLYDISK
bool "Enable DMA only for disks "
- depends on IDEDMA_PCI_AUTO
help
This is used if you know your ATAPI Devices are going to fail DMA
Transfers.
@@ -769,6 +755,14 @@ config BLK_DEV_TC86C001
help
This driver adds support for Toshiba TC86C001 GOKU-S chip.
+config BLK_DEV_CELLEB
+ tristate "Toshiba's Cell Reference Set IDE support"
+ depends on PPC_CELLEB
+ help
+ This driver provides support for the built-in IDE controller on
+ Toshiba Cell Reference Board.
+ If unsure, say Y.
+
endif
config BLK_DEV_IDE_PMAC
@@ -800,14 +794,6 @@ config BLK_DEV_IDEDMA_PMAC
to transfer data to and from memory. Saying Y is safe and improves
performance.
-config BLK_DEV_IDE_CELLEB
- bool "Toshiba's Cell Reference Set IDE support"
- depends on PPC_CELLEB
- help
- This driver provides support for the built-in IDE controller on
- Toshiba Cell Reference Board.
- If unsure, say Y.
-
config BLK_DEV_IDE_SWARM
tristate "IDE for Sibyte evaluation boards"
depends on SIBYTE_SB1xxx_SOC
@@ -851,19 +837,6 @@ config BLK_DEV_IDEDMA_ICS
Say Y here if you want to add DMA (Direct Memory Access) support to
the ICS IDE driver.
-config IDEDMA_ICS_AUTO
- bool "Use ICS DMA by default"
- depends on BLK_DEV_IDEDMA_ICS
- help
- Prior to kernel version 2.1.112, Linux used to automatically use
- DMA for IDE drives and chipsets which support it. Due to concerns
- about a couple of cases where buggy hardware may have caused damage,
- the default is now to NOT use DMA automatically. To revert to the
- previous behaviour, say Y to this question.
-
- If you suspect your hardware is at all flakey, say N here.
- Do NOT email the IDE kernel people regarding this issue!
-
config BLK_DEV_IDE_RAPIDE
tristate "RapIDE interface support"
depends on ARM && ARCH_ACORN
@@ -1086,9 +1059,6 @@ config IDEDMA_IVB
It is normally safe to answer Y; however, the default is N.
-config IDEDMA_AUTO
- def_bool IDEDMA_PCI_AUTO || IDEDMA_ICS_AUTO
-
endif
config BLK_DEV_HD_ONLY
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index 28feedfbd21d..d9f029e8ff74 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -37,7 +37,6 @@ ide-core-$(CONFIG_BLK_DEV_Q40IDE) += legacy/q40ide.o
# built-in only drivers from ppc/
ide-core-$(CONFIG_BLK_DEV_MPC8xx_IDE) += ppc/mpc8xx.o
ide-core-$(CONFIG_BLK_DEV_IDE_PMAC) += ppc/pmac.o
-ide-core-$(CONFIG_BLK_DEV_IDE_CELLEB) += ppc/scc_pata.o
# built-in only drivers from h8300/
ide-core-$(CONFIG_H8300) += h8300/ide-h8300.o
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
index 40e5c66b81ce..e2953fc1fafb 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/arm/icside.c
@@ -196,11 +196,6 @@ static void icside_maskproc(ide_drive_t *drive, int mask)
}
#ifdef CONFIG_BLK_DEV_IDEDMA_ICS
-
-#ifndef CONFIG_IDEDMA_ICS_AUTO
-#warning CONFIG_IDEDMA_ICS_AUTO=n support is obsolete, and will be removed soon.
-#endif
-
/*
* SG-DMA support.
*
@@ -474,12 +469,6 @@ static int icside_dma_lostirq(ide_drive_t *drive)
static void icside_dma_init(ide_hwif_t *hwif)
{
- int autodma = 0;
-
-#ifdef CONFIG_IDEDMA_ICS_AUTO
- autodma = 1;
-#endif
-
printk(" %s: SG-DMA", hwif->name);
hwif->atapi_dma = 1;
@@ -489,7 +478,7 @@ static void icside_dma_init(ide_hwif_t *hwif)
hwif->dmatable_cpu = NULL;
hwif->dmatable_dma = 0;
hwif->speedproc = icside_set_speed;
- hwif->autodma = autodma;
+ hwif->autodma = 1;
hwif->ide_dma_check = icside_dma_check;
hwif->dma_host_off = icside_dma_host_off;
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 45a928c058cf..638becda81c6 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -735,6 +735,15 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
cdrom_saw_media_change (drive);
/*printk("%s: media changed\n",drive->name);*/
return 0;
+ } else if ((sense_key == ILLEGAL_REQUEST) &&
+ (rq->cmd[0] == GPCMD_START_STOP_UNIT)) {
+ /*
+ * Don't print error message for this condition--
+ * SFF8090i indicates that 5/24/00 is the correct
+ * response to a request to close the tray if the
+ * drive doesn't have that capability.
+ * cdrom_log_sense() knows this!
+ */
} else if (!(rq->cmd_flags & REQ_QUIET)) {
/* Otherwise, print an error. */
ide_dump_status(drive, "packet command error", stat);
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 08e7cd043bcc..fd213088b06b 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -767,7 +767,7 @@ int ide_set_dma(ide_drive_t *drive)
switch(rc) {
case -1: /* DMA needs to be disabled */
hwif->dma_off_quietly(drive);
- return 0;
+ return -1;
case 0: /* DMA needs to be enabled */
return hwif->ide_dma_on(drive);
case 1: /* DMA setting cannot be changed */
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index c193553f6fe7..8670112f1d39 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -519,21 +519,24 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ && hwif->err_stops_fifo == 0)
try_to_flush_leftover_data(drive);
+ if (rq->errors >= ERROR_MAX || blk_noretry_request(rq)) {
+ ide_kill_rq(drive, rq);
+ return ide_stopped;
+ }
+
if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT))
- /* force an abort */
- hwif->OUTB(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG);
+ rq->errors |= ERROR_RESET;
- if (rq->errors >= ERROR_MAX || blk_noretry_request(rq))
- ide_kill_rq(drive, rq);
- else {
- if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
- ++rq->errors;
- return ide_do_reset(drive);
- }
- if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
- drive->special.b.recalibrate = 1;
+ if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
++rq->errors;
+ return ide_do_reset(drive);
}
+
+ if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
+ drive->special.b.recalibrate = 1;
+
+ ++rq->errors;
+
return ide_stopped;
}
@@ -1025,6 +1028,13 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
if (!drive->special.all) {
ide_driver_t *drv;
+ /*
+ * We reset the drive so we need to issue a SETFEATURES.
+ * Do it _after_ do_special() restored device parameters.
+ */
+ if (drive->current_speed == 0xff)
+ ide_config_drive_speed(drive, drive->desired_speed);
+
if (rq->cmd_type == REQ_TYPE_ATA_CMD ||
rq->cmd_type == REQ_TYPE_ATA_TASK ||
rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
@@ -1216,6 +1226,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
#endif
/* so that ide_timer_expiry knows what to do */
hwgroup->sleeping = 1;
+ hwgroup->req_gen_timer = hwgroup->req_gen;
mod_timer(&hwgroup->timer, sleep);
/* we purposely leave hwgroup->busy==1
* while sleeping */
@@ -1401,7 +1412,8 @@ void ide_timer_expiry (unsigned long data)
spin_lock_irqsave(&ide_lock, flags);
- if ((handler = hwgroup->handler) == NULL) {
+ if (((handler = hwgroup->handler) == NULL) ||
+ (hwgroup->req_gen != hwgroup->req_gen_timer)) {
/*
* Either a marginal timeout occurred
* (got the interrupt just as timer expired),
@@ -1429,6 +1441,7 @@ void ide_timer_expiry (unsigned long data)
if ((wait = expiry(drive)) > 0) {
/* reset timer */
hwgroup->timer.expires = jiffies + wait;
+ hwgroup->req_gen_timer = hwgroup->req_gen;
add_timer(&hwgroup->timer);
spin_unlock_irqrestore(&ide_lock, flags);
return;
@@ -1643,6 +1656,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
printk(KERN_ERR "%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name);
}
hwgroup->handler = NULL;
+ hwgroup->req_gen++;
del_timer(&hwgroup->timer);
spin_unlock(&ide_lock);
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index bd513f5a2323..3caa176b3155 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -583,8 +583,12 @@ u8 eighty_ninty_three (ide_drive_t *drive)
if(!(drive->id->hw_config & 0x4000))
return 0;
#endif /* CONFIG_IDEDMA_IVB */
- if (!(drive->id->hw_config & 0x2000))
- return 0;
+ /*
+ * FIXME:
+ * - change master/slave IDENTIFY order
+ * - force bit13 (80c cable present) check
+ * (unless the slave device is pre-ATA3)
+ */
return 1;
}
@@ -885,6 +889,7 @@ static void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
hwgroup->handler = handler;
hwgroup->expiry = expiry;
hwgroup->timer.expires = jiffies + timeout;
+ hwgroup->req_gen_timer = hwgroup->req_gen;
add_timer(&hwgroup->timer);
}
@@ -925,6 +930,7 @@ void ide_execute_command(ide_drive_t *drive, task_ioreg_t cmd, ide_handler_t *ha
hwgroup->handler = handler;
hwgroup->expiry = expiry;
hwgroup->timer.expires = jiffies + timeout;
+ hwgroup->req_gen_timer = hwgroup->req_gen;
add_timer(&hwgroup->timer);
hwif->OUTBSYNC(drive, cmd, IDE_COMMAND_REG);
/* Drive takes 400nS to respond, we must avoid the IRQ being
@@ -1090,6 +1096,9 @@ static void pre_reset(ide_drive_t *drive)
if (HWIF(drive)->pre_reset != NULL)
HWIF(drive)->pre_reset(drive);
+ if (drive->current_speed != 0xff)
+ drive->desired_speed = drive->current_speed;
+ drive->current_speed = 0xff;
}
/*
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index dfbd74458522..ae5bf2be6f52 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -177,11 +177,7 @@ DECLARE_MUTEX(ide_cfg_sem);
static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
#endif
-#ifdef CONFIG_IDEDMA_AUTO
int noautodma = 0;
-#else
-int noautodma = 1;
-#endif
EXPORT_SYMBOL(noautodma);
@@ -1128,17 +1124,40 @@ static int set_io_32bit(ide_drive_t *drive, int arg)
static int set_using_dma (ide_drive_t *drive, int arg)
{
#ifdef CONFIG_BLK_DEV_IDEDMA
+ ide_hwif_t *hwif = drive->hwif;
+ int err = -EPERM;
+
if (!drive->id || !(drive->id->capability & 1))
- return -EPERM;
- if (HWIF(drive)->ide_dma_check == NULL)
- return -EPERM;
+ goto out;
+
+ if (hwif->ide_dma_check == NULL)
+ goto out;
+
+ err = -EBUSY;
+ if (ide_spin_wait_hwgroup(drive))
+ goto out;
+ /*
+ * set ->busy flag, unlock and let it ride
+ */
+ hwif->hwgroup->busy = 1;
+ spin_unlock_irq(&ide_lock);
+
+ err = 0;
+
if (arg) {
- if (ide_set_dma(drive))
- return -EIO;
- if (HWIF(drive)->ide_dma_on(drive)) return -EIO;
+ if (ide_set_dma(drive) || hwif->ide_dma_on(drive))
+ err = -EIO;
} else
ide_dma_off(drive);
- return 0;
+
+ /*
+ * lock, clear ->busy flag and unlock before leaving
+ */
+ spin_lock_irq(&ide_lock);
+ hwif->hwgroup->busy = 0;
+ spin_unlock_irq(&ide_lock);
+out:
+ return err;
#else
return -EPERM;
#endif
@@ -1943,6 +1962,8 @@ static char *media_string(ide_drive_t *drive)
return "tape";
case ide_floppy:
return "floppy";
+ case ide_optical:
+ return "optical";
default:
return "UNKNOWN";
}
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
index b2dc028dc8ca..d54d9fe92a7d 100644
--- a/drivers/ide/mips/au1xxx-ide.c
+++ b/drivers/ide/mips/au1xxx-ide.c
@@ -639,6 +639,7 @@ static int au_ide_probe(struct device *dev)
_auide_hwif *ahwif = &auide_hwif;
ide_hwif_t *hwif;
struct resource *res;
+ hw_regs_t *hw;
int ret = 0;
#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
@@ -681,7 +682,7 @@ static int au_ide_probe(struct device *dev)
/* FIXME: This might possibly break PCMCIA IDE devices */
hwif = &ide_hwifs[pdev->id];
- hw_regs_t *hw = &hwif->hw;
+ hw = &hwif->hw;
hwif->irq = hw->irq = ahwif->irq;
hwif->chipset = ide_au1xxx;
diff --git a/drivers/ide/pci/Makefile b/drivers/ide/pci/Makefile
index 6591ff4753cb..95d1ea8f1f14 100644
--- a/drivers/ide/pci/Makefile
+++ b/drivers/ide/pci/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_BLK_DEV_AEC62XX) += aec62xx.o
obj-$(CONFIG_BLK_DEV_ALI15X3) += alim15x3.o
obj-$(CONFIG_BLK_DEV_AMD74XX) += amd74xx.o
obj-$(CONFIG_BLK_DEV_ATIIXP) += atiixp.o
+obj-$(CONFIG_BLK_DEV_CELLEB) += scc_pata.o
obj-$(CONFIG_BLK_DEV_CMD64X) += cmd64x.o
obj-$(CONFIG_BLK_DEV_CS5520) += cs5520.o
obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index b0d4825c56a9..561197f7b5bb 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -1,6 +1,6 @@
/* $Id: cmd64x.c,v 1.21 2000/01/30 23:23:16
*
- * linux/drivers/ide/pci/cmd64x.c Version 1.41 Feb 3, 2007
+ * linux/drivers/ide/pci/cmd64x.c Version 1.42 Feb 8, 2007
*
* cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
* Note, this driver is not used at all on other systems because
@@ -189,6 +189,11 @@ static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count)
#endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */
+static u8 quantize_timing(int timing, int quant)
+{
+ return (timing + quant - 1) / quant;
+}
+
/*
* This routine writes the prepared setup/active/recovery counts
* for a drive into the cmd646 chipset registers to active them.
@@ -268,47 +273,37 @@ static void program_drive_counts (ide_drive_t *drive, int setup_count, int activ
*/
static u8 cmd64x_tune_pio (ide_drive_t *drive, u8 mode_wanted)
{
- int setup_time, active_time, recovery_time;
- int clock_time, pio_mode, cycle_time;
- u8 recovery_count2, cycle_count;
- int setup_count, active_count, recovery_count;
- int bus_speed = system_bus_clock();
- ide_pio_data_t d;
+ int setup_time, active_time, cycle_time;
+ u8 cycle_count, setup_count, active_count, recovery_count;
+ u8 pio_mode;
+ int clock_time = 1000 / system_bus_clock();
+ ide_pio_data_t pio;
- pio_mode = ide_get_best_pio_mode(drive, mode_wanted, 5, &d);
- cycle_time = d.cycle_time;
+ pio_mode = ide_get_best_pio_mode(drive, mode_wanted, 5, &pio);
+ cycle_time = pio.cycle_time;
- /*
- * I copied all this complicated stuff from cmd640.c and made a few
- * minor changes. For now I am just going to pray that it is correct.
- */
setup_time = ide_pio_timings[pio_mode].setup_time;
active_time = ide_pio_timings[pio_mode].active_time;
- recovery_time = cycle_time - (setup_time + active_time);
- clock_time = 1000 / bus_speed;
- cycle_count = (cycle_time + clock_time - 1) / clock_time;
-
- setup_count = (setup_time + clock_time - 1) / clock_time;
- active_count = (active_time + clock_time - 1) / clock_time;
+ setup_count = quantize_timing( setup_time, clock_time);
+ cycle_count = quantize_timing( cycle_time, clock_time);
+ active_count = quantize_timing(active_time, clock_time);
- recovery_count = (recovery_time + clock_time - 1) / clock_time;
- recovery_count2 = cycle_count - (setup_count + active_count);
- if (recovery_count2 > recovery_count)
- recovery_count = recovery_count2;
+ recovery_count = cycle_count - active_count;
+ /* program_drive_counts() takes care of zero recovery cycles */
if (recovery_count > 16) {
active_count += recovery_count - 16;
recovery_count = 16;
}
if (active_count > 16)
- active_count = 16; /* maximum allowed by cmd646 */
+ active_count = 16; /* maximum allowed by cmd64x */
program_drive_counts (drive, setup_count, active_count, recovery_count);
cmdprintk("%s: PIO mode wanted %d, selected %d (%dns)%s, "
"clocks=%d/%d/%d\n",
drive->name, mode_wanted, pio_mode, cycle_time,
- d.overridden ? " (overriding vendor mode)" : "",
+ pio.overridden ? " (overriding vendor mode)" : "",
setup_count, active_count, recovery_count);
return pio_mode;
diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
index 53f25500c22b..be4fc96c29e0 100644
--- a/drivers/ide/pci/jmicron.c
+++ b/drivers/ide/pci/jmicron.c
@@ -240,12 +240,31 @@ static int __devinit jmicron_init_one(struct pci_dev *dev, const struct pci_devi
return 0;
}
+/* If libata is configured, jmicron PCI quirk will configure it such
+ * that the SATA ports are in AHCI function while the PATA ports are
+ * in a separate IDE function. In such cases, match device class and
+ * attach only to IDE. If libata isn't configured, keep the old
+ * behavior for backward compatibility.
+ */
+#if defined(CONFIG_ATA) || defined(CONFIG_ATA_MODULE)
+#define JMB_CLASS PCI_CLASS_STORAGE_IDE << 8
+#define JMB_CLASS_MASK 0xffff00
+#else
+#define JMB_CLASS 0
+#define JMB_CLASS_MASK 0
+#endif
+
static struct pci_device_id jmicron_pci_tbl[] = {
- { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
- { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
- { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
- { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
+ { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361,
+ PCI_ANY_ID, PCI_ANY_ID, JMB_CLASS, JMB_CLASS_MASK, 0},
+ { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363,
+ PCI_ANY_ID, PCI_ANY_ID, JMB_CLASS, JMB_CLASS_MASK, 1},
+ { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365,
+ PCI_ANY_ID, PCI_ANY_ID, JMB_CLASS, JMB_CLASS_MASK, 2},
+ { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366,
+ PCI_ANY_ID, PCI_ANY_ID, JMB_CLASS, JMB_CLASS_MASK, 3},
+ { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368,
+ PCI_ANY_ID, PCI_ANY_ID, JMB_CLASS, JMB_CLASS_MASK, 4},
{ 0, },
};
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index 6ceb25bc5a7b..ace98929cc3d 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -255,7 +255,7 @@ static int config_chipset_for_dma(ide_drive_t *drive)
printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name);
}
- if (drive->media != ide_disk)
+ if (drive->media != ide_disk && drive->media != ide_cdrom)
return 0;
if (id->capability & 4) {
@@ -545,6 +545,7 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif)
hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
+ hwif->atapi_dma = 1;
hwif->ultra_mask = 0x7f;
hwif->mwdma_mask = 0x07;
diff --git a/drivers/ide/ppc/scc_pata.c b/drivers/ide/pci/scc_pata.c
index f84bf791f72e..f84bf791f72e 100644
--- a/drivers/ide/ppc/scc_pata.c
+++ b/drivers/ide/pci/scc_pata.c
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index a52c80fe7d3e..118fb3205ca8 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -505,11 +505,6 @@ static void ide_hwif_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwi
}
}
}
-
-#ifndef CONFIG_IDEDMA_PCI_AUTO
-#warning CONFIG_IDEDMA_PCI_AUTO=n support is obsolete, and will be removed soon.
-#endif
-
#endif /* CONFIG_BLK_DEV_IDEDMA_PCI*/
/**
diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig
index b8a47342cd2c..cd84a55ecf20 100644
--- a/drivers/ieee1394/Kconfig
+++ b/drivers/ieee1394/Kconfig
@@ -138,9 +138,9 @@ config IEEE1394_DV1394
tristate "OHCI-DV I/O support (deprecated)"
depends on IEEE1394 && IEEE1394_OHCI1394
help
- The dv1394 driver will be removed from Linux in a future release.
- Its functionality is now provided by raw1394 together with libraries
- such as libiec61883.
+ The dv1394 driver is unsupported and may be removed from Linux in a
+ future release. Its functionality is now provided by raw1394 together
+ with libraries such as libiec61883.
config IEEE1394_RAWIO
tristate "Raw IEEE1394 I/O support"
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index dee9529aa8e7..026e38face5c 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -2564,8 +2564,8 @@ static int __init dv1394_init_module(void)
int ret;
printk(KERN_WARNING
- "WARNING: The dv1394 driver is unsupported and will be removed "
- "from Linux soon. Use raw1394 instead.\n");
+ "NOTE: The dv1394 driver is unsupported and may be removed in a "
+ "future Linux release. Use raw1394 instead.\n");
cdev_init(&dv1394_cdev, &dv1394_fops);
dv1394_cdev.owner = THIS_MODULE;
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index a95313521985..03e44b337eb0 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -584,7 +584,10 @@ static void ether1394_add_host (struct hpsb_host *host)
}
SET_MODULE_OWNER(dev);
+#if 0
+ /* FIXME - Is this the correct parent device anyway? */
SET_NETDEV_DEV(dev, &host->device);
+#endif
priv = netdev_priv(dev);
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index d441815a3e0c..fde92ce45153 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -1821,7 +1821,7 @@ static int cma_alloc_port(struct idr *ps, struct rdma_id_private *id_priv,
struct rdma_bind_list *bind_list;
int port, ret;
- bind_list = kmalloc(sizeof *bind_list, GFP_KERNEL);
+ bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL);
if (!bind_list)
return -ENOMEM;
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index b516b93b8550..c859134c1daa 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -266,7 +266,7 @@ static int ucma_event_handler(struct rdma_cm_id *cm_id,
mutex_lock(&ctx->file->mut);
if (event->event == RDMA_CM_EVENT_CONNECT_REQUEST) {
if (!ctx->backlog) {
- ret = -EDQUOT;
+ ret = -ENOMEM;
kfree(uevent);
goto out;
}
diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c
index d737c738d876..f5e9aeec6f6e 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_hal.c
+++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c
@@ -36,6 +36,7 @@
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/pci.h>
+#include <linux/dma-mapping.h>
#include "cxio_resource.h"
#include "cxio_hal.h"
@@ -497,9 +498,9 @@ static int cxio_hal_init_ctrl_qp(struct cxio_rdev *rdev_p)
u64 sge_cmd, ctx0, ctx1;
u64 base_addr;
struct t3_modify_qp_wr *wqe;
- struct sk_buff *skb = alloc_skb(sizeof(*wqe), GFP_KERNEL);
-
+ struct sk_buff *skb;
+ skb = alloc_skb(sizeof(*wqe), GFP_KERNEL);
if (!skb) {
PDBG("%s alloc_skb failed\n", __FUNCTION__);
return -ENOMEM;
@@ -507,7 +508,7 @@ static int cxio_hal_init_ctrl_qp(struct cxio_rdev *rdev_p)
err = cxio_hal_init_ctrl_cq(rdev_p);
if (err) {
PDBG("%s err %d initializing ctrl_cq\n", __FUNCTION__, err);
- return err;
+ goto err;
}
rdev_p->ctrl_qp.workq = dma_alloc_coherent(
&(rdev_p->rnic_info.pdev->dev),
@@ -517,7 +518,8 @@ static int cxio_hal_init_ctrl_qp(struct cxio_rdev *rdev_p)
GFP_KERNEL);
if (!rdev_p->ctrl_qp.workq) {
PDBG("%s dma_alloc_coherent failed\n", __FUNCTION__);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto err;
}
pci_unmap_addr_set(&rdev_p->ctrl_qp, mapping,
rdev_p->ctrl_qp.dma_addr);
@@ -555,6 +557,9 @@ static int cxio_hal_init_ctrl_qp(struct cxio_rdev *rdev_p)
rdev_p->ctrl_qp.workq, 1 << T3_CTRL_QP_SIZE_LOG2);
skb->priority = CPL_PRIORITY_CONTROL;
return (cxgb3_ofld_send(rdev_p->t3cdev_p, skb));
+err:
+ kfree_skb(skb);
+ return err;
}
static int cxio_hal_destroy_ctrl_qp(struct cxio_rdev *rdev_p)
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index b21fde8b659d..d0ed1d35ca3e 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -305,8 +305,7 @@ static int status2errno(int status)
*/
static struct sk_buff *get_skb(struct sk_buff *skb, int len, gfp_t gfp)
{
- if (skb) {
- BUG_ON(skb_cloned(skb));
+ if (skb && !skb_is_nonlinear(skb) && !skb_cloned(skb)) {
skb_trim(skb, 0);
skb_get(skb);
} else {
@@ -1415,6 +1414,7 @@ static int peer_close(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
wake_up(&ep->com.waitq);
break;
case FPDU_MODE:
+ start_ep_timer(ep);
__state_set(&ep->com, CLOSING);
attrs.next_state = IWCH_QP_STATE_CLOSING;
iwch_modify_qp(ep->com.qp->rhp, ep->com.qp,
@@ -1425,7 +1425,6 @@ static int peer_close(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
disconnect = 0;
break;
case CLOSING:
- start_ep_timer(ep);
__state_set(&ep->com, MORIBUND);
disconnect = 0;
break;
@@ -1487,8 +1486,10 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
case CONNECTING:
break;
case MPA_REQ_WAIT:
+ stop_ep_timer(ep);
break;
case MPA_REQ_SENT:
+ stop_ep_timer(ep);
connect_reply_upcall(ep, -ECONNRESET);
break;
case MPA_REP_SENT:
@@ -1507,9 +1508,10 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
get_ep(&ep->com);
break;
case MORIBUND:
+ case CLOSING:
stop_ep_timer(ep);
+ /*FALLTHROUGH*/
case FPDU_MODE:
- case CLOSING:
if (ep->com.cm_id && ep->com.qp) {
attrs.next_state = IWCH_QP_STATE_ERROR;
ret = iwch_modify_qp(ep->com.qp->rhp,
@@ -1570,7 +1572,6 @@ static int close_con_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
spin_lock_irqsave(&ep->com.lock, flags);
switch (ep->com.state) {
case CLOSING:
- start_ep_timer(ep);
__state_set(&ep->com, MORIBUND);
break;
case MORIBUND:
@@ -1586,6 +1587,8 @@ static int close_con_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
__state_set(&ep->com, DEAD);
release = 1;
break;
+ case ABORTING:
+ break;
case DEAD:
default:
BUG_ON(1);
@@ -1659,6 +1662,7 @@ static void ep_timeout(unsigned long arg)
break;
case MPA_REQ_WAIT:
break;
+ case CLOSING:
case MORIBUND:
if (ep->com.cm_id && ep->com.qp) {
attrs.next_state = IWCH_QP_STATE_ERROR;
@@ -1687,12 +1691,11 @@ int iwch_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
return -ECONNRESET;
}
BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD);
- state_set(&ep->com, CLOSING);
if (mpa_rev == 0)
abort_connection(ep, NULL, GFP_KERNEL);
else {
err = send_mpa_reject(ep, pdata, pdata_len);
- err = send_halfclose(ep, GFP_KERNEL);
+ err = iwch_ep_disconnect(ep, 0, GFP_KERNEL);
}
return 0;
}
@@ -1957,11 +1960,11 @@ int iwch_ep_disconnect(struct iwch_ep *ep, int abrupt, gfp_t gfp)
case MPA_REQ_RCVD:
case MPA_REP_SENT:
case FPDU_MODE:
+ start_ep_timer(ep);
ep->com.state = CLOSING;
close = 1;
break;
case CLOSING:
- start_ep_timer(ep);
ep->com.state = MORIBUND;
close = 1;
break;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_ev.c b/drivers/infiniband/hw/cxgb3/iwch_ev.c
index 54362afbf72f..b40676662a8a 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_ev.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_ev.c
@@ -47,12 +47,6 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp,
struct iwch_qp_attributes attrs;
struct iwch_qp *qhp;
- printk(KERN_ERR "%s - AE qpid 0x%x opcode %d status 0x%x "
- "type %d wrid.hi 0x%x wrid.lo 0x%x \n", __FUNCTION__,
- CQE_QPID(rsp_msg->cqe), CQE_OPCODE(rsp_msg->cqe),
- CQE_STATUS(rsp_msg->cqe), CQE_TYPE(rsp_msg->cqe),
- CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe));
-
spin_lock(&rnicp->lock);
qhp = get_qhp(rnicp, CQE_QPID(rsp_msg->cqe));
@@ -73,6 +67,12 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp,
return;
}
+ printk(KERN_ERR "%s - AE qpid 0x%x opcode %d status 0x%x "
+ "type %d wrid.hi 0x%x wrid.lo 0x%x \n", __FUNCTION__,
+ CQE_QPID(rsp_msg->cqe), CQE_OPCODE(rsp_msg->cqe),
+ CQE_STATUS(rsp_msg->cqe), CQE_TYPE(rsp_msg->cqe),
+ CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe));
+
atomic_inc(&qhp->refcnt);
spin_unlock(&rnicp->lock);
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index 9947a144a929..24e0df04f7db 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -331,6 +331,7 @@ static int iwch_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
int ret = 0;
struct iwch_mm_entry *mm;
struct iwch_ucontext *ucontext;
+ u64 addr;
PDBG("%s pgoff 0x%lx key 0x%x len %d\n", __FUNCTION__, vma->vm_pgoff,
key, len);
@@ -345,10 +346,11 @@ static int iwch_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
mm = remove_mmap(ucontext, key, len);
if (!mm)
return -EINVAL;
+ addr = mm->addr;
kfree(mm);
- if ((mm->addr >= rdev_p->rnic_info.udbell_physbase) &&
- (mm->addr < (rdev_p->rnic_info.udbell_physbase +
+ if ((addr >= rdev_p->rnic_info.udbell_physbase) &&
+ (addr < (rdev_p->rnic_info.udbell_physbase +
rdev_p->rnic_info.udbell_len))) {
/*
@@ -362,7 +364,7 @@ static int iwch_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND;
vma->vm_flags &= ~VM_MAYREAD;
ret = io_remap_pfn_range(vma, vma->vm_start,
- mm->addr >> PAGE_SHIFT,
+ addr >> PAGE_SHIFT,
len, vma->vm_page_prot);
} else {
@@ -370,7 +372,7 @@ static int iwch_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
* Map WQ or CQ contig dma memory...
*/
ret = remap_pfn_range(vma, vma->vm_start,
- mm->addr >> PAGE_SHIFT,
+ addr >> PAGE_SHIFT,
len, vma->vm_page_prot);
}
@@ -463,9 +465,6 @@ static struct ib_mr *iwch_register_phys_mem(struct ib_pd *pd,
php = to_iwch_pd(pd);
rhp = php->rhp;
- acc = iwch_convert_access(acc);
-
-
mhp = kzalloc(sizeof(*mhp), GFP_KERNEL);
if (!mhp)
return ERR_PTR(-ENOMEM);
@@ -491,12 +490,7 @@ static struct ib_mr *iwch_register_phys_mem(struct ib_pd *pd,
mhp->attr.pdid = php->pdid;
mhp->attr.zbva = 0;
- /* NOTE: TPT perms are backwards from BIND WR perms! */
- mhp->attr.perms = (acc & 0x1) << 3;
- mhp->attr.perms |= (acc & 0x2) << 1;
- mhp->attr.perms |= (acc & 0x4) >> 1;
- mhp->attr.perms |= (acc & 0x8) >> 3;
-
+ mhp->attr.perms = iwch_ib_to_tpt_access(acc);
mhp->attr.va_fbo = *iova_start;
mhp->attr.page_size = shift - 12;
@@ -525,7 +519,6 @@ static int iwch_reregister_phys_mem(struct ib_mr *mr,
struct iwch_mr mh, *mhp;
struct iwch_pd *php;
struct iwch_dev *rhp;
- int new_acc;
__be64 *page_list = NULL;
int shift = 0;
u64 total_size;
@@ -546,19 +539,20 @@ static int iwch_reregister_phys_mem(struct ib_mr *mr,
if (rhp != php->rhp)
return -EINVAL;
- new_acc = mhp->attr.perms;
-
memcpy(&mh, mhp, sizeof *mhp);
if (mr_rereg_mask & IB_MR_REREG_PD)
php = to_iwch_pd(pd);
if (mr_rereg_mask & IB_MR_REREG_ACCESS)
- mh.attr.perms = iwch_convert_access(acc);
- if (mr_rereg_mask & IB_MR_REREG_TRANS)
+ mh.attr.perms = iwch_ib_to_tpt_access(acc);
+ if (mr_rereg_mask & IB_MR_REREG_TRANS) {
ret = build_phys_page_list(buffer_list, num_phys_buf,
iova_start,
&total_size, &npages,
&shift, &page_list);
+ if (ret)
+ return ret;
+ }
ret = iwch_reregister_mem(rhp, php, &mh, shift, page_list, npages);
kfree(page_list);
@@ -568,7 +562,7 @@ static int iwch_reregister_phys_mem(struct ib_mr *mr,
if (mr_rereg_mask & IB_MR_REREG_PD)
mhp->attr.pdid = php->pdid;
if (mr_rereg_mask & IB_MR_REREG_ACCESS)
- mhp->attr.perms = acc;
+ mhp->attr.perms = iwch_ib_to_tpt_access(acc);
if (mr_rereg_mask & IB_MR_REREG_TRANS) {
mhp->attr.zbva = 0;
mhp->attr.va_fbo = *iova_start;
@@ -613,8 +607,6 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, struct ib_umem *region,
goto err;
}
- acc = iwch_convert_access(acc);
-
i = n = 0;
list_for_each_entry(chunk, &region->chunk_list, list)
@@ -630,10 +622,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, struct ib_umem *region,
mhp->rhp = rhp;
mhp->attr.pdid = php->pdid;
mhp->attr.zbva = 0;
- mhp->attr.perms = (acc & 0x1) << 3;
- mhp->attr.perms |= (acc & 0x2) << 1;
- mhp->attr.perms |= (acc & 0x4) >> 1;
- mhp->attr.perms |= (acc & 0x8) >> 3;
+ mhp->attr.perms = iwch_ib_to_tpt_access(acc);
mhp->attr.va_fbo = region->virt_base;
mhp->attr.page_size = shift - 12;
mhp->attr.len = (u32) region->length;
@@ -736,10 +725,8 @@ static int iwch_destroy_qp(struct ib_qp *ib_qp)
qhp = to_iwch_qp(ib_qp);
rhp = qhp->rhp;
- if (qhp->attr.state == IWCH_QP_STATE_RTS) {
- attrs.next_state = IWCH_QP_STATE_ERROR;
- iwch_modify_qp(rhp, qhp, IWCH_QP_ATTR_NEXT_STATE, &attrs, 0);
- }
+ attrs.next_state = IWCH_QP_STATE_ERROR;
+ iwch_modify_qp(rhp, qhp, IWCH_QP_ATTR_NEXT_STATE, &attrs, 0);
wait_event(qhp->wait, !qhp->ep);
remove_handle(rhp, &rhp->qpidr, qhp->wq.qpid);
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.h b/drivers/infiniband/hw/cxgb3/iwch_provider.h
index de0fe1b93a0c..93bcc56756bd 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.h
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.h
@@ -286,27 +286,20 @@ static inline int iwch_convert_state(enum ib_qp_state ib_state)
}
}
-enum iwch_mem_perms {
- IWCH_MEM_ACCESS_LOCAL_READ = 1 << 0,
- IWCH_MEM_ACCESS_LOCAL_WRITE = 1 << 1,
- IWCH_MEM_ACCESS_REMOTE_READ = 1 << 2,
- IWCH_MEM_ACCESS_REMOTE_WRITE = 1 << 3,
- IWCH_MEM_ACCESS_ATOMICS = 1 << 4,
- IWCH_MEM_ACCESS_BINDING = 1 << 5,
- IWCH_MEM_ACCESS_LOCAL =
- (IWCH_MEM_ACCESS_LOCAL_READ | IWCH_MEM_ACCESS_LOCAL_WRITE),
- IWCH_MEM_ACCESS_REMOTE =
- (IWCH_MEM_ACCESS_REMOTE_WRITE | IWCH_MEM_ACCESS_REMOTE_READ)
- /* cannot go beyond 1 << 31 */
-} __attribute__ ((packed));
-
-static inline u32 iwch_convert_access(int acc)
+static inline u32 iwch_ib_to_tpt_access(int acc)
{
- return (acc & IB_ACCESS_REMOTE_WRITE ? IWCH_MEM_ACCESS_REMOTE_WRITE : 0)
- | (acc & IB_ACCESS_REMOTE_READ ? IWCH_MEM_ACCESS_REMOTE_READ : 0) |
- (acc & IB_ACCESS_LOCAL_WRITE ? IWCH_MEM_ACCESS_LOCAL_WRITE : 0) |
- (acc & IB_ACCESS_MW_BIND ? IWCH_MEM_ACCESS_BINDING : 0) |
- IWCH_MEM_ACCESS_LOCAL_READ;
+ return (acc & IB_ACCESS_REMOTE_WRITE ? TPT_REMOTE_WRITE : 0) |
+ (acc & IB_ACCESS_REMOTE_READ ? TPT_REMOTE_READ : 0) |
+ (acc & IB_ACCESS_LOCAL_WRITE ? TPT_LOCAL_WRITE : 0) |
+ TPT_LOCAL_READ;
+}
+
+static inline u32 iwch_ib_to_mwbind_access(int acc)
+{
+ return (acc & IB_ACCESS_REMOTE_WRITE ? T3_MEM_ACCESS_REM_WRITE : 0) |
+ (acc & IB_ACCESS_REMOTE_READ ? T3_MEM_ACCESS_REM_READ : 0) |
+ (acc & IB_ACCESS_LOCAL_WRITE ? T3_MEM_ACCESS_LOCAL_WRITE : 0) |
+ T3_MEM_ACCESS_LOCAL_READ;
}
enum iwch_mmid_state {
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
index 9ea00cc4a5f8..0a472c9b44db 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
@@ -439,7 +439,7 @@ int iwch_bind_mw(struct ib_qp *qp,
wqe->bind.type = T3_VA_BASED_TO;
/* TBD: check perms */
- wqe->bind.perms = iwch_convert_access(mw_bind->mw_access_flags);
+ wqe->bind.perms = iwch_ib_to_mwbind_access(mw_bind->mw_access_flags);
wqe->bind.mr_stag = cpu_to_be32(mw_bind->mr->lkey);
wqe->bind.mw_stag = cpu_to_be32(mw->rkey);
wqe->bind.mw_len = cpu_to_be32(mw_bind->length);
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index 40404c9e2817..82ded44c6cee 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -52,6 +52,8 @@ struct ehca_mw;
struct ehca_pd;
struct ehca_av;
+#include <linux/wait.h>
+
#include <rdma/ib_verbs.h>
#include <rdma/ib_user_verbs.h>
@@ -153,7 +155,9 @@ struct ehca_cq {
spinlock_t cb_lock;
struct hlist_head qp_hashtab[QP_HASHTAB_LEN];
struct list_head entry;
- u32 nr_callbacks;
+ u32 nr_callbacks; /* #events assigned to cpu by scaling code */
+ u32 nr_events; /* #events seen */
+ wait_queue_head_t wait_completion;
spinlock_t task_lock;
u32 ownpid;
/* mmap counter for resources mapped into user space */
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
index 6ebfa27e4e16..e2cdc1a16fe9 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -146,6 +146,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe,
spin_lock_init(&my_cq->spinlock);
spin_lock_init(&my_cq->cb_lock);
spin_lock_init(&my_cq->task_lock);
+ init_waitqueue_head(&my_cq->wait_completion);
my_cq->ownpid = current->tgid;
cq = &my_cq->ib_cq;
@@ -302,6 +303,16 @@ create_cq_exit1:
return cq;
}
+static int get_cq_nr_events(struct ehca_cq *my_cq)
+{
+ int ret;
+ unsigned long flags;
+ spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+ ret = my_cq->nr_events;
+ spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+ return ret;
+}
+
int ehca_destroy_cq(struct ib_cq *cq)
{
u64 h_ret;
@@ -329,10 +340,11 @@ int ehca_destroy_cq(struct ib_cq *cq)
}
spin_lock_irqsave(&ehca_cq_idr_lock, flags);
- while (my_cq->nr_callbacks) {
+ while (my_cq->nr_events) {
spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
- yield();
+ wait_event(my_cq->wait_completion, !get_cq_nr_events(my_cq));
spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+ /* recheck nr_events to assure no cqe has just arrived */
}
idr_remove(&ehca_cq_idr, my_cq->token);
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index 3ec53c687d08..f284be1c9166 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -66,7 +66,9 @@
static void queue_comp_task(struct ehca_cq *__cq);
static struct ehca_comp_pool* pool;
+#ifdef CONFIG_HOTPLUG_CPU
static struct notifier_block comp_pool_callback_nb;
+#endif
static inline void comp_event_callback(struct ehca_cq *cq)
{
@@ -404,10 +406,11 @@ static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe)
u32 token;
unsigned long flags;
struct ehca_cq *cq;
+
eqe_value = eqe->entry;
ehca_dbg(&shca->ib_device, "eqe_value=%lx", eqe_value);
if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
- ehca_dbg(&shca->ib_device, "... completion event");
+ ehca_dbg(&shca->ib_device, "Got completion event");
token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
spin_lock_irqsave(&ehca_cq_idr_lock, flags);
cq = idr_find(&ehca_cq_idr, token);
@@ -419,16 +422,20 @@ static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe)
return;
}
reset_eq_pending(cq);
- if (ehca_scaling_code) {
+ cq->nr_events++;
+ spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+ if (ehca_scaling_code)
queue_comp_task(cq);
- spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
- } else {
- spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+ else {
comp_event_callback(cq);
+ spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+ cq->nr_events--;
+ if (!cq->nr_events)
+ wake_up(&cq->wait_completion);
+ spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
}
} else {
- ehca_dbg(&shca->ib_device,
- "Got non completion event");
+ ehca_dbg(&shca->ib_device, "Got non completion event");
parse_identifier(shca, eqe_value);
}
}
@@ -478,6 +485,7 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
"token=%x", token);
continue;
}
+ eqe_cache[eqe_cnt].cq->nr_events++;
spin_unlock(&ehca_cq_idr_lock);
} else
eqe_cache[eqe_cnt].cq = NULL;
@@ -504,12 +512,18 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
/* call completion handler for cached eqes */
for (i = 0; i < eqe_cnt; i++)
if (eq->eqe_cache[i].cq) {
- if (ehca_scaling_code) {
- spin_lock(&ehca_cq_idr_lock);
+ if (ehca_scaling_code)
queue_comp_task(eq->eqe_cache[i].cq);
- spin_unlock(&ehca_cq_idr_lock);
- } else
- comp_event_callback(eq->eqe_cache[i].cq);
+ else {
+ struct ehca_cq *cq = eq->eqe_cache[i].cq;
+ comp_event_callback(cq);
+ spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+ cq->nr_events--;
+ if (!cq->nr_events)
+ wake_up(&cq->wait_completion);
+ spin_unlock_irqrestore(&ehca_cq_idr_lock,
+ flags);
+ }
} else {
ehca_dbg(&shca->ib_device, "Got non completion event");
parse_identifier(shca, eq->eqe_cache[i].eqe->entry);
@@ -523,7 +537,6 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
if (!eqe)
break;
process_eqe(shca, eqe);
- eqe_cnt++;
} while (1);
unlock_irq_spinlock:
@@ -567,8 +580,7 @@ static void __queue_comp_task(struct ehca_cq *__cq,
list_add_tail(&__cq->entry, &cct->cq_list);
cct->cq_jobs++;
wake_up(&cct->wait_queue);
- }
- else
+ } else
__cq->nr_callbacks++;
spin_unlock(&__cq->task_lock);
@@ -577,18 +589,21 @@ static void __queue_comp_task(struct ehca_cq *__cq,
static void queue_comp_task(struct ehca_cq *__cq)
{
- int cpu;
int cpu_id;
struct ehca_cpu_comp_task *cct;
+ int cq_jobs;
+ unsigned long flags;
- cpu = get_cpu();
cpu_id = find_next_online_cpu(pool);
BUG_ON(!cpu_online(cpu_id));
cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id);
BUG_ON(!cct);
- if (cct->cq_jobs > 0) {
+ spin_lock_irqsave(&cct->task_lock, flags);
+ cq_jobs = cct->cq_jobs;
+ spin_unlock_irqrestore(&cct->task_lock, flags);
+ if (cq_jobs > 0) {
cpu_id = find_next_online_cpu(pool);
cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id);
BUG_ON(!cct);
@@ -608,11 +623,17 @@ static void run_comp_task(struct ehca_cpu_comp_task* cct)
cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
spin_unlock_irqrestore(&cct->task_lock, flags);
comp_event_callback(cq);
- spin_lock_irqsave(&cct->task_lock, flags);
+ spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+ cq->nr_events--;
+ if (!cq->nr_events)
+ wake_up(&cq->wait_completion);
+ spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+
+ spin_lock_irqsave(&cct->task_lock, flags);
spin_lock(&cq->task_lock);
cq->nr_callbacks--;
- if (cq->nr_callbacks == 0) {
+ if (!cq->nr_callbacks) {
list_del_init(cct->cq_list.next);
cct->cq_jobs--;
}
@@ -714,6 +735,7 @@ static void take_over_work(struct ehca_comp_pool *pool,
}
+#ifdef CONFIG_HOTPLUG_CPU
static int comp_pool_callback(struct notifier_block *nfb,
unsigned long action,
void *hcpu)
@@ -756,6 +778,7 @@ static int comp_pool_callback(struct notifier_block *nfb,
return NOTIFY_OK;
}
+#endif
int ehca_create_comp_pool(void)
{
@@ -786,9 +809,11 @@ int ehca_create_comp_pool(void)
}
}
+#ifdef CONFIG_HOTPLUG_CPU
comp_pool_callback_nb.notifier_call = comp_pool_callback;
comp_pool_callback_nb.priority =0;
register_cpu_notifier(&comp_pool_callback_nb);
+#endif
printk(KERN_INFO "eHCA scaling code enabled\n");
@@ -802,7 +827,9 @@ void ehca_destroy_comp_pool(void)
if (!ehca_scaling_code)
return;
+#ifdef CONFIG_HOTPLUG_CPU
unregister_cpu_notifier(&comp_pool_callback_nb);
+#endif
for (i = 0; i < NR_CPUS; i++) {
if (cpu_online(i))
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index c1835121a822..059da9628bb5 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -52,7 +52,7 @@
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
-MODULE_VERSION("SVNEHCA_0021");
+MODULE_VERSION("SVNEHCA_0022");
int ehca_open_aqp1 = 0;
int ehca_debug_level = 0;
@@ -810,7 +810,7 @@ int __init ehca_module_init(void)
int ret;
printk(KERN_INFO "eHCA Infiniband Device Driver "
- "(Rel.: SVNEHCA_0021)\n");
+ "(Rel.: SVNEHCA_0022)\n");
idr_init(&ehca_qp_idr);
idr_init(&ehca_cq_idr);
spin_lock_init(&ehca_qp_idr_lock);
diff --git a/drivers/infiniband/hw/ipath/ipath_dma.c b/drivers/infiniband/hw/ipath/ipath_dma.c
index f6f949040825..f87f003e3ef8 100644
--- a/drivers/infiniband/hw/ipath/ipath_dma.c
+++ b/drivers/infiniband/hw/ipath/ipath_dma.c
@@ -167,7 +167,7 @@ static void *ipath_dma_alloc_coherent(struct ib_device *dev, size_t size,
}
static void ipath_dma_free_coherent(struct ib_device *dev, size_t size,
- void *cpu_addr, dma_addr_t dma_handle)
+ void *cpu_addr, u64 dma_handle)
{
free_pages((unsigned long) cpu_addr, get_order(size));
}
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
index 5b40a846ff95..ed55979bfd34 100644
--- a/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -451,12 +451,18 @@ bail:
return ret;
}
-static void remove_file(struct dentry *parent, char *name)
+static int remove_file(struct dentry *parent, char *name)
{
struct dentry *tmp;
+ int ret;
tmp = lookup_one_len(name, parent, strlen(name));
+ if (IS_ERR(tmp)) {
+ ret = PTR_ERR(tmp);
+ goto bail;
+ }
+
spin_lock(&dcache_lock);
spin_lock(&tmp->d_lock);
if (!(d_unhashed(tmp) && tmp->d_inode)) {
@@ -469,6 +475,14 @@ static void remove_file(struct dentry *parent, char *name)
spin_unlock(&tmp->d_lock);
spin_unlock(&dcache_lock);
}
+
+ ret = 0;
+bail:
+ /*
+ * We don't expect clients to care about the return value, but
+ * it's there if they need it.
+ */
+ return ret;
}
static int remove_device_files(struct super_block *sb,
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
index 8e4846b5c641..fdb576dcfaa8 100644
--- a/drivers/infiniband/hw/mthca/mthca_mr.c
+++ b/drivers/infiniband/hw/mthca/mthca_mr.c
@@ -881,8 +881,8 @@ int mthca_init_mr_table(struct mthca_dev *dev)
}
mpts = mtts = 1 << i;
} else {
- mpts = dev->limits.num_mtt_segs;
- mtts = dev->limits.num_mpts;
+ mtts = dev->limits.num_mtt_segs;
+ mpts = dev->limits.num_mpts;
}
if (!mthca_is_memfree(dev) &&
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index 71dc84bd4254..1c6b63aca268 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -1088,21 +1088,21 @@ static void mthca_unmap_memfree(struct mthca_dev *dev,
static int mthca_alloc_memfree(struct mthca_dev *dev,
struct mthca_qp *qp)
{
- int ret = 0;
-
if (mthca_is_memfree(dev)) {
qp->rq.db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_RQ,
qp->qpn, &qp->rq.db);
if (qp->rq.db_index < 0)
- return ret;
+ return -ENOMEM;
qp->sq.db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_SQ,
qp->qpn, &qp->sq.db);
- if (qp->sq.db_index < 0)
+ if (qp->sq.db_index < 0) {
mthca_free_db(dev, MTHCA_DB_TYPE_RQ, qp->rq.db_index);
+ return -ENOMEM;
+ }
}
- return ret;
+ return 0;
}
static void mthca_free_memfree(struct mthca_dev *dev,
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 3484e8ba24a4..2b242a4823f8 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -131,7 +131,7 @@ static struct sk_buff *ipoib_cm_alloc_rx_skb(struct net_device *dev, int id, int
skb_fill_page_desc(skb, i, page, 0, PAGE_SIZE);
mapping[i + 1] = ib_dma_map_page(priv->ca, skb_shinfo(skb)->frags[i].page,
- 0, PAGE_SIZE, DMA_TO_DEVICE);
+ 0, PAGE_SIZE, DMA_FROM_DEVICE);
if (unlikely(ib_dma_mapping_error(priv->ca, mapping[i + 1])))
goto partial_error;
}
@@ -452,7 +452,7 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_
skb->len, tx->mtu);
++priv->stats.tx_dropped;
++priv->stats.tx_errors;
- ipoib_cm_skb_too_long(dev, skb, tx->mtu - INFINIBAND_ALEN);
+ ipoib_cm_skb_too_long(dev, skb, tx->mtu - IPOIB_ENCAP_LEN);
return;
}
@@ -1095,7 +1095,7 @@ static void ipoib_cm_stale_task(struct work_struct *work)
/* List if sorted by LRU, start from tail,
* stop when we see a recently used entry */
p = list_entry(priv->cm.passive_ids.prev, typeof(*p), list);
- if (time_after_eq(jiffies, p->jiffies + IPOIB_CM_RX_TIMEOUT))
+ if (time_before_eq(jiffies, p->jiffies + IPOIB_CM_RX_TIMEOUT))
break;
list_del_init(&p->list);
spin_unlock_irqrestore(&priv->lock, flags);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index f2aa923ddbea..ba0ee5cf2ad7 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -328,9 +328,9 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
struct ipoib_tx_buf *tx_req;
u64 addr;
- if (unlikely(skb->len > priv->mcast_mtu + INFINIBAND_ALEN)) {
+ if (unlikely(skb->len > priv->mcast_mtu + IPOIB_ENCAP_LEN)) {
ipoib_warn(priv, "packet len %d (> %d) too long to send, dropping\n",
- skb->len, priv->mcast_mtu + INFINIBAND_ALEN);
+ skb->len, priv->mcast_mtu + IPOIB_ENCAP_LEN);
++priv->stats.tx_dropped;
++priv->stats.tx_errors;
ipoib_cm_skb_too_long(dev, skb, priv->mcast_mtu);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index f9dbc6f68145..f2a40ae8e7d0 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -380,7 +380,7 @@ static void path_rec_completion(int status,
struct net_device *dev = path->dev;
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_ah *ah = NULL;
- struct ipoib_neigh *neigh;
+ struct ipoib_neigh *neigh, *tn;
struct sk_buff_head skqueue;
struct sk_buff *skb;
unsigned long flags;
@@ -418,7 +418,7 @@ static void path_rec_completion(int status,
while ((skb = __skb_dequeue(&path->queue)))
__skb_queue_tail(&skqueue, skb);
- list_for_each_entry(neigh, &path->neigh_list, list) {
+ list_for_each_entry_safe(neigh, tn, &path->neigh_list, list) {
kref_get(&path->ah->ref);
neigh->ah = path->ah;
memcpy(&neigh->dgid.raw, &path->pathrec.dgid.raw,
@@ -814,7 +814,7 @@ static void ipoib_set_mcast_list(struct net_device *dev)
queue_work(ipoib_workqueue, &priv->restart_task);
}
-static void ipoib_neigh_destructor(struct neighbour *n)
+static void ipoib_neigh_cleanup(struct neighbour *n)
{
struct ipoib_neigh *neigh;
struct ipoib_dev_priv *priv = netdev_priv(n->dev);
@@ -822,7 +822,7 @@ static void ipoib_neigh_destructor(struct neighbour *n)
struct ipoib_ah *ah = NULL;
ipoib_dbg(priv,
- "neigh_destructor for %06x " IPOIB_GID_FMT "\n",
+ "neigh_cleanup for %06x " IPOIB_GID_FMT "\n",
IPOIB_QPN(n->ha),
IPOIB_GID_RAW_ARG(n->ha + 4));
@@ -874,7 +874,7 @@ void ipoib_neigh_free(struct net_device *dev, struct ipoib_neigh *neigh)
static int ipoib_neigh_setup_dev(struct net_device *dev, struct neigh_parms *parms)
{
- parms->neigh_destructor = ipoib_neigh_destructor;
+ parms->neigh_cleanup = ipoib_neigh_cleanup;
return 0;
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index bb2e3d5eee20..54fbead4de01 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -407,6 +407,10 @@ static int ipoib_mcast_join_complete(int status,
queue_delayed_work(ipoib_workqueue,
&priv->mcast_task, 0);
mutex_unlock(&mcast_mutex);
+
+ if (mcast == priv->broadcast)
+ netif_carrier_on(dev);
+
return 0;
}
@@ -594,7 +598,6 @@ void ipoib_mcast_join_task(struct work_struct *work)
ipoib_dbg_mcast(priv, "successfully joined all multicast groups\n");
clear_bit(IPOIB_MCAST_RUN, &priv->flags);
- netif_carrier_on(dev);
}
int ipoib_mcast_start_thread(struct net_device *dev)
@@ -641,6 +644,9 @@ static int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast)
struct ipoib_dev_priv *priv = netdev_priv(dev);
int ret = 0;
+ if (test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))
+ ib_sa_free_multicast(mcast->mc);
+
if (test_and_clear_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) {
ipoib_dbg_mcast(priv, "leaving MGID " IPOIB_GID_FMT "\n",
IPOIB_GID_ARG(mcast->mcmember.mgid));
@@ -652,9 +658,6 @@ static int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast)
ipoib_warn(priv, "ipoib_mcast_detach failed (result = %d)\n", ret);
}
- if (test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))
- ib_sa_free_multicast(mcast->mc);
-
return 0;
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 3cb551b88756..7f3ec205e35f 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -259,12 +259,13 @@ void ipoib_event(struct ib_event_handler *handler,
struct ipoib_dev_priv *priv =
container_of(handler, struct ipoib_dev_priv, event_handler);
- if (record->event == IB_EVENT_PORT_ERR ||
- record->event == IB_EVENT_PKEY_CHANGE ||
- record->event == IB_EVENT_PORT_ACTIVE ||
- record->event == IB_EVENT_LID_CHANGE ||
- record->event == IB_EVENT_SM_CHANGE ||
- record->event == IB_EVENT_CLIENT_REREGISTER) {
+ if ((record->event == IB_EVENT_PORT_ERR ||
+ record->event == IB_EVENT_PKEY_CHANGE ||
+ record->event == IB_EVENT_PORT_ACTIVE ||
+ record->event == IB_EVENT_LID_CHANGE ||
+ record->event == IB_EVENT_SM_CHANGE ||
+ record->event == IB_EVENT_CLIENT_REREGISTER) &&
+ record->element.port_num == priv->port) {
ipoib_dbg(priv, "Port state change event\n");
queue_work(ipoib_workqueue, &priv->flush_task);
}
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
index cae8c96a55f8..8960196ffb0f 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -245,7 +245,6 @@ struct iser_conn {
wait_queue_head_t wait; /* waitq for conn/disconn */
atomic_t post_recv_buf_count; /* posted rx count */
atomic_t post_send_buf_count; /* posted tx count */
- struct work_struct comperror_work; /* conn term sleepable ctx*/
char name[ISER_OBJECT_NAME_SIZE];
struct iser_page_vec *page_vec; /* represents SG to fmr maps*
* maps serialized as tx is*/
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
index 89e37283c836..278fcbccc2d9 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -658,6 +658,7 @@ void iser_ctask_rdma_finalize(struct iscsi_iser_cmd_task *iser_ctask)
{
int deferred;
int is_rdma_aligned = 1;
+ struct iser_regd_buf *regd;
/* if we were reading, copy back to unaligned sglist,
* anyway dma_unmap and free the copy
@@ -672,20 +673,20 @@ void iser_ctask_rdma_finalize(struct iscsi_iser_cmd_task *iser_ctask)
}
if (iser_ctask->dir[ISER_DIR_IN]) {
- deferred = iser_regd_buff_release
- (&iser_ctask->rdma_regd[ISER_DIR_IN]);
+ regd = &iser_ctask->rdma_regd[ISER_DIR_IN];
+ deferred = iser_regd_buff_release(regd);
if (deferred) {
- iser_err("References remain for BUF-IN rdma reg\n");
- BUG();
+ iser_err("%d references remain for BUF-IN rdma reg\n",
+ atomic_read(&regd->ref_count));
}
}
if (iser_ctask->dir[ISER_DIR_OUT]) {
- deferred = iser_regd_buff_release
- (&iser_ctask->rdma_regd[ISER_DIR_OUT]);
+ regd = &iser_ctask->rdma_regd[ISER_DIR_OUT];
+ deferred = iser_regd_buff_release(regd);
if (deferred) {
- iser_err("References remain for BUF-OUT rdma reg\n");
- BUG();
+ iser_err("%d references remain for BUF-OUT rdma reg\n",
+ atomic_read(&regd->ref_count));
}
}
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index 693b77002897..1fc967464a28 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -48,7 +48,6 @@
static void iser_cq_tasklet_fn(unsigned long data);
static void iser_cq_callback(struct ib_cq *cq, void *cq_context);
-static void iser_comp_error_worker(struct work_struct *work);
static void iser_cq_event_callback(struct ib_event *cause, void *context)
{
@@ -480,7 +479,6 @@ int iser_conn_init(struct iser_conn **ibconn)
init_waitqueue_head(&ib_conn->wait);
atomic_set(&ib_conn->post_recv_buf_count, 0);
atomic_set(&ib_conn->post_send_buf_count, 0);
- INIT_WORK(&ib_conn->comperror_work, iser_comp_error_worker);
INIT_LIST_HEAD(&ib_conn->conn_list);
spin_lock_init(&ib_conn->lock);
@@ -753,26 +751,6 @@ int iser_post_send(struct iser_desc *tx_desc)
return ret_val;
}
-static void iser_comp_error_worker(struct work_struct *work)
-{
- struct iser_conn *ib_conn =
- container_of(work, struct iser_conn, comperror_work);
-
- /* getting here when the state is UP means that the conn is being *
- * terminated asynchronously from the iSCSI layer's perspective. */
- if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP,
- ISER_CONN_TERMINATING))
- iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn,
- ISCSI_ERR_CONN_FAILED);
-
- /* complete the termination process if disconnect event was delivered *
- * note there are no more non completed posts to the QP */
- if (ib_conn->disc_evt_flag) {
- ib_conn->state = ISER_CONN_DOWN;
- wake_up_interruptible(&ib_conn->wait);
- }
-}
-
static void iser_handle_comp_error(struct iser_desc *desc)
{
struct iser_dto *dto = &desc->dto;
@@ -791,8 +769,22 @@ static void iser_handle_comp_error(struct iser_desc *desc)
}
if (atomic_read(&ib_conn->post_recv_buf_count) == 0 &&
- atomic_read(&ib_conn->post_send_buf_count) == 0)
- schedule_work(&ib_conn->comperror_work);
+ atomic_read(&ib_conn->post_send_buf_count) == 0) {
+ /* getting here when the state is UP means that the conn is *
+ * being terminated asynchronously from the iSCSI layer's *
+ * perspective. */
+ if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP,
+ ISER_CONN_TERMINATING))
+ iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn,
+ ISCSI_ERR_CONN_FAILED);
+
+ /* complete the termination process if disconnect event was delivered *
+ * note there are no more non completed posts to the QP */
+ if (ib_conn->disc_evt_flag) {
+ ib_conn->state = ISER_CONN_DOWN;
+ wake_up_interruptible(&ib_conn->wait);
+ }
+ }
}
static void iser_cq_tasklet_fn(unsigned long data)
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index ec195a36e8f6..db9cca3b65e0 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -553,7 +553,8 @@ static int __devinit i8042_check_aux(void)
*/
param = 0x5a;
- if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param != 0x5a) {
+ retval = i8042_command(&param, I8042_CMD_AUX_LOOP);
+ if (retval || param != 0x5a) {
/*
* External connection test - filters out AT-soldered PS/2 i8042's
@@ -567,7 +568,12 @@ static int __devinit i8042_check_aux(void)
(param && param != 0xfa && param != 0xff))
return -1;
- aux_loop_broken = 1;
+/*
+ * If AUX_LOOP completed without error but returned unexpected data
+ * mark it as broken
+ */
+ if (!retval)
+ aux_loop_broken = 1;
}
/*
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
index c7db4032ef02..e8606c48c9c3 100644
--- a/drivers/input/touchscreen/ucb1400_ts.c
+++ b/drivers/input/touchscreen/ucb1400_ts.c
@@ -553,6 +553,7 @@ static int ucb1400_ts_remove(struct device *dev)
}
static struct device_driver ucb1400_ts_driver = {
+ .name = "ucb1400_ts",
.owner = THIS_MODULE,
.bus = &ac97_bus_type,
.probe = ucb1400_ts_probe,
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 63e51dd6debe..00e31609a238 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -54,7 +54,7 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode");
#define USB_SX353_PRODUCT_ID 0x0022
/* table of devices that work with this driver */
-static struct usb_device_id gigaset_table [] = {
+static const struct usb_device_id gigaset_table [] = {
{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3070_PRODUCT_ID) },
{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3075_PRODUCT_ID) },
{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) },
@@ -2305,7 +2305,7 @@ static void gigaset_disconnect(struct usb_interface *interface)
gigaset_unassign(cs);
}
-static struct gigaset_ops gigops = {
+static const struct gigaset_ops gigops = {
gigaset_write_cmd,
gigaset_write_room,
gigaset_chars_in_buffer,
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index b460a73a7c85..6df336bdd571 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -944,8 +944,8 @@ static DEFINE_SPINLOCK(driver_lock);
struct cardstate *gigaset_get_cs_by_id(int id)
{
unsigned long flags;
- static struct cardstate *ret = NULL;
- static struct cardstate *cs;
+ struct cardstate *ret = NULL;
+ struct cardstate *cs;
struct gigaset_driver *drv;
unsigned i;
@@ -999,7 +999,7 @@ void gigaset_debugdrivers(void)
static struct cardstate *gigaset_get_cs_by_minor(unsigned minor)
{
unsigned long flags;
- static struct cardstate *ret = NULL;
+ struct cardstate *ret = NULL;
struct gigaset_driver *drv;
unsigned index;
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c
index 4661e2c722bc..cec1ef342fcc 100644
--- a/drivers/isdn/gigaset/ev-layer.c
+++ b/drivers/isdn/gigaset/ev-layer.c
@@ -409,7 +409,7 @@ static struct reply_t tab_cid[] = /* no dle mode */ //FIXME
};
#endif
-static struct resp_type_t resp_type[]=
+static const struct resp_type_t resp_type[] =
{
/*{"", RSP_EMPTY, RT_NOTHING},*/
{"OK", RSP_OK, RT_NOTHING},
@@ -511,7 +511,7 @@ void gigaset_handle_modem_response(struct cardstate *cs)
unsigned char *argv[MAX_REC_PARAMS + 1];
int params;
int i, j;
- struct resp_type_t *rt;
+ const struct resp_type_t *rt;
int curarg;
unsigned long flags;
unsigned next, tail, head;
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c
index 8c0eb522dab1..e0505f238807 100644
--- a/drivers/isdn/gigaset/isocdata.c
+++ b/drivers/isdn/gigaset/isocdata.c
@@ -274,7 +274,7 @@ static inline void dump_bytes(enum debuglevel level, const char *tag,
* bit 12..10 = number of trailing '1' bits in result
* bit 14..13 = number of bits added by stuffing
*/
-static u16 stufftab[5 * 256] = {
+static const u16 stufftab[5 * 256] = {
// previous 1s = 0:
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x201f,
@@ -629,7 +629,7 @@ static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits)
* (replacing 8 by 7 to make it fit; the algorithm won't care)
* bit 7 set if there are 5 or more "interior" consecutive '1' bits
*/
-static unsigned char bitcounts[256] = {
+static const unsigned char bitcounts[256] = {
0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04,
0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05,
0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04,
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c
index c8b7db65e48f..ea44302e6e7e 100644
--- a/drivers/isdn/gigaset/ser-gigaset.c
+++ b/drivers/isdn/gigaset/ser-gigaset.c
@@ -459,7 +459,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
return -EINVAL;
}
-static struct gigaset_ops ops = {
+static const struct gigaset_ops ops = {
gigaset_write_cmd,
gigaset_write_room,
gigaset_chars_in_buffer,
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c
index 04f2ad7ba8b0..2baef349c12d 100644
--- a/drivers/isdn/gigaset/usb-gigaset.c
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -50,7 +50,7 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode");
#define USB_M105_PRODUCT_ID 0x0009
/* table of devices that work with this driver */
-static struct usb_device_id gigaset_table [] = {
+static const struct usb_device_id gigaset_table [] = {
{ USB_DEVICE(USB_M105_VENDOR_ID, USB_M105_PRODUCT_ID) },
{ } /* Terminating entry */
};
@@ -860,7 +860,7 @@ static void gigaset_disconnect(struct usb_interface *interface)
gigaset_unassign(cs);
}
-static struct gigaset_ops ops = {
+static const struct gigaset_ops ops = {
gigaset_write_cmd,
gigaset_write_room,
gigaset_chars_in_buffer,
diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c
index 9df9e3548cf1..c547a6665052 100644
--- a/drivers/isdn/hisax/isar.c
+++ b/drivers/isdn/hisax/isar.c
@@ -440,7 +440,7 @@ isar_bh(struct work_struct *work)
{
struct BCState *bcs = container_of(work, struct BCState, tqueue);
- BChannel_bh(bcs);
+ BChannel_bh(work);
if (test_and_clear_bit(B_LL_NOCARRIER, &bcs->event))
ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_NOCARR);
if (test_and_clear_bit(B_LL_CONNECT, &bcs->event))
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index a163bca38973..dc7a8c78cbf9 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -2464,7 +2464,7 @@ int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module)
r = kvm_arch_ops->hardware_setup();
if (r < 0)
- return r;
+ goto out;
on_each_cpu(kvm_arch_ops->hardware_enable, NULL, 0, 1);
r = register_cpu_notifier(&kvm_cpu_notifier);
@@ -2500,6 +2500,8 @@ out_free_2:
out_free_1:
on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1);
kvm_arch_ops->hardware_unsetup();
+out:
+ kvm_arch_ops = NULL;
return r;
}
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index a1a93368f314..e85b4c7c36f7 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -131,7 +131,7 @@ static int dbg = 1;
(((address) >> PT32_LEVEL_SHIFT(level)) & ((1 << PT32_LEVEL_BITS) - 1))
-#define PT64_BASE_ADDR_MASK (((1ULL << 52) - 1) & PAGE_MASK)
+#define PT64_BASE_ADDR_MASK (((1ULL << 52) - 1) & ~(u64)(PAGE_SIZE-1))
#define PT64_DIR_BASE_ADDR_MASK \
(PT64_BASE_ADDR_MASK & ~((1ULL << (PAGE_SHIFT + PT64_LEVEL_BITS)) - 1))
@@ -406,8 +406,8 @@ static void rmap_write_protect(struct kvm_vcpu *vcpu, u64 gfn)
spte = desc->shadow_ptes[0];
}
BUG_ON(!spte);
- BUG_ON((*spte & PT64_BASE_ADDR_MASK) !=
- page_to_pfn(page) << PAGE_SHIFT);
+ BUG_ON((*spte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT
+ != page_to_pfn(page));
BUG_ON(!(*spte & PT_PRESENT_MASK));
BUG_ON(!(*spte & PT_WRITABLE_MASK));
rmap_printk("rmap_write_protect: spte %p %llx\n", spte, *spte);
@@ -1093,22 +1093,40 @@ out:
return r;
}
+static void mmu_pre_write_zap_pte(struct kvm_vcpu *vcpu,
+ struct kvm_mmu_page *page,
+ u64 *spte)
+{
+ u64 pte;
+ struct kvm_mmu_page *child;
+
+ pte = *spte;
+ if (is_present_pte(pte)) {
+ if (page->role.level == PT_PAGE_TABLE_LEVEL)
+ rmap_remove(vcpu, spte);
+ else {
+ child = page_header(pte & PT64_BASE_ADDR_MASK);
+ mmu_page_remove_parent_pte(vcpu, child, spte);
+ }
+ }
+ *spte = 0;
+}
+
void kvm_mmu_pre_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes)
{
gfn_t gfn = gpa >> PAGE_SHIFT;
struct kvm_mmu_page *page;
- struct kvm_mmu_page *child;
struct hlist_node *node, *n;
struct hlist_head *bucket;
unsigned index;
u64 *spte;
- u64 pte;
unsigned offset = offset_in_page(gpa);
unsigned pte_size;
unsigned page_offset;
unsigned misaligned;
int level;
int flooded = 0;
+ int npte;
pgprintk("%s: gpa %llx bytes %d\n", __FUNCTION__, gpa, bytes);
if (gfn == vcpu->last_pt_write_gfn) {
@@ -1144,22 +1162,26 @@ void kvm_mmu_pre_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes)
}
page_offset = offset;
level = page->role.level;
+ npte = 1;
if (page->role.glevels == PT32_ROOT_LEVEL) {
- page_offset <<= 1; /* 32->64 */
+ page_offset <<= 1; /* 32->64 */
+ /*
+ * A 32-bit pde maps 4MB while the shadow pdes map
+ * only 2MB. So we need to double the offset again
+ * and zap two pdes instead of one.
+ */
+ if (level == PT32_ROOT_LEVEL) {
+ page_offset <<= 1;
+ npte = 2;
+ }
page_offset &= ~PAGE_MASK;
}
spte = __va(page->page_hpa);
spte += page_offset / sizeof(*spte);
- pte = *spte;
- if (is_present_pte(pte)) {
- if (level == PT_PAGE_TABLE_LEVEL)
- rmap_remove(vcpu, spte);
- else {
- child = page_header(pte & PT64_BASE_ADDR_MASK);
- mmu_page_remove_parent_pte(vcpu, child, spte);
- }
+ while (npte--) {
+ mmu_pre_write_zap_pte(vcpu, page, spte);
+ ++spte;
}
- *spte = 0;
}
}
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index c07178e61122..fbbf9d6b299f 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -371,10 +371,10 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
data = vmcs_read32(GUEST_SYSENTER_CS);
break;
case MSR_IA32_SYSENTER_EIP:
- data = vmcs_read32(GUEST_SYSENTER_EIP);
+ data = vmcs_readl(GUEST_SYSENTER_EIP);
break;
case MSR_IA32_SYSENTER_ESP:
- data = vmcs_read32(GUEST_SYSENTER_ESP);
+ data = vmcs_readl(GUEST_SYSENTER_ESP);
break;
default:
msr = find_msr_entry(vcpu, msr_index);
@@ -412,10 +412,10 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
vmcs_write32(GUEST_SYSENTER_CS, data);
break;
case MSR_IA32_SYSENTER_EIP:
- vmcs_write32(GUEST_SYSENTER_EIP, data);
+ vmcs_writel(GUEST_SYSENTER_EIP, data);
break;
case MSR_IA32_SYSENTER_ESP:
- vmcs_write32(GUEST_SYSENTER_ESP, data);
+ vmcs_writel(GUEST_SYSENTER_ESP, data);
break;
case MSR_IA32_TIME_STAMP_COUNTER:
guest_write_tsc(data);
@@ -618,7 +618,7 @@ static void fix_pmode_dataseg(int seg, struct kvm_save_segment *save)
{
struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
- if (vmcs_readl(sf->base) == save->base) {
+ if (vmcs_readl(sf->base) == save->base && (save->base & AR_S_MASK)) {
vmcs_write16(sf->selector, save->selector);
vmcs_writel(sf->base, save->base);
vmcs_write32(sf->limit, save->limit);
@@ -1888,6 +1888,27 @@ again:
[cr2]"i"(offsetof(struct kvm_vcpu, cr2))
: "cc", "memory" );
+ /*
+ * Reload segment selectors ASAP. (it's needed for a functional
+ * kernel: x86 relies on having __KERNEL_PDA in %fs and x86_64
+ * relies on having 0 in %gs for the CPU PDA to work.)
+ */
+ if (fs_gs_ldt_reload_needed) {
+ load_ldt(ldt_sel);
+ load_fs(fs_sel);
+ /*
+ * If we have to reload gs, we must take care to
+ * preserve our gs base.
+ */
+ local_irq_disable();
+ load_gs(gs_sel);
+#ifdef CONFIG_X86_64
+ wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE));
+#endif
+ local_irq_enable();
+
+ reload_tss();
+ }
++kvm_stat.exits;
save_msrs(vcpu->guest_msrs, NR_BAD_MSRS);
@@ -1905,22 +1926,6 @@ again:
kvm_run->exit_reason = vmcs_read32(VM_INSTRUCTION_ERROR);
r = 0;
} else {
- if (fs_gs_ldt_reload_needed) {
- load_ldt(ldt_sel);
- load_fs(fs_sel);
- /*
- * If we have to reload gs, we must take care to
- * preserve our gs base.
- */
- local_irq_disable();
- load_gs(gs_sel);
-#ifdef CONFIG_X86_64
- wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE));
-#endif
- local_irq_enable();
-
- reload_tss();
- }
/*
* Profile KVM exit RIPs:
*/
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index c625ddb8833d..d5ecd2d53046 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -188,7 +188,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
for (i=0; i < cnt-1 ; i++) {
sector_t sz = 0;
int j;
- for (j=i; i<cnt-1 && sz < min_spacing ; j++)
+ for (j = i; j < cnt - 1 && sz < min_spacing; j++)
sz += conf->disks[j].size;
if (sz >= min_spacing && sz < conf->hash_spacing)
conf->hash_spacing = sz;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 6c06e825cff5..509171ca7fa8 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1318,6 +1318,7 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
char b[BDEVNAME_SIZE];
struct kobject *ko;
char *s;
+ int err;
if (rdev->mddev) {
MD_BUG();
@@ -1352,20 +1353,35 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
while ( (s=strchr(rdev->kobj.k_name, '/')) != NULL)
*s = '!';
- list_add(&rdev->same_set, &mddev->disks);
rdev->mddev = mddev;
printk(KERN_INFO "md: bind<%s>\n", b);
rdev->kobj.parent = &mddev->kobj;
- kobject_add(&rdev->kobj);
+ if ((err = kobject_add(&rdev->kobj)))
+ goto fail;
if (rdev->bdev->bd_part)
ko = &rdev->bdev->bd_part->kobj;
else
ko = &rdev->bdev->bd_disk->kobj;
- sysfs_create_link(&rdev->kobj, ko, "block");
+ if ((err = sysfs_create_link(&rdev->kobj, ko, "block"))) {
+ kobject_del(&rdev->kobj);
+ goto fail;
+ }
+ list_add(&rdev->same_set, &mddev->disks);
bd_claim_by_disk(rdev->bdev, rdev, mddev->gendisk);
return 0;
+
+ fail:
+ printk(KERN_WARNING "md: failed to register dev-%s for %s\n",
+ b, mdname(mddev));
+ return err;
+}
+
+static void delayed_delete(struct work_struct *ws)
+{
+ mdk_rdev_t *rdev = container_of(ws, mdk_rdev_t, del_work);
+ kobject_del(&rdev->kobj);
}
static void unbind_rdev_from_array(mdk_rdev_t * rdev)
@@ -1380,7 +1396,12 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev)
printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b));
rdev->mddev = NULL;
sysfs_remove_link(&rdev->kobj, "block");
- kobject_del(&rdev->kobj);
+
+ /* We need to delay this, otherwise we can deadlock when
+ * writing to 'remove' to "dev/state"
+ */
+ INIT_WORK(&rdev->del_work, delayed_delete);
+ schedule_work(&rdev->del_work);
}
/*
@@ -2966,7 +2987,9 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data)
mddev->kobj.k_name = NULL;
snprintf(mddev->kobj.name, KOBJ_NAME_LEN, "%s", "md");
mddev->kobj.ktype = &md_ktype;
- kobject_register(&mddev->kobj);
+ if (kobject_register(&mddev->kobj))
+ printk(KERN_WARNING "md: cannot register %s/md - name in use\n",
+ disk->disk_name);
return NULL;
}
@@ -3144,9 +3167,12 @@ static int do_md_run(mddev_t * mddev)
bitmap_destroy(mddev);
return err;
}
- if (mddev->pers->sync_request)
- sysfs_create_group(&mddev->kobj, &md_redundancy_group);
- else if (mddev->ro == 2) /* auto-readonly not meaningful */
+ if (mddev->pers->sync_request) {
+ if (sysfs_create_group(&mddev->kobj, &md_redundancy_group))
+ printk(KERN_WARNING
+ "md: cannot register extra attributes for %s\n",
+ mdname(mddev));
+ } else if (mddev->ro == 2) /* auto-readonly not meaningful */
mddev->ro = 0;
atomic_set(&mddev->writes_pending,0);
@@ -3160,7 +3186,9 @@ static int do_md_run(mddev_t * mddev)
if (rdev->raid_disk >= 0) {
char nm[20];
sprintf(nm, "rd%d", rdev->raid_disk);
- sysfs_create_link(&mddev->kobj, &rdev->kobj, nm);
+ if (sysfs_create_link(&mddev->kobj, &rdev->kobj, nm))
+ printk("md: cannot register %s for %s\n",
+ nm, mdname(mddev));
}
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
@@ -3325,6 +3353,7 @@ static int do_md_stop(mddev_t * mddev, int mode)
mddev->queue->merge_bvec_fn = NULL;
mddev->queue->unplug_fn = NULL;
mddev->queue->issue_flush_fn = NULL;
+ mddev->queue->backing_dev_info.congested_fn = NULL;
if (mddev->pers->sync_request)
sysfs_remove_group(&mddev->kobj, &md_redundancy_group);
@@ -3371,6 +3400,9 @@ static int do_md_stop(mddev_t * mddev, int mode)
sysfs_remove_link(&mddev->kobj, nm);
}
+ /* make sure all delayed_delete calls have finished */
+ flush_scheduled_work();
+
export_array(mddev);
mddev->array_size = 0;
@@ -5385,8 +5417,12 @@ static int remove_and_add_spares(mddev_t *mddev)
if (mddev->pers->hot_add_disk(mddev,rdev)) {
char nm[20];
sprintf(nm, "rd%d", rdev->raid_disk);
- sysfs_create_link(&mddev->kobj,
- &rdev->kobj, nm);
+ if (sysfs_create_link(&mddev->kobj,
+ &rdev->kobj, nm))
+ printk(KERN_WARNING
+ "md: cannot register "
+ "%s for %s\n",
+ nm, mdname(mddev));
spares++;
md_new_event(mddev);
} else
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 54a1ad5eef42..8d59914f2057 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -3642,12 +3642,15 @@ static int run(mddev_t *mddev)
}
/* Ok, everything is just fine now */
- sysfs_create_group(&mddev->kobj, &raid5_attrs_group);
+ if (sysfs_create_group(&mddev->kobj, &raid5_attrs_group))
+ printk(KERN_WARNING
+ "raid5: failed to create sysfs attributes for %s\n",
+ mdname(mddev));
mddev->queue->unplug_fn = raid5_unplug_device;
mddev->queue->issue_flush_fn = raid5_issue_flush;
- mddev->queue->backing_dev_info.congested_fn = raid5_congested;
mddev->queue->backing_dev_info.congested_data = mddev;
+ mddev->queue->backing_dev_info.congested_fn = raid5_congested;
mddev->array_size = mddev->size * (conf->previous_raid_disks -
conf->max_degraded);
@@ -3678,6 +3681,7 @@ static int stop(mddev_t *mddev)
mddev->thread = NULL;
shrink_stripes(conf);
kfree(conf->stripe_hashtbl);
+ mddev->queue->backing_dev_info.congested_fn = NULL;
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
sysfs_remove_group(&mddev->kobj, &raid5_attrs_group);
kfree(conf->disks);
@@ -3950,7 +3954,12 @@ static int raid5_start_reshape(mddev_t *mddev)
added_devices++;
rdev->recovery_offset = 0;
sprintf(nm, "rd%d", rdev->raid_disk);
- sysfs_create_link(&mddev->kobj, &rdev->kobj, nm);
+ if (sysfs_create_link(&mddev->kobj,
+ &rdev->kobj, nm))
+ printk(KERN_WARNING
+ "raid5: failed to create "
+ " link %s for %s\n",
+ nm, mdname(mddev));
} else
break;
}
@@ -4104,6 +4113,10 @@ static struct mdk_personality raid4_personality =
.spare_active = raid5_spare_active,
.sync_request = sync_request,
.resize = raid5_resize,
+#ifdef CONFIG_MD_RAID5_RESHAPE
+ .check_reshape = raid5_check_reshape,
+ .start_reshape = raid5_start_reshape,
+#endif
.quiesce = raid5_quiesce,
};
diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c
index cbf7c0564889..fcb194135627 100644
--- a/drivers/media/common/ir-functions.c
+++ b/drivers/media/common/ir-functions.c
@@ -310,13 +310,15 @@ void ir_rc5_timer_end(unsigned long data)
tv.tv_usec - ir->base_time.tv_usec;
}
- /* Allow some timmer jitter (RC5 is ~24ms anyway so this is ok) */
+ /* signal we're ready to start a new code */
+ ir->active = 0;
+
+ /* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */
if (gap < 28000) {
dprintk(1, "ir-common: spurious timer_end\n");
return;
}
- ir->active = 0;
if (ir->last_bit < 20) {
/* ignore spurious codes (caused by light/other remotes) */
dprintk(1, "ir-common: short code: %x\n", ir->code);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index fc77de45ca4d..a5c0e1a3e6d1 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -180,8 +180,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
struct dvb_device *dvbdev = file->private_data;
struct dmxdev *dmxdev = dvbdev->priv;
- if (mutex_lock_interruptible(&dmxdev->mutex))
- return -ERESTARTSYS;
+ mutex_lock(&dmxdev->mutex);
if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
dmxdev->demux->disconnect_frontend(dmxdev->demux);
@@ -673,13 +672,8 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev,
struct dmxdev_filter *dmxdevfilter)
{
- if (mutex_lock_interruptible(&dmxdev->mutex))
- return -ERESTARTSYS;
-
- if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
- mutex_unlock(&dmxdev->mutex);
- return -ERESTARTSYS;
- }
+ mutex_lock(&dmxdev->mutex);
+ mutex_lock(&dmxdevfilter->mutex);
dvb_dmxdev_filter_stop(dmxdevfilter);
dvb_dmxdev_filter_reset(dmxdevfilter);
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index fcff5eab21a3..6d8d1c3df863 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -673,8 +673,7 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed *ts_feed)
struct dvb_demux *demux = feed->demux;
int ret;
- if (mutex_lock_interruptible(&demux->mutex))
- return -ERESTARTSYS;
+ mutex_lock(&demux->mutex);
if (feed->state < DMX_STATE_GO) {
mutex_unlock(&demux->mutex);
@@ -748,8 +747,7 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx,
struct dvb_demux *demux = (struct dvb_demux *)dmx;
struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
- if (mutex_lock_interruptible(&demux->mutex))
- return -ERESTARTSYS;
+ mutex_lock(&demux->mutex);
if (feed->state == DMX_STATE_FREE) {
mutex_unlock(&demux->mutex);
@@ -916,8 +914,7 @@ static int dmx_section_feed_stop_filtering(struct dmx_section_feed *feed)
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
int ret;
- if (mutex_lock_interruptible(&dvbdmx->mutex))
- return -ERESTARTSYS;
+ mutex_lock(&dvbdmx->mutex);
if (!dvbdmx->stop_feed) {
mutex_unlock(&dvbdmx->mutex);
@@ -942,8 +939,7 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
- if (mutex_lock_interruptible(&dvbdmx->mutex))
- return -ERESTARTSYS;
+ mutex_lock(&dvbdmx->mutex);
if (dvbdmxfilter->feed != dvbdmxfeed) {
mutex_unlock(&dvbdmx->mutex);
@@ -1016,8 +1012,7 @@ static int dvbdmx_release_section_feed(struct dmx_demux *demux,
struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
struct dvb_demux *dvbdmx = (struct dvb_demux *)demux;
- if (mutex_lock_interruptible(&dvbdmx->mutex))
- return -ERESTARTSYS;
+ mutex_lock(&dvbdmx->mutex);
if (dvbdmxfeed->state == DMX_STATE_FREE) {
mutex_unlock(&dvbdmx->mutex);
@@ -1126,8 +1121,7 @@ static int dvbdmx_connect_frontend(struct dmx_demux *demux,
if (demux->frontend)
return -EINVAL;
- if (mutex_lock_interruptible(&dvbdemux->mutex))
- return -ERESTARTSYS;
+ mutex_lock(&dvbdemux->mutex);
demux->frontend = frontend;
mutex_unlock(&dvbdemux->mutex);
@@ -1138,8 +1132,7 @@ static int dvbdmx_disconnect_frontend(struct dmx_demux *demux)
{
struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
- if (mutex_lock_interruptible(&dvbdemux->mutex))
- return -ERESTARTSYS;
+ mutex_lock(&dvbdemux->mutex);
demux->frontend = NULL;
mutex_unlock(&dvbdemux->mutex);
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index 490337b5ee3e..14a372a0fe8b 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -203,8 +203,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
int id;
- if (mutex_lock_interruptible(&dvbdev_register_lock))
- return -ERESTARTSYS;
+ mutex_lock(&dvbdev_register_lock);
if ((id = dvbdev_get_free_id (adap, type)) < 0){
mutex_unlock(&dvbdev_register_lock);
@@ -294,8 +293,7 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct modu
{
int num;
- if (mutex_lock_interruptible(&dvbdev_register_lock))
- return -ERESTARTSYS;
+ mutex_lock(&dvbdev_register_lock);
if ((num = dvbdev_get_free_adapter_num ()) < 0) {
mutex_unlock(&dvbdev_register_lock);
@@ -323,8 +321,7 @@ EXPORT_SYMBOL(dvb_register_adapter);
int dvb_unregister_adapter(struct dvb_adapter *adap)
{
- if (mutex_lock_interruptible(&dvbdev_register_lock))
- return -ERESTARTSYS;
+ mutex_lock(&dvbdev_register_lock);
list_del (&adap->list_head);
mutex_unlock(&dvbdev_register_lock);
return 0;
diff --git a/drivers/media/dvb/frontends/isl6421.c b/drivers/media/dvb/frontends/isl6421.c
index ef319369ec26..c967148a5945 100644
--- a/drivers/media/dvb/frontends/isl6421.c
+++ b/drivers/media/dvb/frontends/isl6421.c
@@ -122,6 +122,7 @@ struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter
/* detect if it is present or not */
if (isl6421_set_voltage(fe, SEC_VOLTAGE_OFF)) {
kfree(isl6421);
+ fe->sec_priv = NULL;
return NULL;
}
diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c
index 87c286ee6a00..b809f83d9563 100644
--- a/drivers/media/dvb/frontends/nxt200x.c
+++ b/drivers/media/dvb/frontends/nxt200x.c
@@ -562,7 +562,7 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
/* set input */
if (state->config->set_pll_input)
- state->config->set_pll_input(buf, 1);
+ state->config->set_pll_input(buf+1, 1);
break;
case VSB_8:
/* Set non-punctured clock for VSB */
@@ -571,7 +571,7 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
/* set input */
if (state->config->set_pll_input)
- state->config->set_pll_input(buf, 0);
+ state->config->set_pll_input(buf+1, 0);
break;
default:
return -EINVAL;
diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c
index 4c27a2d90a38..ccc429cbbad0 100644
--- a/drivers/media/dvb/frontends/tda10086.c
+++ b/drivers/media/dvb/frontends/tda10086.c
@@ -212,7 +212,7 @@ static int tda10086_send_master_cmd (struct dvb_frontend* fe,
for(i=0; i< cmd->msg_len; i++) {
tda10086_write_byte(state, 0x48+i, cmd->msg[i]);
}
- tda10086_write_byte(state, 0x36, 0x08 | ((cmd->msg_len + 1) << 4));
+ tda10086_write_byte(state, 0x36, 0x08 | ((cmd->msg_len - 1) << 4));
tda10086_diseqc_wait(state);
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index ffda71dfdd65..058df5c10034 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -149,6 +149,15 @@ static inline void pluto_rw(struct pluto *pluto, u32 reg, u32 mask, u32 bits)
writel(val, &pluto->io_mem[reg]);
}
+static void pluto_write_tscr(struct pluto *pluto, u32 val)
+{
+ /* set the number of packets */
+ val &= ~TSCR_ADEF;
+ val |= TS_DMA_PACKETS / 2;
+
+ pluto_writereg(pluto, REG_TSCR, val);
+}
+
static void pluto_setsda(void *data, int state)
{
struct pluto *pluto = data;
@@ -213,11 +222,11 @@ static void pluto_reset_ts(struct pluto *pluto, int reenable)
if (val & TSCR_RSTN) {
val &= ~TSCR_RSTN;
- pluto_writereg(pluto, REG_TSCR, val);
+ pluto_write_tscr(pluto, val);
}
if (reenable) {
val |= TSCR_RSTN;
- pluto_writereg(pluto, REG_TSCR, val);
+ pluto_write_tscr(pluto, val);
}
}
@@ -339,7 +348,7 @@ static irqreturn_t pluto_irq(int irq, void *dev_id)
}
/* ACK the interrupt */
- pluto_writereg(pluto, REG_TSCR, tscr | TSCR_IACK);
+ pluto_write_tscr(pluto, tscr | TSCR_IACK);
return IRQ_HANDLED;
}
@@ -348,9 +357,6 @@ static void __devinit pluto_enable_irqs(struct pluto *pluto)
{
u32 val = pluto_readreg(pluto, REG_TSCR);
- /* set the number of packets */
- val &= ~TSCR_ADEF;
- val |= TS_DMA_PACKETS / 2;
/* disable AFUL and LOCK interrupts */
val |= (TSCR_MSKA | TSCR_MSKL);
/* enable DMA and OVERFLOW interrupts */
@@ -358,7 +364,7 @@ static void __devinit pluto_enable_irqs(struct pluto *pluto)
/* clear pending interrupts */
val |= TSCR_IACK;
- pluto_writereg(pluto, REG_TSCR, val);
+ pluto_write_tscr(pluto, val);
}
static void pluto_disable_irqs(struct pluto *pluto)
@@ -370,7 +376,7 @@ static void pluto_disable_irqs(struct pluto *pluto)
/* clear pending interrupts */
val |= TSCR_IACK;
- pluto_writereg(pluto, REG_TSCR, val);
+ pluto_write_tscr(pluto, val);
}
static int __devinit pluto_hw_init(struct pluto *pluto)
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index 920b63f8cf05..af66a5d5ecd8 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -3,7 +3,7 @@
#
menu "Radio Adapters"
- depends on VIDEO_DEV!=n
+ depends on VIDEO_DEV
config RADIO_CADET
tristate "ADS Cadet AM/FM Tuner"
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
index 2fb9fe6a1ae7..ba1af3c8525e 100644
--- a/drivers/media/video/msp3400-driver.c
+++ b/drivers/media/video/msp3400-driver.c
@@ -780,18 +780,16 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
}
-static int msp_suspend(struct device * dev, pm_message_t state)
+static int msp_suspend(struct i2c_client *client, pm_message_t state)
{
- struct i2c_client *client = container_of(dev, struct i2c_client, dev);
v4l_dbg(1, msp_debug, client, "suspend\n");
msp_reset(client);
return 0;
}
-static int msp_resume(struct device * dev)
+static int msp_resume(struct i2c_client *client)
{
- struct i2c_client *client = container_of(dev, struct i2c_client, dev);
v4l_dbg(1, msp_debug, client, "resume\n");
msp_wake_thread(client);
@@ -825,7 +823,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind)
if (msp_reset(client) == -1) {
v4l_dbg(1, msp_debug, client, "msp3400 not found\n");
kfree(client);
- return -1;
+ return 0;
}
state = kmalloc(sizeof(*state), GFP_KERNEL);
@@ -859,7 +857,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind)
v4l_dbg(1, msp_debug, client, "not an msp3400 (cannot read chip version)\n");
kfree(state);
kfree(client);
- return -1;
+ return 0;
}
msp_set_audio(client);
@@ -996,11 +994,11 @@ static struct i2c_driver i2c_driver = {
.id = I2C_DRIVERID_MSP3400,
.attach_adapter = msp_probe,
.detach_client = msp_detach,
+ .suspend = msp_suspend,
+ .resume = msp_resume,
.command = msp_command,
.driver = {
.name = "msp3400",
- .suspend = msp_suspend,
- .resume = msp_resume,
},
};
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 1ff5138e4bb6..9916cf32494d 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -1248,10 +1248,10 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/
LOCK_TAKE(hdw->ctl_lock); do {
hdw->cmd_buffer[0] = FX2CMD_FWPOST1;
- ret |= pvr2_send_request(hdw,hdw->cmd_buffer,1,0,0);
+ ret |= pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
hdw->cmd_buffer[0] = FX2CMD_MEMSEL;
hdw->cmd_buffer[1] = 0;
- ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,0,0);
+ ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,NULL,0);
} while (0); LOCK_GIVE(hdw->ctl_lock);
if (ret) {
@@ -1320,7 +1320,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
LOCK_TAKE(hdw->ctl_lock); do {
hdw->cmd_buffer[0] = FX2CMD_MEMSEL;
hdw->cmd_buffer[1] = 0;
- ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,0,0);
+ ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,NULL,0);
} while (0); LOCK_GIVE(hdw->ctl_lock);
if (ret) {
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index 5313d342666e..25d3830b482a 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -808,11 +808,11 @@ static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
{
if (vp->dev_video) {
pvr2_v4l2_dev_destroy(vp->dev_video);
- vp->dev_video = 0;
+ vp->dev_video = NULL;
}
if (vp->dev_radio) {
pvr2_v4l2_dev_destroy(vp->dev_radio);
- vp->dev_radio = 0;
+ vp->dev_radio = NULL;
}
pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
@@ -1138,7 +1138,7 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
{
int mindevnum;
int unit_number;
- int *nr_ptr = 0;
+ int *nr_ptr = NULL;
dip->v4lp = vp;
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index 7735b6758921..4d5bbd859de1 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -961,7 +961,7 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
reg |= 0x10;
} else if (std == V4L2_STD_NTSC_M_JP) {
reg |= 0x40;
- } else if (std == V4L2_STD_SECAM) {
+ } else if (std & V4L2_STD_SECAM) {
reg |= 0x50;
}
saa711x_write(client, R_0E_CHROMA_CNTL_1, reg);
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index 7be73e3763de..15dbc6bf42a7 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -804,9 +804,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
}
-static int tuner_suspend(struct device *dev, pm_message_t state)
+static int tuner_suspend(struct i2c_client *c, pm_message_t state)
{
- struct i2c_client *c = container_of (dev, struct i2c_client, dev);
struct tuner *t = i2c_get_clientdata (c);
tuner_dbg ("suspend\n");
@@ -814,9 +813,8 @@ static int tuner_suspend(struct device *dev, pm_message_t state)
return 0;
}
-static int tuner_resume(struct device *dev)
+static int tuner_resume(struct i2c_client *c)
{
- struct i2c_client *c = container_of (dev, struct i2c_client, dev);
struct tuner *t = i2c_get_clientdata (c);
tuner_dbg ("resume\n");
@@ -837,10 +835,10 @@ static struct i2c_driver driver = {
.attach_adapter = tuner_probe,
.detach_client = tuner_detach,
.command = tuner_command,
+ .suspend = tuner_suspend,
+ .resume = tuner_resume,
.driver = {
.name = "tuner",
- .suspend = tuner_suspend,
- .resume = tuner_resume,
},
};
static struct i2c_client client_template = {
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 404c014db1bd..1d2d03f77894 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -815,7 +815,7 @@ mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
static int
mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
{
- MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+ MPT_SCSI_HOST *hd;
struct mptsas_target_reset_event *target_reset_list, *n;
int rc;
@@ -827,7 +827,10 @@ mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
if (reset_phase != MPT_IOC_POST_RESET)
goto out;
- if (!hd || !hd->ioc)
+ if (!ioc->sh || !ioc->sh->hostdata)
+ goto out;
+ hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+ if (!hd->ioc)
goto out;
if (list_empty(&hd->target_reset_list))
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index da9859f2caf2..b17c4b2bc9ef 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -390,13 +390,6 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req)
return BLKPREP_KILL;
}
- /* request is already processed by us, so return */
- if (blk_special_request(req)) {
- osm_debug("REQ_SPECIAL already set!\n");
- req->cmd_flags |= REQ_DONTPREP;
- return BLKPREP_OK;
- }
-
/* connect the i2o_block_request to the request */
if (!req->special) {
ireq = i2o_block_request_alloc();
@@ -408,11 +401,8 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req)
ireq->i2o_blk_dev = i2o_blk_dev;
req->special = ireq;
ireq->req = req;
- } else
- ireq = req->special;
-
+ }
/* do not come back here */
- req->cmd_type = REQ_TYPE_SPECIAL;
req->cmd_flags |= REQ_DONTPREP;
return BLKPREP_OK;
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index c707c8ebc1a2..b0b4458ae90b 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -319,7 +319,7 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
mode &= 3; /* get current power mode */
- if (unit > ARRAY_SIZE(sm->unit_power)) {
+ if (unit >= ARRAY_SIZE(sm->unit_power)) {
dev_err(dev, "%s: bad unit %d\n", __FUNCTION__, unit);
goto already;
}
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c
index 295e931c0dfb..4b232124a1ab 100644
--- a/drivers/misc/asus-laptop.c
+++ b/drivers/misc/asus-laptop.c
@@ -211,7 +211,7 @@ static struct workqueue_struct *led_workqueue;
enum led_brightness value); \
static void object##_led_update(struct work_struct *ignored); \
static int object##_led_wk; \
- DECLARE_WORK(object##_led_work, object##_led_update); \
+ static DECLARE_WORK(object##_led_work, object##_led_update); \
static struct led_classdev object##_led = { \
.name = "asus:" ledname, \
.brightness_set = object##_led_set, \
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
index 2ebe240dd537..ac708bc2f9f3 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/misc/sony-laptop.c
@@ -453,7 +453,7 @@ static int sony_acpi_resume(struct acpi_device *device)
static int sony_acpi_add(struct acpi_device *device)
{
acpi_status status;
- int result;
+ int result = 0;
acpi_handle handle;
sony_acpi_acpi_device = device;
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c
index b060d4bfba29..0de5c9e94e74 100644
--- a/drivers/mmc/imxmmc.c
+++ b/drivers/mmc/imxmmc.c
@@ -569,10 +569,12 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat)
if(host->dma_dir == DMA_FROM_DEVICE) {
imxmci_busy_wait_for_status(host, &stat,
- STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE,
+ STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE |
+ STATUS_TIME_OUT_READ,
50, "imxmci_cpu_driven_data read");
while((stat & (STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE)) &&
+ !(stat & STATUS_TIME_OUT_READ) &&
(host->data_cnt < 512)) {
udelay(20); /* required for clocks < 8MHz*/
@@ -602,6 +604,12 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat)
if(host->dma_size & 0x1ff)
stat &= ~STATUS_CRC_READ_ERR;
+ if(stat & STATUS_TIME_OUT_READ) {
+ dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data read timeout STATUS = 0x%x\n",
+ stat);
+ trans_done = -1;
+ }
+
} else {
imxmci_busy_wait_for_status(host, &stat,
STATUS_APPL_BUFF_FE,
@@ -709,6 +717,9 @@ static void imxmci_tasklet_fnc(unsigned long data)
*/
stat |= host->status_reg;
+ if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events))
+ stat &= ~STATUS_CRC_READ_ERR;
+
if(test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) {
imxmci_busy_wait_for_status(host, &stat,
STATUS_END_CMD_RESP | STATUS_ERR_MASK,
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index e3acd398fb37..1f6445840461 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -359,6 +359,8 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
+ cfi->chips[i].ref_point_counter = 0;
+ init_waitqueue_head(&(cfi->chips[i].wq));
}
map->fldrv = &cfi_amdstd_chipdrv;
diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c
index 69d49e0250a9..b344ff858b2d 100644
--- a/drivers/mtd/chips/cfi_cmdset_0020.c
+++ b/drivers/mtd/chips/cfi_cmdset_0020.c
@@ -158,6 +158,8 @@ struct mtd_info *cfi_cmdset_0020(struct map_info *map, int primary)
cfi->chips[i].word_write_time = 128;
cfi->chips[i].buffer_write_time = 128;
cfi->chips[i].erase_time = 1024;
+ cfi->chips[i].ref_point_counter = 0;
+ init_waitqueue_head(&(cfi->chips[i].wq));
}
return cfi_staa_setup(map);
diff --git a/drivers/mtd/maps/dilnetpc.c b/drivers/mtd/maps/dilnetpc.c
index b1104fe1f207..1c3b34ad7325 100644
--- a/drivers/mtd/maps/dilnetpc.c
+++ b/drivers/mtd/maps/dilnetpc.c
@@ -402,8 +402,8 @@ static int __init init_dnpc(void)
++higlvl_partition_info[i].name;
}
- printk(KERN_NOTICE "DIL/Net %s flash: 0x%lx at 0x%lx\n",
- is_dnp ? "DNPC" : "ADNP", dnpc_map.size, dnpc_map.phys);
+ printk(KERN_NOTICE "DIL/Net %s flash: 0x%lx at 0x%llx\n",
+ is_dnp ? "DNPC" : "ADNP", dnpc_map.size, (unsigned long long)dnpc_map.phys);
dnpc_map.virt = ioremap_nocache(dnpc_map.phys, dnpc_map.size);
diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c
index 0bc013fd66a3..aa64a4752781 100644
--- a/drivers/mtd/maps/esb2rom.c
+++ b/drivers/mtd/maps/esb2rom.c
@@ -30,7 +30,7 @@
#define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */
-#define BIOS_CNTL 0xDC
+#define BIOS_CNTL 0xDC
#define BIOS_LOCK_ENABLE 0x02
#define BIOS_WRITE_ENABLE 0x01
@@ -145,7 +145,7 @@ static void esb2rom_cleanup(struct esb2rom_window *window)
}
static int __devinit esb2rom_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+ const struct pci_device_id *ent)
{
static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
struct esb2rom_window *window = &esb2rom_window;
@@ -185,7 +185,7 @@ static int __devinit esb2rom_init_one(struct pci_dev *pdev,
/* Find a region continuous to the end of the ROM window */
window->phys = 0;
pci_read_config_word(pdev, FWH_DEC_EN1, &word);
- printk(KERN_DEBUG "pci_read_config_byte : %x\n", word);
+ printk(KERN_DEBUG "pci_read_config_word : %x\n", word);
if ((word & FWH_8MiB) == FWH_8MiB)
window->phys = 0xff400000;
@@ -212,6 +212,11 @@ static int __devinit esb2rom_init_one(struct pci_dev *pdev,
else if ((word & FWH_0_5MiB) == FWH_0_5MiB)
window->phys = 0xfff80000;
+ if (window->phys == 0) {
+ printk(KERN_ERR MOD_NAME ": Rom window is closed\n");
+ goto out;
+ }
+
/* reserved 0x0020 and 0x0010 */
window->phys -= 0x400000UL;
window->size = (0xffffffffUL - window->phys) + 1UL;
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index 880580c44e01..41844ea02462 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -727,6 +727,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
concat->mtd.erasesize = subdev[0]->erasesize;
concat->mtd.writesize = subdev[0]->writesize;
concat->mtd.oobsize = subdev[0]->oobsize;
+ concat->mtd.oobavail = subdev[0]->oobavail;
if (subdev[0]->writev)
concat->mtd.writev = concat_writev;
if (subdev[0]->read_oob)
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 633def3fb087..1af989023c66 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -200,6 +200,11 @@ static int part_erase (struct mtd_info *mtd, struct erase_info *instr)
return -EINVAL;
instr->addr += part->offset;
ret = part->master->erase(part->master, instr);
+ if (ret) {
+ if (instr->fail_addr != 0xffffffff)
+ instr->fail_addr -= part->offset;
+ instr->addr -= part->offset;
+ }
return ret;
}
@@ -338,6 +343,7 @@ int add_mtd_partitions(struct mtd_info *master,
slave->mtd.size = parts[i].size;
slave->mtd.writesize = master->writesize;
slave->mtd.oobsize = master->oobsize;
+ slave->mtd.oobavail = master->oobavail;
slave->mtd.subpage_sft = master->subpage_sft;
slave->mtd.name = parts[i].name;
@@ -559,4 +565,3 @@ EXPORT_SYMBOL_GPL(deregister_mtd_parser);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>");
MODULE_DESCRIPTION("Generic support for partitioning of MTD devices");
-
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 12608c13cce5..595208f965a5 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -114,7 +114,7 @@ module_param(no_autopart, int, 0);
static int show_firmware_partition = 0;
module_param(show_firmware_partition, int, 0);
-#ifdef MTD_NAND_DISKONCHIP_BBTWRITE
+#ifdef CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE
static int inftl_bbt_write = 1;
#else
static int inftl_bbt_write = 0;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index acaf97bc80d1..6af37b8cff65 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2524,6 +2524,7 @@ int nand_scan_tail(struct mtd_info *mtd)
for (i = 0; chip->ecc.layout->oobfree[i].length; i++)
chip->ecc.layout->oobavail +=
chip->ecc.layout->oobfree[i].length;
+ mtd->oobavail = chip->ecc.layout->oobavail;
/*
* Set the number of read / write steps for one page depending on ECC
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 7f1cb6e5dccb..9e14a26ca4e8 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -4,6 +4,11 @@
* Copyright (C) 2005-2007 Samsung Electronics
* Kyungmin Park <kyungmin.park@samsung.com>
*
+ * Credits:
+ * Adrian Hunter <ext-adrian.hunter@nokia.com>:
+ * auto-placement support, read-while load support, various fixes
+ * Copyright (C) Nokia Corporation, 2007
+ *
* 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.
@@ -831,7 +836,7 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int col
int readcol = column;
int readend = column + thislen;
int lastgap = 0;
- uint8_t *oob_buf = this->page_buf + mtd->writesize;
+ uint8_t *oob_buf = this->oob_buf;
for (free = this->ecclayout->oobfree; free->length; ++free) {
if (readcol >= lastgap)
@@ -849,7 +854,8 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int col
int n = ed - st;
memcpy(buf, oob_buf + st, n);
buf += n;
- }
+ } else
+ break;
}
return 0;
}
@@ -947,9 +953,9 @@ static int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
/**
* onenand_read_oob - [MTD Interface] NAND write data and/or out-of-band
- * @mtd: MTD device structure
- * @from: offset to read from
- * @ops: oob operation description structure
+ * @param mtd: MTD device structure
+ * @param from: offset to read from
+ * @param ops: oob operation description structure
*/
static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
struct mtd_oob_ops *ops)
@@ -1017,7 +1023,7 @@ static int onenand_bbt_wait(struct mtd_info *mtd, int state)
* onenand_bbt_read_oob - [MTD Interface] OneNAND read out-of-band for bbt scan
* @param mtd MTD device structure
* @param from offset to read from
- * @param @ops oob operation description structure
+ * @param ops oob operation description structure
*
* OneNAND read out-of-band data from the spare area for bbt scan
*/
@@ -1093,7 +1099,7 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to)
{
struct onenand_chip *this = mtd->priv;
- char *readp = this->page_buf + mtd->writesize;
+ char oobbuf[64];
int status, i;
this->command(mtd, ONENAND_CMD_READOOB, to, mtd->oobsize);
@@ -1102,9 +1108,9 @@ static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to
if (status)
return status;
- this->read_bufferram(mtd, ONENAND_SPARERAM, readp, 0, mtd->oobsize);
- for(i = 0; i < mtd->oobsize; i++)
- if (buf[i] != 0xFF && buf[i] != readp[i])
+ this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize);
+ for (i = 0; i < mtd->oobsize; i++)
+ if (buf[i] != 0xFF && buf[i] != oobbuf[i])
return -EBADMSG;
return 0;
@@ -1290,7 +1296,8 @@ static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf,
int n = ed - st;
memcpy(oob_buf + st, buf, n);
buf += n;
- }
+ } else
+ break;
}
return 0;
}
@@ -1312,6 +1319,7 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
struct onenand_chip *this = mtd->priv;
int column, ret = 0, oobsize;
int written = 0;
+ u_char *oobbuf;
DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
@@ -1331,7 +1339,7 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
}
/* For compatibility with NAND: Do not allow write past end of page */
- if (column + len > oobsize) {
+ if (unlikely(column + len > oobsize)) {
printk(KERN_ERR "onenand_write_oob: "
"Attempt to write past end of page\n");
return -EINVAL;
@@ -1348,6 +1356,8 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
/* Grab the lock and see if the device is available */
onenand_get_device(mtd, FL_WRITING);
+ oobbuf = this->oob_buf;
+
/* Loop until all data write */
while (written < len) {
int thislen = min_t(int, oobsize, len - written);
@@ -1358,12 +1368,12 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
/* We send data to spare ram with oobsize
* to prevent byte access */
- memset(this->page_buf, 0xff, mtd->oobsize);
+ memset(oobbuf, 0xff, mtd->oobsize);
if (mode == MTD_OOB_AUTO)
- onenand_fill_auto_oob(mtd, this->page_buf, buf, column, thislen);
+ onenand_fill_auto_oob(mtd, oobbuf, buf, column, thislen);
else
- memcpy(this->page_buf + column, buf, thislen);
- this->write_bufferram(mtd, ONENAND_SPARERAM, this->page_buf, 0, mtd->oobsize);
+ memcpy(oobbuf + column, buf, thislen);
+ this->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize);
this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize);
@@ -1375,7 +1385,7 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
break;
}
- ret = onenand_verify_oob(mtd, this->page_buf, to);
+ ret = onenand_verify_oob(mtd, oobbuf, to);
if (ret) {
printk(KERN_ERR "onenand_write_oob: verify failed %d\n", ret);
break;
@@ -1400,9 +1410,9 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
/**
* onenand_write_oob - [MTD Interface] NAND write data and/or out-of-band
- * @mtd: MTD device structure
- * @from: offset to read from
- * @ops: oob operation description structure
+ * @param mtd: MTD device structure
+ * @param to: offset to write
+ * @param ops: oob operation description structure
*/
static int onenand_write_oob(struct mtd_info *mtd, loff_t to,
struct mtd_oob_ops *ops)
@@ -1616,6 +1626,7 @@ static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
* @param mtd MTD device structure
* @param ofs offset relative to mtd start
* @param len number of bytes to lock or unlock
+ * @param cmd lock or unlock command
*
* Lock or unlock one or more blocks
*/
@@ -2117,10 +2128,11 @@ static void onenand_check_features(struct mtd_info *mtd)
}
/**
- * onenand_print_device_info - Print device ID
+ * onenand_print_device_info - Print device & version ID
* @param device device ID
+ * @param version version ID
*
- * Print device ID
+ * Print device & version ID
*/
static void onenand_print_device_info(int device, int version)
{
@@ -2320,15 +2332,25 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
/* Allocate buffers, if necessary */
if (!this->page_buf) {
- size_t len;
- len = mtd->writesize + mtd->oobsize;
- this->page_buf = kmalloc(len, GFP_KERNEL);
+ this->page_buf = kzalloc(mtd->writesize, GFP_KERNEL);
if (!this->page_buf) {
printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n");
return -ENOMEM;
}
this->options |= ONENAND_PAGEBUF_ALLOC;
}
+ if (!this->oob_buf) {
+ this->oob_buf = kzalloc(mtd->oobsize, GFP_KERNEL);
+ if (!this->oob_buf) {
+ printk(KERN_ERR "onenand_scan(): Can't allocate oob_buf\n");
+ if (this->options & ONENAND_PAGEBUF_ALLOC) {
+ this->options &= ~ONENAND_PAGEBUF_ALLOC;
+ kfree(this->page_buf);
+ }
+ return -ENOMEM;
+ }
+ this->options |= ONENAND_OOBBUF_ALLOC;
+ }
this->state = FL_READY;
init_waitqueue_head(&this->wq);
@@ -2367,6 +2389,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
for (i = 0; this->ecclayout->oobfree[i].length; i++)
this->ecclayout->oobavail +=
this->ecclayout->oobfree[i].length;
+ mtd->oobavail = this->ecclayout->oobavail;
mtd->ecclayout = this->ecclayout;
@@ -2424,9 +2447,11 @@ void onenand_release(struct mtd_info *mtd)
kfree(bbm->bbt);
kfree(this->bbm);
}
- /* Buffer allocated by onenand_scan */
+ /* Buffers allocated by onenand_scan */
if (this->options & ONENAND_PAGEBUF_ALLOC)
kfree(this->page_buf);
+ if (this->options & ONENAND_OOBBUF_ALLOC)
+ kfree(this->oob_buf);
}
EXPORT_SYMBOL_GPL(onenand_scan);
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 72995777f809..b406ecfa7268 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -858,19 +858,7 @@ static struct eisa_device_id vortex_eisa_ids[] = {
};
MODULE_DEVICE_TABLE(eisa, vortex_eisa_ids);
-static int vortex_eisa_probe(struct device *device);
-static int vortex_eisa_remove(struct device *device);
-
-static struct eisa_driver vortex_eisa_driver = {
- .id_table = vortex_eisa_ids,
- .driver = {
- .name = "3c59x",
- .probe = vortex_eisa_probe,
- .remove = vortex_eisa_remove
- }
-};
-
-static int vortex_eisa_probe(struct device *device)
+static int __init vortex_eisa_probe(struct device *device)
{
void __iomem *ioaddr;
struct eisa_device *edev;
@@ -893,7 +881,7 @@ static int vortex_eisa_probe(struct device *device)
return 0;
}
-static int vortex_eisa_remove(struct device *device)
+static int __devexit vortex_eisa_remove(struct device *device)
{
struct eisa_device *edev;
struct net_device *dev;
@@ -918,7 +906,17 @@ static int vortex_eisa_remove(struct device *device)
free_netdev(dev);
return 0;
}
-#endif
+
+static struct eisa_driver vortex_eisa_driver = {
+ .id_table = vortex_eisa_ids,
+ .driver = {
+ .name = "3c59x",
+ .probe = vortex_eisa_probe,
+ .remove = __devexit_p(vortex_eisa_remove)
+ }
+};
+
+#endif /* CONFIG_EISA */
/* returns count found (>= 0), or negative on error */
static int __init vortex_eisa_init(void)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index dae0aa408bc4..753695b624b3 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2373,22 +2373,23 @@ config CHELSIO_T1_NAPI
when the driver is receiving lots of packets from the card.
config CHELSIO_T3
- tristate "Chelsio Communications T3 10Gb Ethernet support"
- depends on PCI
- help
- This driver supports Chelsio T3-based gigabit and 10Gb Ethernet
- adapters.
+ tristate "Chelsio Communications T3 10Gb Ethernet support"
+ depends on PCI
+ select FW_LOADER
+ help
+ This driver supports Chelsio T3-based gigabit and 10Gb Ethernet
+ adapters.
- For general information about Chelsio and our products, visit
- our website at <http://www.chelsio.com>.
+ For general information about Chelsio and our products, visit
+ our website at <http://www.chelsio.com>.
- For customer support, please visit our customer support page at
- <http://www.chelsio.com/support.htm>.
+ For customer support, please visit our customer support page at
+ <http://www.chelsio.com/support.htm>.
- Please send feedback to <linux-bugs@chelsio.com>.
+ Please send feedback to <linux-bugs@chelsio.com>.
- To compile this driver as a module, choose M here: the module
- will be called cxgb3.
+ To compile this driver as a module, choose M here: the module
+ will be called cxgb3.
config EHEA
tristate "eHEA Ethernet support"
diff --git a/drivers/net/atl1/atl1_hw.c b/drivers/net/atl1/atl1_hw.c
index 314dbaabb642..69482e0d849b 100644
--- a/drivers/net/atl1/atl1_hw.c
+++ b/drivers/net/atl1/atl1_hw.c
@@ -334,7 +334,6 @@ u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr)
int i;
crc32 = ether_crc_le(6, mc_addr);
- crc32 = ~crc32;
for (i = 0; i < 32; i++)
value |= (((crc32 >> i) & 1) << (31 - i));
diff --git a/drivers/net/atl1/atl1_main.c b/drivers/net/atl1/atl1_main.c
index 88d4f70035bb..8606eac5bec8 100644
--- a/drivers/net/atl1/atl1_main.c
+++ b/drivers/net/atl1/atl1_main.c
@@ -1328,7 +1328,7 @@ static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
cso = skb->h.raw - skb->data;
- css = (skb->h.raw + skb->csum) - skb->data;
+ css = (skb->h.raw + skb->csum_offset) - skb->data;
if (unlikely(cso & 0x1)) {
printk(KERN_DEBUG "%s: payload offset != even number\n",
atl1_driver_name);
@@ -1562,7 +1562,7 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
/* mss will be nonzero if we're doing segment offload (TSO/GSO) */
mss = skb_shinfo(skb)->gso_size;
if (mss) {
- if (skb->protocol == ntohs(ETH_P_IP)) {
+ if (skb->protocol == htons(ETH_P_IP)) {
proto_hdr_len = ((skb->h.raw - skb->data) +
(skb->h.th->doff << 2));
if (unlikely(proto_hdr_len > len)) {
@@ -2320,6 +2320,16 @@ static void __devexit atl1_remove(struct pci_dev *pdev)
return;
adapter = netdev_priv(netdev);
+
+ /* Some atl1 boards lack persistent storage for their MAC, and get it
+ * from the BIOS during POST. If we've been messing with the MAC
+ * address, we need to save the permanent one.
+ */
+ if (memcmp(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN)) {
+ memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN);
+ atl1_set_mac_addr(&adapter->hw);
+ }
+
iowrite16(0, adapter->hw.hw_addr + REG_GPHY_ENABLE);
unregister_netdev(netdev);
pci_iounmap(pdev, adapter->hw.hw_addr);
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index aaada572732a..d742bfe24471 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -1709,7 +1709,7 @@ static void __b44_set_rx_mode(struct net_device *dev)
bw32(bp, B44_RXCONFIG, val);
} else {
unsigned char zero[6] = {0, 0, 0, 0, 0, 0};
- int i = 0;
+ int i = 1;
__b44_set_mac_addr(bp);
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index c12e5ea61819..0b7aded8dcfd 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -54,8 +54,8 @@
#define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "1.5.5"
-#define DRV_MODULE_RELDATE "February 1, 2007"
+#define DRV_MODULE_VERSION "1.5.7"
+#define DRV_MODULE_RELDATE "March 29, 2007"
#define RUN_AT(x) (jiffies + (x))
@@ -2033,8 +2033,8 @@ bnx2_has_work(struct bnx2 *bp)
(sblk->status_tx_quick_consumer_index0 != bp->hw_tx_cons))
return 1;
- if (((sblk->status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) != 0) !=
- bp->link_up)
+ if ((sblk->status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) !=
+ (sblk->status_attn_bits_ack & STATUS_ATTN_BITS_LINK_STATE))
return 1;
return 0;
@@ -3099,20 +3099,18 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf,
if ((align_start = (offset32 & 3))) {
offset32 &= ~3;
- len32 += (4 - align_start);
+ len32 += align_start;
+ if (len32 < 4)
+ len32 = 4;
if ((rc = bnx2_nvram_read(bp, offset32, start, 4)))
return rc;
}
if (len32 & 3) {
- if ((len32 > 4) || !align_start) {
- align_end = 4 - (len32 & 3);
- len32 += align_end;
- if ((rc = bnx2_nvram_read(bp, offset32 + len32 - 4,
- end, 4))) {
- return rc;
- }
- }
+ align_end = 4 - (len32 & 3);
+ len32 += align_end;
+ if ((rc = bnx2_nvram_read(bp, offset32 + len32 - 4, end, 4)))
+ return rc;
}
if (align_start || align_end) {
@@ -3187,17 +3185,17 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf,
if ((rc = bnx2_enable_nvram_write(bp)) != 0)
goto nvram_write_end;
- /* Erase the page */
- if ((rc = bnx2_nvram_erase_page(bp, page_start)) != 0)
- goto nvram_write_end;
-
- /* Re-enable the write again for the actual write */
- bnx2_enable_nvram_write(bp);
-
/* Loop to write back the buffer data from page_start to
* data_start */
i = 0;
if (bp->flash_info->buffered == 0) {
+ /* Erase the page */
+ if ((rc = bnx2_nvram_erase_page(bp, page_start)) != 0)
+ goto nvram_write_end;
+
+ /* Re-enable the write again for the actual write */
+ bnx2_enable_nvram_write(bp);
+
for (addr = page_start; addr < data_start;
addr += 4, i += 4) {
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h
index e23deeb7d06d..8d1379633698 100644
--- a/drivers/net/cxgb3/common.h
+++ b/drivers/net/cxgb3/common.h
@@ -112,8 +112,7 @@ enum {
};
enum {
- SUPPORTED_OFFLOAD = 1 << 24,
- SUPPORTED_IRQ = 1 << 25
+ SUPPORTED_IRQ = 1 << 24
};
enum { /* adapter interrupt-maintained statistics */
@@ -260,6 +259,10 @@ struct mac_stats {
unsigned long serdes_signal_loss;
unsigned long xaui_pcs_ctc_err;
unsigned long xaui_pcs_align_change;
+
+ unsigned long num_toggled; /* # times toggled TxEn due to stuck TX */
+ unsigned long num_resets; /* # times reset due to stuck TX */
+
};
struct tp_mib_stats {
@@ -354,6 +357,9 @@ enum {
MC5_MODE_72_BIT = 2
};
+/* MC5 min active region size */
+enum { MC5_MIN_TIDS = 16 };
+
struct vpd_params {
unsigned int cclk;
unsigned int mclk;
@@ -398,6 +404,13 @@ struct adapter_params {
unsigned int stats_update_period; /* MAC stats accumulation period */
unsigned int linkpoll_period; /* link poll period in 0.1s */
unsigned int rev; /* chip revision */
+ unsigned int offload;
+};
+
+enum { /* chip revisions */
+ T3_REV_A = 0,
+ T3_REV_B = 2,
+ T3_REV_B2 = 3,
};
struct trace_params {
@@ -465,6 +478,13 @@ struct cmac {
struct adapter *adapter;
unsigned int offset;
unsigned int nucast; /* # of address filters for unicast MACs */
+ unsigned int tx_tcnt;
+ unsigned int tx_xcnt;
+ u64 tx_mcnt;
+ unsigned int rx_xcnt;
+ u64 rx_mcnt;
+ unsigned int toggle_cnt;
+ unsigned int txen;
struct mac_stats stats;
};
@@ -588,7 +608,7 @@ static inline int is_10G(const struct adapter *adap)
static inline int is_offload(const struct adapter *adap)
{
- return adapter_info(adap)->caps & SUPPORTED_OFFLOAD;
+ return adap->params.offload;
}
static inline unsigned int core_ticks_per_usec(const struct adapter *adap)
@@ -666,6 +686,7 @@ int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6]);
int t3_mac_set_num_ucast(struct cmac *mac, int n);
const struct mac_stats *t3_mac_update_stats(struct cmac *mac);
int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc);
+int t3b2_mac_watchdog_task(struct cmac *mac);
void t3_mc5_prep(struct adapter *adapter, struct mc5 *mc5, int mode);
int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index 7ff834e45d6b..67b4b219d927 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -42,6 +42,7 @@
#include <linux/workqueue.h>
#include <linux/proc_fs.h>
#include <linux/rtnetlink.h>
+#include <linux/firmware.h>
#include <asm/uaccess.h>
#include "common.h"
@@ -184,16 +185,24 @@ void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat,
int speed, int duplex, int pause)
{
struct net_device *dev = adapter->port[port_id];
+ struct port_info *pi = netdev_priv(dev);
+ struct cmac *mac = &pi->mac;
/* Skip changes from disabled ports. */
if (!netif_running(dev))
return;
if (link_stat != netif_carrier_ok(dev)) {
- if (link_stat)
+ if (link_stat) {
+ t3_mac_enable(mac, MAC_DIRECTION_RX);
netif_carrier_on(dev);
- else
+ } else {
netif_carrier_off(dev);
+ pi->phy.ops->power_down(&pi->phy, 1);
+ t3_mac_disable(mac, MAC_DIRECTION_RX);
+ t3_link_start(&pi->phy, mac, &pi->link_config);
+ }
+
link_report(dev);
}
}
@@ -406,7 +415,7 @@ static void quiesce_rx(struct adapter *adap)
static int setup_sge_qsets(struct adapter *adap)
{
int i, j, err, irq_idx = 0, qset_idx = 0, dummy_dev_idx = 0;
- unsigned int ntxq = is_offload(adap) ? SGE_TXQ_PER_SET : 1;
+ unsigned int ntxq = SGE_TXQ_PER_SET;
if (adap->params.rev > 0 && !(adap->flags & USING_MSI))
irq_idx = -1;
@@ -484,12 +493,14 @@ static ssize_t show_##name(struct device *d, struct device_attribute *attr, \
static ssize_t set_nfilters(struct net_device *dev, unsigned int val)
{
struct adapter *adap = dev->priv;
+ int min_tids = is_offload(adap) ? MC5_MIN_TIDS : 0;
if (adap->flags & FULL_INIT_DONE)
return -EBUSY;
if (val && adap->params.rev == 0)
return -EINVAL;
- if (val > t3_mc5_size(&adap->mc5) - adap->params.mc5.nservers)
+ if (val > t3_mc5_size(&adap->mc5) - adap->params.mc5.nservers -
+ min_tids)
return -EINVAL;
adap->params.mc5.nfilters = val;
return 0;
@@ -507,7 +518,8 @@ static ssize_t set_nservers(struct net_device *dev, unsigned int val)
if (adap->flags & FULL_INIT_DONE)
return -EBUSY;
- if (val > t3_mc5_size(&adap->mc5) - adap->params.mc5.nfilters)
+ if (val > t3_mc5_size(&adap->mc5) - adap->params.mc5.nfilters -
+ MC5_MIN_TIDS)
return -EINVAL;
adap->params.mc5.nservers = val;
return 0;
@@ -707,6 +719,28 @@ static void bind_qsets(struct adapter *adap)
}
}
+#define FW_FNAME "t3fw-%d.%d.%d.bin"
+
+static int upgrade_fw(struct adapter *adap)
+{
+ int ret;
+ char buf[64];
+ const struct firmware *fw;
+ struct device *dev = &adap->pdev->dev;
+
+ snprintf(buf, sizeof(buf), FW_FNAME, FW_VERSION_MAJOR,
+ FW_VERSION_MINOR, FW_VERSION_MICRO);
+ ret = request_firmware(&fw, buf, dev);
+ if (ret < 0) {
+ dev_err(dev, "could not upgrade firmware: unable to load %s\n",
+ buf);
+ return ret;
+ }
+ ret = t3_load_fw(adap, fw->data, fw->size);
+ release_firmware(fw);
+ return ret;
+}
+
/**
* cxgb_up - enable the adapter
* @adapter: adapter being enabled
@@ -723,6 +757,8 @@ static int cxgb_up(struct adapter *adap)
if (!(adap->flags & FULL_INIT_DONE)) {
err = t3_check_fw_version(adap);
+ if (err == -EINVAL)
+ err = upgrade_fw(adap);
if (err)
goto out;
@@ -734,6 +770,8 @@ static int cxgb_up(struct adapter *adap)
if (err)
goto out;
+ t3_write_reg(adap, A_ULPRX_TDDP_PSZ, V_HPZ0(PAGE_SHIFT - 12));
+
err = setup_sge_qsets(adap);
if (err)
goto out;
@@ -894,7 +932,7 @@ static int cxgb_open(struct net_device *dev)
return err;
set_bit(pi->port_id, &adapter->open_device_map);
- if (!ofld_disable) {
+ if (is_offload(adapter) && !ofld_disable) {
err = offload_open(dev);
if (err)
printk(KERN_WARNING
@@ -1031,7 +1069,11 @@ static char stats_strings[][ETH_GSTRING_LEN] = {
"VLANinsertions ",
"TxCsumOffload ",
"RxCsumGood ",
- "RxDrops "
+ "RxDrops ",
+
+ "CheckTXEnToggled ",
+ "CheckResets ",
+
};
static int get_stats_count(struct net_device *dev)
@@ -1145,6 +1187,9 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
*data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_TX_CSUM);
*data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_RX_CSUM_GOOD);
*data++ = s->rx_cong_drops;
+
+ *data++ = s->num_toggled;
+ *data++ = s->num_resets;
}
static inline void reg_block_dump(struct adapter *ap, void *buf,
@@ -1362,23 +1407,27 @@ static int set_rx_csum(struct net_device *dev, u32 data)
static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
{
- struct adapter *adapter = dev->priv;
+ const struct adapter *adapter = dev->priv;
+ const struct port_info *pi = netdev_priv(dev);
+ const struct qset_params *q = &adapter->params.sge.qset[pi->first_qset];
e->rx_max_pending = MAX_RX_BUFFERS;
e->rx_mini_max_pending = 0;
e->rx_jumbo_max_pending = MAX_RX_JUMBO_BUFFERS;
e->tx_max_pending = MAX_TXQ_ENTRIES;
- e->rx_pending = adapter->params.sge.qset[0].fl_size;
- e->rx_mini_pending = adapter->params.sge.qset[0].rspq_size;
- e->rx_jumbo_pending = adapter->params.sge.qset[0].jumbo_size;
- e->tx_pending = adapter->params.sge.qset[0].txq_size[0];
+ e->rx_pending = q->fl_size;
+ e->rx_mini_pending = q->rspq_size;
+ e->rx_jumbo_pending = q->jumbo_size;
+ e->tx_pending = q->txq_size[0];
}
static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
{
int i;
+ struct qset_params *q;
struct adapter *adapter = dev->priv;
+ const struct port_info *pi = netdev_priv(dev);
if (e->rx_pending > MAX_RX_BUFFERS ||
e->rx_jumbo_pending > MAX_RX_JUMBO_BUFFERS ||
@@ -1393,9 +1442,8 @@ static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
if (adapter->flags & FULL_INIT_DONE)
return -EBUSY;
- for (i = 0; i < SGE_QSETS; ++i) {
- struct qset_params *q = &adapter->params.sge.qset[i];
-
+ q = &adapter->params.sge.qset[pi->first_qset];
+ for (i = 0; i < pi->nqsets; ++i, ++q) {
q->rspq_size = e->rx_mini_pending;
q->fl_size = e->rx_pending;
q->jumbo_size = e->rx_jumbo_pending;
@@ -2067,6 +2115,42 @@ static void check_link_status(struct adapter *adapter)
}
}
+static void check_t3b2_mac(struct adapter *adapter)
+{
+ int i;
+
+ if (!rtnl_trylock()) /* synchronize with ifdown */
+ return;
+
+ for_each_port(adapter, i) {
+ struct net_device *dev = adapter->port[i];
+ struct port_info *p = netdev_priv(dev);
+ int status;
+
+ if (!netif_running(dev))
+ continue;
+
+ status = 0;
+ if (netif_running(dev) && netif_carrier_ok(dev))
+ status = t3b2_mac_watchdog_task(&p->mac);
+ if (status == 1)
+ p->mac.stats.num_toggled++;
+ else if (status == 2) {
+ struct cmac *mac = &p->mac;
+
+ t3_mac_set_mtu(mac, dev->mtu);
+ t3_mac_set_address(mac, 0, dev->dev_addr);
+ cxgb_set_rxmode(dev);
+ t3_link_start(&p->phy, mac, &p->link_config);
+ t3_mac_enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
+ t3_port_intr_enable(adapter, p->port_id);
+ p->mac.stats.num_resets++;
+ }
+ }
+ rtnl_unlock();
+}
+
+
static void t3_adap_check_task(struct work_struct *work)
{
struct adapter *adapter = container_of(work, struct adapter,
@@ -2087,6 +2171,9 @@ static void t3_adap_check_task(struct work_struct *work)
adapter->check_task_cnt = 0;
}
+ if (p->rev == T3_REV_B2)
+ check_t3b2_mac(adapter);
+
/* Schedule the next check update if any port is active. */
spin_lock(&adapter->work_lock);
if (adapter->open_device_map & PORT_MASK)
@@ -2195,9 +2282,9 @@ static void __devinit print_port_info(struct adapter *adap,
if (!test_bit(i, &adap->registered_device_map))
continue;
- printk(KERN_INFO "%s: %s %s RNIC (rev %d) %s%s\n",
+ printk(KERN_INFO "%s: %s %s %sNIC (rev %d) %s%s\n",
dev->name, ai->desc, pi->port_type->desc,
- adap->params.rev, buf,
+ is_offload(adap) ? "R" : "", adap->params.rev, buf,
(adap->flags & USING_MSIX) ? " MSI-X" :
(adap->flags & USING_MSI) ? " MSI" : "");
if (adap->name == dev->name && adap->params.vpd.mclk)
diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
index f6ed033efb56..48649244673e 100644
--- a/drivers/net/cxgb3/cxgb3_offload.c
+++ b/drivers/net/cxgb3/cxgb3_offload.c
@@ -553,7 +553,9 @@ int cxgb3_alloc_atid(struct t3cdev *tdev, struct cxgb3_client *client,
struct tid_info *t = &(T3C_DATA(tdev))->tid_maps;
spin_lock_bh(&t->atid_lock);
- if (t->afree) {
+ if (t->afree &&
+ t->atids_in_use + atomic_read(&t->tids_in_use) + MC5_MIN_TIDS <=
+ t->ntids) {
union active_open_entry *p = t->afree;
atid = (p - t->atid_tab) + t->atid_base;
@@ -741,17 +743,6 @@ static int do_act_establish(struct t3cdev *dev, struct sk_buff *skb)
}
}
-static int do_set_tcb_rpl(struct t3cdev *dev, struct sk_buff *skb)
-{
- struct cpl_set_tcb_rpl *rpl = cplhdr(skb);
-
- if (rpl->status != CPL_ERR_NONE)
- printk(KERN_ERR
- "Unexpected SET_TCB_RPL status %u for tid %u\n",
- rpl->status, GET_TID(rpl));
- return CPL_RET_BUF_DONE;
-}
-
static int do_trace(struct t3cdev *dev, struct sk_buff *skb)
{
struct cpl_trace_pkt *p = cplhdr(skb);
@@ -1213,7 +1204,8 @@ void __init cxgb3_offload_init(void)
t3_register_cpl_handler(CPL_CLOSE_CON_RPL, do_hwtid_rpl);
t3_register_cpl_handler(CPL_ABORT_REQ_RSS, do_abort_req_rss);
t3_register_cpl_handler(CPL_ACT_ESTABLISH, do_act_establish);
- t3_register_cpl_handler(CPL_SET_TCB_RPL, do_set_tcb_rpl);
+ t3_register_cpl_handler(CPL_SET_TCB_RPL, do_hwtid_rpl);
+ t3_register_cpl_handler(CPL_GET_TCB_RPL, do_hwtid_rpl);
t3_register_cpl_handler(CPL_RDMA_TERMINATE, do_term);
t3_register_cpl_handler(CPL_RDMA_EC_STATUS, do_hwtid_rpl);
t3_register_cpl_handler(CPL_TRACE_PKT, do_trace);
diff --git a/drivers/net/cxgb3/mc5.c b/drivers/net/cxgb3/mc5.c
index 644d62ea86a6..84c1ffa8e2d3 100644
--- a/drivers/net/cxgb3/mc5.c
+++ b/drivers/net/cxgb3/mc5.c
@@ -328,6 +328,9 @@ int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
unsigned int tcam_size = mc5->tcam_size;
struct adapter *adap = mc5->adapter;
+ if (!tcam_size)
+ return 0;
+
if (nroutes > MAX_ROUTES || nroutes + nservers + nfilters > tcam_size)
return -EINVAL;
diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h
index b56c5f52bcdc..e5a553410e24 100644
--- a/drivers/net/cxgb3/regs.h
+++ b/drivers/net/cxgb3/regs.h
@@ -1206,6 +1206,14 @@
#define A_TP_RX_TRC_KEY0 0x120
+#define A_TP_TX_DROP_CNT_CH0 0x12d
+
+#define S_TXDROPCNTCH0RCVD 0
+#define M_TXDROPCNTCH0RCVD 0xffff
+#define V_TXDROPCNTCH0RCVD(x) ((x) << S_TXDROPCNTCH0RCVD)
+#define G_TXDROPCNTCH0RCVD(x) (((x) >> S_TXDROPCNTCH0RCVD) & \
+ M_TXDROPCNTCH0RCVD)
+
#define A_ULPRX_CTL 0x500
#define S_ROUND_ROBIN 4
@@ -1226,9 +1234,15 @@
#define A_ULPRX_ISCSI_TAGMASK 0x514
+#define S_HPZ0 0
+#define M_HPZ0 0xf
+#define V_HPZ0(x) ((x) << S_HPZ0)
+#define G_HPZ0(x) (((x) >> S_HPZ0) & M_HPZ0)
+
#define A_ULPRX_TDDP_LLIMIT 0x51c
#define A_ULPRX_TDDP_ULIMIT 0x520
+#define A_ULPRX_TDDP_PSZ 0x528
#define A_ULPRX_STAG_LLIMIT 0x52c
@@ -1834,6 +1848,8 @@
#define V_TXPAUSEEN(x) ((x) << S_TXPAUSEEN)
#define F_TXPAUSEEN V_TXPAUSEEN(1U)
+#define A_XGM_TX_PAUSE_QUANTA 0x808
+
#define A_XGM_RX_CTRL 0x80c
#define S_RXEN 0
@@ -1920,11 +1936,20 @@
#define A_XGM_TXFIFO_CFG 0x888
+#define S_TXIPG 13
+#define M_TXIPG 0xff
+#define V_TXIPG(x) ((x) << S_TXIPG)
+#define G_TXIPG(x) (((x) >> S_TXIPG) & M_TXIPG)
+
#define S_TXFIFOTHRESH 4
#define M_TXFIFOTHRESH 0x1ff
#define V_TXFIFOTHRESH(x) ((x) << S_TXFIFOTHRESH)
+#define S_ENDROPPKT 21
+#define V_ENDROPPKT(x) ((x) << S_ENDROPPKT)
+#define F_ENDROPPKT V_ENDROPPKT(1U)
+
#define A_XGM_SERDES_CTRL 0x890
#define A_XGM_SERDES_CTRL0 0x8e0
@@ -2190,6 +2215,13 @@
#define A_XGM_RX_MAX_PKT_SIZE_ERR_CNT 0x9a4
+#define A_XGM_TX_SPI4_SOP_EOP_CNT 0x9a8
+
+#define S_TXSPI4SOPCNT 16
+#define M_TXSPI4SOPCNT 0xffff
+#define V_TXSPI4SOPCNT(x) ((x) << S_TXSPI4SOPCNT)
+#define G_TXSPI4SOPCNT(x) (((x) >> S_TXSPI4SOPCNT) & M_TXSPI4SOPCNT)
+
#define A_XGM_RX_SPI4_SOP_EOP_CNT 0x9ac
#define XGMAC0_1_BASE_ADDR 0xa00
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index c23783432e51..027ab2c3825c 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -2631,7 +2631,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
q->txq[TXQ_ETH].stop_thres = nports *
flits_to_desc(sgl_len(MAX_SKB_FRAGS + 1) + 3);
- if (ntxq == 1) {
+ if (!is_offload(adapter)) {
#ifdef USE_RX_PAGE
q->fl[0].buf_size = RX_PAGE_SIZE;
#else
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
index eaa7a2e89a30..d83f075ef2d7 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/cxgb3/t3_hw.c
@@ -438,23 +438,23 @@ static const struct adapter_info t3_adap_info[] = {
{2, 0, 0, 0,
F_GPIO2_OEN | F_GPIO4_OEN |
F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, F_GPIO3 | F_GPIO5,
- SUPPORTED_OFFLOAD,
+ 0,
&mi1_mdio_ops, "Chelsio PE9000"},
{2, 0, 0, 0,
F_GPIO2_OEN | F_GPIO4_OEN |
F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, F_GPIO3 | F_GPIO5,
- SUPPORTED_OFFLOAD,
+ 0,
&mi1_mdio_ops, "Chelsio T302"},
{1, 0, 0, 0,
F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN |
F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, 0,
- SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_OFFLOAD,
+ SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
&mi1_mdio_ext_ops, "Chelsio T310"},
{2, 0, 0, 0,
F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO5_OEN | F_GPIO6_OEN |
F_GPIO7_OEN | F_GPIO10_OEN | F_GPIO11_OEN | F_GPIO1_OUT_VAL |
F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, 0,
- SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_OFFLOAD,
+ SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
&mi1_mdio_ext_ops, "Chelsio T320"},
};
@@ -681,7 +681,8 @@ enum {
SF_ERASE_SECTOR = 0xd8, /* erase sector */
FW_FLASH_BOOT_ADDR = 0x70000, /* start address of FW in flash */
- FW_VERS_ADDR = 0x77ffc /* flash address holding FW version */
+ FW_VERS_ADDR = 0x77ffc, /* flash address holding FW version */
+ FW_MIN_SIZE = 8 /* at least version and csum */
};
/**
@@ -935,7 +936,7 @@ int t3_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size)
const u32 *p = (const u32 *)fw_data;
int ret, addr, fw_sector = FW_FLASH_BOOT_ADDR >> 16;
- if (size & 3)
+ if ((size & 3) || size < FW_MIN_SIZE)
return -EINVAL;
if (size > FW_VERS_ADDR + 8 - FW_FLASH_BOOT_ADDR)
return -EFBIG;
@@ -2899,6 +2900,9 @@ static int mc7_init(struct mc7 *mc7, unsigned int mc7_clock, int mem_type)
struct adapter *adapter = mc7->adapter;
const struct mc7_timing_params *p = &mc7_timings[mem_type];
+ if (!mc7->size)
+ return 0;
+
val = t3_read_reg(adapter, mc7->offset + A_MC7_CFG);
slow = val & F_SLOW;
width = G_WIDTH(val);
@@ -3099,8 +3103,10 @@ int t3_init_hw(struct adapter *adapter, u32 fw_params)
do { /* wait for uP to initialize */
msleep(20);
} while (t3_read_reg(adapter, A_CIM_HOST_ACC_DATA) && --attempts);
- if (!attempts)
+ if (!attempts) {
+ CH_ERR(adapter, "uP initialization timed out\n");
goto out_err;
+ }
err = 0;
out_err:
@@ -3200,7 +3206,7 @@ static void __devinit mc7_prep(struct adapter *adapter, struct mc7 *mc7,
mc7->name = name;
mc7->offset = base_addr - MC7_PMRX_BASE_ADDR;
cfg = t3_read_reg(adapter, mc7->offset + A_MC7_CFG);
- mc7->size = mc7_calc_size(cfg);
+ mc7->size = mc7->size = G_DEN(cfg) == M_DEN ? 0 : mc7_calc_size(cfg);
mc7->width = G_WIDTH(cfg);
}
@@ -3227,6 +3233,7 @@ void early_hw_init(struct adapter *adapter, const struct adapter_info *ai)
V_I2C_CLKDIV(adapter->params.vpd.cclk / 80 - 1));
t3_write_reg(adapter, A_T3DBG_GPIO_EN,
ai->gpio_out | F_GPIO0_OEN | F_GPIO0_OUT_VAL);
+ t3_write_reg(adapter, A_MC5_DB_SERVER_INDEX, 0);
if (adapter->params.rev == 0 || !uses_xaui(adapter))
val |= F_ENRGMII;
@@ -3243,15 +3250,17 @@ void early_hw_init(struct adapter *adapter, const struct adapter_info *ai)
}
/*
- * Reset the adapter. PCIe cards lose their config space during reset, PCI-X
+ * Reset the adapter.
+ * Older PCIe cards lose their config space during reset, PCI-X
* ones don't.
*/
int t3_reset_adapter(struct adapter *adapter)
{
- int i;
+ int i, save_and_restore_pcie =
+ adapter->params.rev < T3_REV_B2 && is_pcie(adapter);
uint16_t devid = 0;
- if (is_pcie(adapter))
+ if (save_and_restore_pcie)
pci_save_state(adapter->pdev);
t3_write_reg(adapter, A_PL_RST, F_CRSTWRM | F_CRSTWRMMODE);
@@ -3269,7 +3278,7 @@ int t3_reset_adapter(struct adapter *adapter)
if (devid != 0x1425)
return -1;
- if (is_pcie(adapter))
+ if (save_and_restore_pcie)
pci_restore_state(adapter->pdev);
return 0;
}
@@ -3323,7 +3332,13 @@ int __devinit t3_prep_adapter(struct adapter *adapter,
p->tx_num_pgs = pm_num_pages(p->chan_tx_size, p->tx_pg_size);
p->ntimer_qs = p->cm_size >= (128 << 20) ||
adapter->params.rev > 0 ? 12 : 6;
+ }
+
+ adapter->params.offload = t3_mc7_size(&adapter->pmrx) &&
+ t3_mc7_size(&adapter->pmtx) &&
+ t3_mc7_size(&adapter->cm);
+ if (is_offload(adapter)) {
adapter->params.mc5.nservers = DEFAULT_NSERVERS;
adapter->params.mc5.nfilters = adapter->params.rev > 0 ?
DEFAULT_NFILTERS : 0;
diff --git a/drivers/net/cxgb3/version.h b/drivers/net/cxgb3/version.h
index 82278f850259..042e27e291cd 100644
--- a/drivers/net/cxgb3/version.h
+++ b/drivers/net/cxgb3/version.h
@@ -36,6 +36,9 @@
#define DRV_NAME "cxgb3"
/* Driver version */
#define DRV_VERSION "1.0-ko"
+
+/* Firmware version */
#define FW_VERSION_MAJOR 3
-#define FW_VERSION_MINOR 2
+#define FW_VERSION_MINOR 3
+#define FW_VERSION_MICRO 0
#endif /* __CHELSIO_VERSION_H */
diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c
index 907a272ae32d..a506792f9575 100644
--- a/drivers/net/cxgb3/xgmac.c
+++ b/drivers/net/cxgb3/xgmac.c
@@ -124,9 +124,6 @@ int t3_mac_reset(struct cmac *mac)
xaui_serdes_reset(mac);
}
- if (adap->params.rev > 0)
- t3_write_reg(adap, A_XGM_PAUSE_TIMER + oft, 0xf000);
-
val = F_MAC_RESET_;
if (is_10G(adap))
val |= F_PCS_RESET_;
@@ -145,6 +142,58 @@ int t3_mac_reset(struct cmac *mac)
return 0;
}
+int t3b2_mac_reset(struct cmac *mac)
+{
+ struct adapter *adap = mac->adapter;
+ unsigned int oft = mac->offset;
+ u32 val;
+
+ if (!macidx(mac))
+ t3_set_reg_field(adap, A_MPS_CFG, F_PORT0ACTIVE, 0);
+ else
+ t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE, 0);
+
+ t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_);
+ t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
+
+ msleep(10);
+
+ /* Check for xgm Rx fifo empty */
+ if (t3_wait_op_done(adap, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + oft,
+ 0x80000000, 1, 5, 2)) {
+ CH_ERR(adap, "MAC %d Rx fifo drain failed\n",
+ macidx(mac));
+ return -1;
+ }
+
+ t3_write_reg(adap, A_XGM_RESET_CTRL + oft, 0);
+ t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
+
+ val = F_MAC_RESET_;
+ if (is_10G(adap))
+ val |= F_PCS_RESET_;
+ else if (uses_xaui(adap))
+ val |= F_PCS_RESET_ | F_XG2G_RESET_;
+ else
+ val |= F_RGMII_RESET_ | F_XG2G_RESET_;
+ t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val);
+ t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
+ if ((val & F_PCS_RESET_) && adap->params.rev) {
+ msleep(1);
+ t3b_pcs_reset(mac);
+ }
+ t3_write_reg(adap, A_XGM_RX_CFG + oft,
+ F_DISPAUSEFRAMES | F_EN1536BFRAMES |
+ F_RMFCS | F_ENJUMBO | F_ENHASHMCAST);
+
+ if (!macidx(mac))
+ t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT0ACTIVE);
+ else
+ t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT1ACTIVE);
+
+ return 0;
+}
+
/*
* Set the exact match register 'idx' to recognize the given Ethernet address.
*/
@@ -251,9 +300,11 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
* Adjust the PAUSE frame watermarks. We always set the LWM, and the
* HWM only if flow-control is enabled.
*/
- hwm = max(MAC_RXFIFO_SIZE - 3 * mtu, MAC_RXFIFO_SIZE / 2U);
- hwm = min(hwm, 3 * MAC_RXFIFO_SIZE / 4 + 1024);
- lwm = hwm - 1024;
+ hwm = max_t(unsigned int, MAC_RXFIFO_SIZE - 3 * mtu,
+ MAC_RXFIFO_SIZE * 38 / 100);
+ hwm = min(hwm, MAC_RXFIFO_SIZE - 8192);
+ lwm = min(3 * (int)mtu, MAC_RXFIFO_SIZE / 4);
+
v = t3_read_reg(adap, A_XGM_RXFIFO_CFG + mac->offset);
v &= ~V_RXFIFOPAUSELWM(M_RXFIFOPAUSELWM);
v |= V_RXFIFOPAUSELWM(lwm / 8);
@@ -270,7 +321,15 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
thres = mtu > thres ? (mtu - thres + 7) / 8 : 0;
thres = max(thres, 8U); /* need at least 8 */
t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + mac->offset,
- V_TXFIFOTHRESH(M_TXFIFOTHRESH), V_TXFIFOTHRESH(thres));
+ V_TXFIFOTHRESH(M_TXFIFOTHRESH) | V_TXIPG(M_TXIPG),
+ V_TXFIFOTHRESH(thres) | V_TXIPG(1));
+
+ if (adap->params.rev > 0)
+ t3_write_reg(adap, A_XGM_PAUSE_TIMER + mac->offset,
+ (hwm - lwm) * 4 / 8);
+ t3_write_reg(adap, A_XGM_TX_PAUSE_QUANTA + mac->offset,
+ MAC_RXFIFO_SIZE * 4 * 8 / 512);
+
return 0;
}
@@ -298,12 +357,6 @@ int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc)
V_PORTSPEED(M_PORTSPEED), val);
}
- val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft);
- val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM);
- if (fc & PAUSE_TX)
- val |= V_RXFIFOPAUSEHWM(G_RXFIFOPAUSELWM(val) + 128); /* +1KB */
- t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val);
-
t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN,
(fc & PAUSE_RX) ? F_TXPAUSEEN : 0);
return 0;
@@ -314,13 +367,28 @@ int t3_mac_enable(struct cmac *mac, int which)
int idx = macidx(mac);
struct adapter *adap = mac->adapter;
unsigned int oft = mac->offset;
-
+ struct mac_stats *s = &mac->stats;
+
if (which & MAC_DIRECTION_TX) {
t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN);
t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
- t3_write_reg(adap, A_TP_PIO_DATA, 0xbf000001);
+ t3_write_reg(adap, A_TP_PIO_DATA, 0xc0ede401);
t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE);
t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx);
+
+ t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + idx);
+ mac->tx_mcnt = s->tx_frames;
+ mac->tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
+ A_TP_PIO_DATA)));
+ mac->tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
+ A_XGM_TX_SPI4_SOP_EOP_CNT +
+ oft)));
+ mac->rx_mcnt = s->rx_frames;
+ mac->rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
+ A_XGM_RX_SPI4_SOP_EOP_CNT +
+ oft)));
+ mac->txen = F_TXEN;
+ mac->toggle_cnt = 0;
}
if (which & MAC_DIRECTION_RX)
t3_write_reg(adap, A_XGM_RX_CTRL + oft, F_RXEN);
@@ -331,19 +399,102 @@ int t3_mac_disable(struct cmac *mac, int which)
{
int idx = macidx(mac);
struct adapter *adap = mac->adapter;
+ int val;
if (which & MAC_DIRECTION_TX) {
t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0);
t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
t3_write_reg(adap, A_TP_PIO_DATA, 0xc000001f);
t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE);
- t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 0);
+ t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx);
+ mac->txen = 0;
}
- if (which & MAC_DIRECTION_RX)
+ if (which & MAC_DIRECTION_RX) {
+ t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset,
+ F_PCS_RESET_, 0);
+ msleep(100);
t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0);
+ val = F_MAC_RESET_;
+ if (is_10G(adap))
+ val |= F_PCS_RESET_;
+ else if (uses_xaui(adap))
+ val |= F_PCS_RESET_ | F_XG2G_RESET_;
+ else
+ val |= F_RGMII_RESET_ | F_XG2G_RESET_;
+ t3_write_reg(mac->adapter, A_XGM_RESET_CTRL + mac->offset, val);
+ }
return 0;
}
+int t3b2_mac_watchdog_task(struct cmac *mac)
+{
+ struct adapter *adap = mac->adapter;
+ struct mac_stats *s = &mac->stats;
+ unsigned int tx_tcnt, tx_xcnt;
+ unsigned int tx_mcnt = s->tx_frames;
+ unsigned int rx_mcnt = s->rx_frames;
+ unsigned int rx_xcnt;
+ int status;
+
+ if (tx_mcnt == mac->tx_mcnt) {
+ tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
+ A_XGM_TX_SPI4_SOP_EOP_CNT +
+ mac->offset)));
+ if (tx_xcnt == 0) {
+ t3_write_reg(adap, A_TP_PIO_ADDR,
+ A_TP_TX_DROP_CNT_CH0 + macidx(mac));
+ tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
+ A_TP_PIO_DATA)));
+ } else {
+ mac->toggle_cnt = 0;
+ return 0;
+ }
+ } else {
+ mac->toggle_cnt = 0;
+ return 0;
+ }
+
+ if (((tx_tcnt != mac->tx_tcnt) &&
+ (tx_xcnt == 0) && (mac->tx_xcnt == 0)) ||
+ ((mac->tx_mcnt == tx_mcnt) &&
+ (tx_xcnt != 0) && (mac->tx_xcnt != 0))) {
+ if (mac->toggle_cnt > 4)
+ status = 2;
+ else
+ status = 1;
+ } else {
+ mac->toggle_cnt = 0;
+ return 0;
+ }
+
+ if (rx_mcnt != mac->rx_mcnt)
+ rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
+ A_XGM_RX_SPI4_SOP_EOP_CNT +
+ mac->offset)));
+ else
+ return 0;
+
+ if (mac->rx_mcnt != s->rx_frames && rx_xcnt == 0 && mac->rx_xcnt == 0)
+ status = 2;
+
+ mac->tx_tcnt = tx_tcnt;
+ mac->tx_xcnt = tx_xcnt;
+ mac->tx_mcnt = s->tx_frames;
+ mac->rx_xcnt = rx_xcnt;
+ mac->rx_mcnt = s->rx_frames;
+ if (status == 1) {
+ t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0);
+ t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */
+ t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, mac->txen);
+ t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */
+ mac->toggle_cnt++;
+ } else if (status == 2) {
+ t3b2_mac_reset(mac);
+ mac->toggle_cnt = 0;
+ }
+ return status;
+}
+
/*
* This function is called periodically to accumulate the current values of the
* RMON counters into the port statistics. Since the packet counters are only
@@ -373,7 +524,11 @@ const struct mac_stats *t3_mac_update_stats(struct cmac *mac)
RMON_UPDATE(mac, rx_symbol_errs, RX_SYM_CODE_ERR_FRAMES);
RMON_UPDATE(mac, rx_too_long, RX_OVERSIZE_FRAMES);
- mac->stats.rx_too_long += RMON_READ(mac, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT);
+
+ v = RMON_READ(mac, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT);
+ if (mac->adapter->params.rev == T3_REV_B2)
+ v &= 0x7fffffff;
+ mac->stats.rx_too_long += v;
RMON_UPDATE(mac, rx_frames_64, RX_64B_FRAMES);
RMON_UPDATE(mac, rx_frames_65_127, RX_65_127B_FRAMES);
diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c
index c8c41f0a47d6..714ea1176ec7 100644
--- a/drivers/net/ewrk3.c
+++ b/drivers/net/ewrk3.c
@@ -414,10 +414,9 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase)
icr &= 0x70;
outb(icr, EWRK3_ICR); /* Disable all the IRQs */
- if (nicsr == (CSR_TXD | CSR_RXD))
+ if (nicsr != (CSR_TXD | CSR_RXD))
return -ENXIO;
-
/* Check that the EEPROM is alive and well and not living on Pluto... */
for (chksum = 0, i = 0; i < EEPROM_MAX; i += 2) {
union {
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 46e1697d9cfd..d04214e4e581 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -2050,9 +2050,10 @@ static void nv_tx_timeout(struct net_device *dev)
nv_drain_tx(dev);
nv_init_tx(dev);
setup_hw_rings(dev, NV_SETUP_TX_RING);
- netif_wake_queue(dev);
}
+ netif_wake_queue(dev);
+
/* 4) restart tx engine */
nv_start_tx(dev);
spin_unlock_irq(&np->lock);
@@ -3536,7 +3537,10 @@ static void nv_do_nic_poll(unsigned long data)
pci_push(base);
if (!using_multi_irqs(dev)) {
- nv_nic_irq(0, dev);
+ if (np->desc_ver == DESC_VER_3)
+ nv_nic_irq_optimized(0, dev);
+ else
+ nv_nic_irq(0, dev);
if (np->msi_flags & NV_MSI_X_ENABLED)
enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
else
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index ca2b21f9d444..07b4c0d7a75c 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -96,17 +96,24 @@ static void ri_tasklet(unsigned long dev)
skb->tc_verd = SET_TC_NCLS(skb->tc_verd);
stats->tx_packets++;
stats->tx_bytes +=skb->len;
+
+ skb->dev = __dev_get_by_index(skb->iif);
+ if (!skb->dev) {
+ dev_kfree_skb(skb);
+ stats->tx_dropped++;
+ break;
+ }
+ skb->iif = _dev->ifindex;
+
if (from & AT_EGRESS) {
dp->st_rx_frm_egr++;
dev_queue_xmit(skb);
} else if (from & AT_INGRESS) {
-
dp->st_rx_frm_ing++;
+ skb_pull(skb, skb->dev->hard_header_len);
netif_rx(skb);
- } else {
- dev_kfree_skb(skb);
- stats->tx_dropped++;
- }
+ } else
+ BUG();
}
if (netif_tx_trylock(_dev)) {
@@ -157,26 +164,10 @@ static int ifb_xmit(struct sk_buff *skb, struct net_device *dev)
stats->rx_packets++;
stats->rx_bytes+=skb->len;
- if (!from || !skb->input_dev) {
-dropped:
+ if (!(from & (AT_INGRESS|AT_EGRESS)) || !skb->iif) {
dev_kfree_skb(skb);
stats->rx_dropped++;
return ret;
- } else {
- /*
- * note we could be going
- * ingress -> egress or
- * egress -> ingress
- */
- skb->dev = skb->input_dev;
- skb->input_dev = dev;
- if (from & AT_INGRESS) {
- skb_pull(skb, skb->dev->hard_header_len);
- } else {
- if (!(from & AT_EGRESS)) {
- goto dropped;
- }
- }
}
if (skb_queue_len(&dp->rq) >= dev->tx_queue_len) {
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 340ee99652eb..1d510bdc9b84 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1057,6 +1057,8 @@ static int stir421x_fw_upload(struct irda_usb_cb *self,
if (ret < 0)
break;
+
+ mdelay(10);
}
kfree(patch_block);
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 9137e239fac2..2272156af31e 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -321,15 +321,22 @@ static void pxa_irda_fir_dma_tx_irq(int channel, void *data)
pxa_irda_set_speed(si, si->newspeed);
si->newspeed = 0;
} else {
+ int i = 64;
+
ICCR0 = 0;
pxa_irda_fir_dma_rx_start(si);
+ while ((ICSR1 & ICSR1_RNE) && i--)
+ (void)ICDR;
ICCR0 = ICCR0_ITR | ICCR0_RXE;
+
+ if (i < 0)
+ printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n");
}
netif_wake_queue(dev);
}
/* EIF(Error in FIFO/End in Frame) handler for FIR */
-static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev)
+static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev, int icsr0)
{
unsigned int len, stat, data;
@@ -350,7 +357,7 @@ static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev)
}
if (stat & ICSR1_ROR) {
printk(KERN_DEBUG "pxa_ir: fir receive overrun\n");
- si->stats.rx_frame_errors++;
+ si->stats.rx_over_errors++;
}
} else {
si->dma_rx_buff[len++] = data;
@@ -362,7 +369,15 @@ static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev)
if (stat & ICSR1_EOF) {
/* end of frame. */
- struct sk_buff *skb = alloc_skb(len+1,GFP_ATOMIC);
+ struct sk_buff *skb;
+
+ if (icsr0 & ICSR0_FRE) {
+ printk(KERN_ERR "pxa_ir: dropping erroneous frame\n");
+ si->stats.rx_dropped++;
+ return;
+ }
+
+ skb = alloc_skb(len+1,GFP_ATOMIC);
if (!skb) {
printk(KERN_ERR "pxa_ir: fir out of memory for receive skb\n");
si->stats.rx_dropped++;
@@ -392,7 +407,7 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct pxa_irda *si = netdev_priv(dev);
- int icsr0;
+ int icsr0, i = 64;
/* stop RX DMA */
DCSR(si->rxdma) &= ~DCSR_RUN;
@@ -412,13 +427,18 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id)
if (icsr0 & ICSR0_EIF) {
/* An error in FIFO occured, or there is a end of frame */
- pxa_irda_fir_irq_eif(si, dev);
+ pxa_irda_fir_irq_eif(si, dev, icsr0);
}
ICCR0 = 0;
pxa_irda_fir_dma_rx_start(si);
+ while ((ICSR1 & ICSR1_RNE) && i--)
+ (void)ICDR;
ICCR0 = ICCR0_ITR | ICCR0_RXE;
+ if (i < 0)
+ printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n");
+
return IRQ_HANDLED;
}
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 9ba21e0f27c5..8015a7c5b0c9 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -787,6 +787,12 @@ static int mv643xx_eth_open(struct net_device *dev)
unsigned int size;
int err;
+ /* Clear any pending ethernet port interrupts */
+ mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
+ mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+ /* wait for previous write to complete */
+ mv_read (MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num));
+
err = request_irq(dev->irq, mv643xx_eth_int_handler,
IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, dev);
if (err) {
@@ -875,10 +881,6 @@ static int mv643xx_eth_open(struct net_device *dev)
mv643xx_eth_rx_refill_descs(dev); /* Fill RX ring with skb's */
- /* Clear any pending ethernet port interrupts */
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
-
eth_port_start(dev);
/* Interrupt Coalescing */
@@ -1377,7 +1379,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
spin_lock_init(&mp->lock);
- port_num = pd->port_number;
+ port_num = mp->port_num = pd->port_number;
/* set default config values */
eth_port_uc_addr_get(dev, dev->dev_addr);
@@ -1409,8 +1411,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
duplex = pd->duplex;
speed = pd->speed;
- mp->port_num = port_num;
-
/* Hook up MII support for ethtool */
mp->mii.dev = dev;
mp->mii.mdio_read = mv643xx_mdio_read;
@@ -1514,9 +1514,23 @@ static int mv643xx_eth_shared_remove(struct platform_device *pdev)
return 0;
}
+static void mv643xx_eth_shutdown(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct mv643xx_private *mp = netdev_priv(dev);
+ unsigned int port_num = mp->port_num;
+
+ /* Mask all interrupts on ethernet port */
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), 0);
+ mv_read (MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
+
+ eth_port_reset(port_num);
+}
+
static struct platform_driver mv643xx_eth_driver = {
.probe = mv643xx_eth_probe,
.remove = mv643xx_eth_remove,
+ .shutdown = mv643xx_eth_shutdown,
.driver = {
.name = MV643XX_ETH_NAME,
},
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index b05dc6ed7fb7..f8efe0e70a6b 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -71,7 +71,7 @@
#include "myri10ge_mcp.h"
#include "myri10ge_mcp_gen_header.h"
-#define MYRI10GE_VERSION_STR "1.2.0"
+#define MYRI10GE_VERSION_STR "1.3.0-1.233"
MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -181,6 +181,7 @@ struct myri10ge_priv {
int intr_coal_delay;
__be32 __iomem *intr_coal_delay_ptr;
int mtrr;
+ int wc_enabled;
int wake_queue;
int stop_queue;
int down_cnt;
@@ -233,7 +234,7 @@ static int myri10ge_msi = 1; /* enable msi by default */
module_param(myri10ge_msi, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(myri10ge_msi, "Enable Message Signalled Interrupts\n");
-static int myri10ge_intr_coal_delay = 25;
+static int myri10ge_intr_coal_delay = 75;
module_param(myri10ge_intr_coal_delay, int, S_IRUGO);
MODULE_PARM_DESC(myri10ge_intr_coal_delay, "Interrupt coalescing delay\n");
@@ -278,7 +279,7 @@ static int myri10ge_fill_thresh = 256;
module_param(myri10ge_fill_thresh, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed\n");
-static int myri10ge_wcfifo = 1;
+static int myri10ge_wcfifo = 0;
module_param(myri10ge_wcfifo, int, S_IRUGO);
MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled\n");
@@ -717,6 +718,8 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
int status;
size_t bytes;
u32 len;
+ struct page *dmatest_page;
+ dma_addr_t dmatest_bus;
/* try to send a reset command to the card to see if it
* is alive */
@@ -726,6 +729,11 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
dev_err(&mgp->pdev->dev, "failed reset\n");
return -ENXIO;
}
+ dmatest_page = alloc_page(GFP_KERNEL);
+ if (!dmatest_page)
+ return -ENOMEM;
+ dmatest_bus = pci_map_page(mgp->pdev, dmatest_page, 0, PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
/* Now exchange information about interrupts */
@@ -764,8 +772,8 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
len = mgp->tx.boundary;
- cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
- cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+ cmd.data0 = MYRI10GE_LOWPART_TO_U32(dmatest_bus);
+ cmd.data1 = MYRI10GE_HIGHPART_TO_U32(dmatest_bus);
cmd.data2 = len * 0x10000;
status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0);
if (status == 0)
@@ -774,8 +782,8 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
else
dev_warn(&mgp->pdev->dev, "DMA read benchmark failed: %d\n",
status);
- cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
- cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+ cmd.data0 = MYRI10GE_LOWPART_TO_U32(dmatest_bus);
+ cmd.data1 = MYRI10GE_HIGHPART_TO_U32(dmatest_bus);
cmd.data2 = len * 0x1;
status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0);
if (status == 0)
@@ -785,8 +793,8 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
dev_warn(&mgp->pdev->dev, "DMA write benchmark failed: %d\n",
status);
- cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
- cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+ cmd.data0 = MYRI10GE_LOWPART_TO_U32(dmatest_bus);
+ cmd.data1 = MYRI10GE_HIGHPART_TO_U32(dmatest_bus);
cmd.data2 = len * 0x10001;
status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0);
if (status == 0)
@@ -796,6 +804,9 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
dev_warn(&mgp->pdev->dev,
"DMA read/write benchmark failed: %d\n", status);
+ pci_unmap_page(mgp->pdev, dmatest_bus, PAGE_SIZE, DMA_BIDIRECTIONAL);
+ put_page(dmatest_page);
+
memset(mgp->rx_done.entry, 0, bytes);
/* reset mcp/driver shared state back to 0 */
@@ -889,9 +900,7 @@ myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
/* try to refill entire ring */
while (rx->fill_cnt != (rx->cnt + rx->mask + 1)) {
idx = rx->fill_cnt & rx->mask;
-
- if ((bytes < MYRI10GE_ALLOC_SIZE / 2) &&
- (rx->page_offset + bytes <= MYRI10GE_ALLOC_SIZE)) {
+ if (rx->page_offset + bytes <= MYRI10GE_ALLOC_SIZE) {
/* we can use part of previous page */
get_page(rx->page);
} else {
@@ -922,6 +931,13 @@ myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
/* start next packet on a cacheline boundary */
rx->page_offset += SKB_DATA_ALIGN(bytes);
+
+#if MYRI10GE_ALLOC_SIZE > 4096
+ /* don't cross a 4KB boundary */
+ if ((rx->page_offset >> 12) !=
+ ((rx->page_offset + bytes - 1) >> 12))
+ rx->page_offset = (rx->page_offset + 4096) & ~4095;
+#endif
rx->fill_cnt++;
/* copy 8 descriptors to the firmware at a time */
@@ -1375,7 +1391,7 @@ myri10ge_get_ethtool_stats(struct net_device *netdev,
data[i] = ((unsigned long *)&mgp->stats)[i];
data[i++] = (unsigned int)mgp->tx.boundary;
- data[i++] = (unsigned int)(mgp->mtrr >= 0);
+ data[i++] = (unsigned int)mgp->wc_enabled;
data[i++] = (unsigned int)mgp->pdev->irq;
data[i++] = (unsigned int)mgp->msi_enabled;
data[i++] = (unsigned int)mgp->read_dma;
@@ -1456,6 +1472,8 @@ static int myri10ge_allocate_rings(struct net_device *dev)
status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_RING_SIZE, &cmd, 0);
tx_ring_size = cmd.data0;
status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RX_RING_SIZE, &cmd, 0);
+ if (status != 0)
+ return status;
rx_ring_size = cmd.data0;
tx_ring_entries = tx_ring_size / sizeof(struct mcp_kreq_ether_send);
@@ -1463,6 +1481,8 @@ static int myri10ge_allocate_rings(struct net_device *dev)
mgp->tx.mask = tx_ring_entries - 1;
mgp->rx_small.mask = mgp->rx_big.mask = rx_ring_entries - 1;
+ status = -ENOMEM;
+
/* allocate the host shadow rings */
bytes = 8 + (MYRI10GE_MAX_SEND_DESC_TSO + 4)
@@ -1735,7 +1755,7 @@ static int myri10ge_open(struct net_device *dev)
goto abort_with_irq;
}
- if (myri10ge_wcfifo && mgp->mtrr >= 0) {
+ if (myri10ge_wcfifo && mgp->wc_enabled) {
mgp->tx.wc_fifo = (u8 __iomem *) mgp->sram + MXGEFW_ETH_SEND_4;
mgp->rx_small.wc_fifo =
(u8 __iomem *) mgp->sram + MXGEFW_ETH_RECV_SMALL;
@@ -1992,10 +2012,9 @@ again:
mss = 0;
max_segments = MXGEFW_MAX_SEND_DESC;
- if (skb->len > (dev->mtu + ETH_HLEN)) {
+ if (skb_is_gso(skb)) {
mss = skb_shinfo(skb)->gso_size;
- if (mss != 0)
- max_segments = MYRI10GE_MAX_SEND_DESC_TSO;
+ max_segments = MYRI10GE_MAX_SEND_DESC_TSO;
}
if ((unlikely(avail < max_segments))) {
@@ -2468,6 +2487,12 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp)
#define PCI_DEVICE_ID_INTEL_E5000_PCIE23 0x25f7
#define PCI_DEVICE_ID_INTEL_E5000_PCIE47 0x25fa
+#define PCI_DEVICE_ID_INTEL_6300ESB_PCIEE1 0x3510
+#define PCI_DEVICE_ID_INTEL_6300ESB_PCIEE4 0x351b
+#define PCI_DEVICE_ID_INTEL_E3000_PCIE 0x2779
+#define PCI_DEVICE_ID_INTEL_E3010_PCIE 0x277a
+#define PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_FIRST 0x140
+#define PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_LAST 0x142
static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
{
@@ -2499,6 +2524,24 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
((bridge->vendor == PCI_VENDOR_ID_SERVERWORKS
&& bridge->device ==
PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE)
+ /* ServerWorks HT2100 */
+ || (bridge->vendor == PCI_VENDOR_ID_SERVERWORKS
+ && bridge->device >=
+ PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_FIRST
+ && bridge->device <=
+ PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_LAST)
+ /* All Intel E3000/E3010 PCIE ports */
+ || (bridge->vendor == PCI_VENDOR_ID_INTEL
+ && (bridge->device ==
+ PCI_DEVICE_ID_INTEL_E3000_PCIE
+ || bridge->device ==
+ PCI_DEVICE_ID_INTEL_E3010_PCIE))
+ /* All Intel 6310/6311/6321ESB PCIE ports */
+ || (bridge->vendor == PCI_VENDOR_ID_INTEL
+ && bridge->device >=
+ PCI_DEVICE_ID_INTEL_6300ESB_PCIEE1
+ && bridge->device <=
+ PCI_DEVICE_ID_INTEL_6300ESB_PCIEE4)
/* All Intel E5000 PCIE ports */
|| (bridge->vendor == PCI_VENDOR_ID_INTEL
&& bridge->device >=
@@ -2510,6 +2553,12 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
bridge->vendor, bridge->device);
mgp->tx.boundary = 4096;
mgp->fw_name = myri10ge_fw_aligned;
+ } else if (bridge &&
+ bridge->vendor == PCI_VENDOR_ID_SGI &&
+ bridge->device == 0x4002 /* TIOCE pcie-port */ ) {
+ /* this pcie bridge does not support 4K rdma request */
+ mgp->tx.boundary = 2048;
+ mgp->fw_name = myri10ge_fw_aligned;
}
} else {
if (myri10ge_force_firmware == 1) {
@@ -2830,9 +2879,12 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
mgp->board_span = pci_resource_len(pdev, 0);
mgp->iomem_base = pci_resource_start(pdev, 0);
mgp->mtrr = -1;
+ mgp->wc_enabled = 0;
#ifdef CONFIG_MTRR
mgp->mtrr = mtrr_add(mgp->iomem_base, mgp->board_span,
MTRR_TYPE_WRCOMB, 1);
+ if (mgp->mtrr >= 0)
+ mgp->wc_enabled = 1;
#endif
/* Hack. need to get rid of these magic numbers */
mgp->sram_size =
@@ -2927,7 +2979,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev_info(dev, "%s IRQ %d, tx bndry %d, fw %s, WC %s\n",
(mgp->msi_enabled ? "MSI" : "xPIC"),
netdev->irq, mgp->tx.boundary, mgp->fw_name,
- (mgp->mtrr >= 0 ? "Enabled" : "Disabled"));
+ (mgp->wc_enabled ? "Enabled" : "Disabled"));
return 0;
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index c6172a77a6d7..349b96a3ec4c 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -1712,7 +1712,7 @@ static void init_registers(struct net_device *dev)
/* Enable interrupts by setting the interrupt mask. */
writel(DEFAULT_INTR, ioaddr + IntrMask);
- writel(1, ioaddr + IntrEnable);
+ natsemi_irq_enable(dev);
writel(RxOn | TxOn, ioaddr + ChipCmd);
writel(StatsClear, ioaddr + StatsCtrl); /* Clear Stats */
@@ -2119,28 +2119,35 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
struct netdev_private *np = netdev_priv(dev);
void __iomem * ioaddr = ns_ioaddr(dev);
- if (np->hands_off)
+ /* Reading IntrStatus automatically acknowledges so don't do
+ * that while interrupts are disabled, (for example, while a
+ * poll is scheduled). */
+ if (np->hands_off || !readl(ioaddr + IntrEnable))
return IRQ_NONE;
- /* Reading automatically acknowledges. */
np->intr_status = readl(ioaddr + IntrStatus);
+ if (!np->intr_status)
+ return IRQ_NONE;
+
if (netif_msg_intr(np))
printk(KERN_DEBUG
"%s: Interrupt, status %#08x, mask %#08x.\n",
dev->name, np->intr_status,
readl(ioaddr + IntrMask));
- if (!np->intr_status)
- return IRQ_NONE;
-
prefetch(&np->rx_skbuff[np->cur_rx % RX_RING_SIZE]);
if (netif_rx_schedule_prep(dev)) {
/* Disable interrupts and register for poll */
natsemi_irq_disable(dev);
__netif_rx_schedule(dev);
- }
+ } else
+ printk(KERN_WARNING
+ "%s: Ignoring interrupt, status %#08x, mask %#08x.\n",
+ dev->name, np->intr_status,
+ readl(ioaddr + IntrMask));
+
return IRQ_HANDLED;
}
@@ -2156,6 +2163,20 @@ static int natsemi_poll(struct net_device *dev, int *budget)
int work_done = 0;
do {
+ if (netif_msg_intr(np))
+ printk(KERN_DEBUG
+ "%s: Poll, status %#08x, mask %#08x.\n",
+ dev->name, np->intr_status,
+ readl(ioaddr + IntrMask));
+
+ /* netdev_rx() may read IntrStatus again if the RX state
+ * machine falls over so do it first. */
+ if (np->intr_status &
+ (IntrRxDone | IntrRxIntr | RxStatusFIFOOver |
+ IntrRxErr | IntrRxOverrun)) {
+ netdev_rx(dev, &work_done, work_to_do);
+ }
+
if (np->intr_status &
(IntrTxDone | IntrTxIntr | IntrTxIdle | IntrTxErr)) {
spin_lock(&np->lock);
@@ -2167,12 +2188,6 @@ static int natsemi_poll(struct net_device *dev, int *budget)
if (np->intr_status & IntrAbnormalSummary)
netdev_error(dev, np->intr_status);
- if (np->intr_status &
- (IntrRxDone | IntrRxIntr | RxStatusFIFOOver |
- IntrRxErr | IntrRxOverrun)) {
- netdev_rx(dev, &work_done, work_to_do);
- }
-
*budget -= work_done;
dev->quota -= work_done;
@@ -2399,19 +2414,8 @@ static struct net_device_stats *get_stats(struct net_device *dev)
#ifdef CONFIG_NET_POLL_CONTROLLER
static void natsemi_poll_controller(struct net_device *dev)
{
- struct netdev_private *np = netdev_priv(dev);
-
disable_irq(dev->irq);
-
- /*
- * A real interrupt might have already reached us at this point
- * but NAPI might still haven't called us back. As the interrupt
- * status register is cleared by reading, we should prevent an
- * interrupt loss in this case...
- */
- if (!np->intr_status)
- intr_handler(dev->irq, dev);
-
+ intr_handler(dev->irq, dev);
enable_irq(dev->irq);
}
#endif
@@ -3071,7 +3075,7 @@ static void enable_wol_mode(struct net_device *dev, int enable_intr)
* Could be used to send a netlink message.
*/
writel(WOLPkt | LinkChange, ioaddr + IntrMask);
- writel(1, ioaddr + IntrEnable);
+ natsemi_irq_enable(dev);
}
}
@@ -3202,7 +3206,7 @@ static int natsemi_suspend (struct pci_dev *pdev, pm_message_t state)
disable_irq(dev->irq);
spin_lock_irq(&np->lock);
- writel(0, ioaddr + IntrEnable);
+ natsemi_irq_disable(dev);
np->hands_off = 1;
natsemi_stop_rxtx(dev);
netif_stop_queue(dev);
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 81742e4e5610..dd8ce35332fe 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -232,6 +232,7 @@ enum {
#define MPORT_SINGLE_FUNCTION_MODE 0x1111
extern unsigned long long netxen_dma_mask;
+extern unsigned long last_schedule_time;
/*
* NetXen host-peg signal message structure
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
index 986ef98db229..ee1b5a24cbe7 100644
--- a/drivers/net/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/netxen/netxen_nic_ethtool.c
@@ -462,6 +462,7 @@ netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
}
printk(KERN_INFO "%s: flash unlocked. \n",
netxen_nic_driver_name);
+ last_schedule_time = jiffies;
ret = netxen_flash_erase_secondary(adapter);
if (ret != FLASH_SUCCESS) {
printk(KERN_ERR "%s: Flash erase failed.\n",
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index a2877f33fa85..6537574a9cda 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -228,7 +228,7 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
&adapter->ctx_desc_pdev);
printk("ctx_desc_phys_addr: 0x%llx\n",
- (u64) adapter->ctx_desc_phys_addr);
+ (unsigned long long) adapter->ctx_desc_phys_addr);
if (addr == NULL) {
DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
err = -ENOMEM;
@@ -247,7 +247,8 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
adapter->max_tx_desc_count,
(dma_addr_t *) & hw->cmd_desc_phys_addr,
&adapter->ahw.cmd_desc_pdev);
- printk("cmd_desc_phys_addr: 0x%llx\n", (u64) hw->cmd_desc_phys_addr);
+ printk("cmd_desc_phys_addr: 0x%llx\n",
+ (unsigned long long) hw->cmd_desc_phys_addr);
if (addr == NULL) {
DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
@@ -821,7 +822,10 @@ int netxen_nic_set_mtu_xgb(struct netxen_port *port, int new_mtu)
{
struct netxen_adapter *adapter = port->adapter;
new_mtu += NETXEN_NIU_HDRSIZE + NETXEN_NIU_TLRSIZE;
- netxen_nic_write_w0(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE, new_mtu);
+ if (port->portnum == 0)
+ netxen_nic_write_w0(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE, new_mtu);
+ else if (port->portnum == 1)
+ netxen_nic_write_w0(adapter, NETXEN_NIU_XG1_MAX_FRAME_SIZE, new_mtu);
return 0;
}
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 586d32b676af..eff965dc5fff 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -42,6 +42,8 @@ struct crb_addr_pair {
u32 data;
};
+unsigned long last_schedule_time;
+
#define NETXEN_MAX_CRB_XFORM 60
static unsigned int crb_addr_xform[NETXEN_MAX_CRB_XFORM];
#define NETXEN_ADDR_ERROR (0xffffffff)
@@ -404,9 +406,14 @@ static inline int do_rom_fast_write(struct netxen_adapter *adapter, int addr,
static inline int
do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp)
{
+ if (jiffies > (last_schedule_time + (8 * HZ))) {
+ last_schedule_time = jiffies;
+ schedule();
+ }
+
netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
- udelay(70); /* prevent bursting on CRB */
+ udelay(100); /* prevent bursting on CRB */
netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb);
if (netxen_wait_rom_done(adapter)) {
@@ -415,7 +422,7 @@ do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp)
}
/* reset abyte_cnt and dummy_byte_cnt */
netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
- udelay(70); /* prevent bursting on CRB */
+ udelay(100); /* prevent bursting on CRB */
netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
*valp = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_ROM_RDATA);
@@ -431,6 +438,7 @@ do_rom_fast_read_words(struct netxen_adapter *adapter, int addr,
for (addridx = addr; addridx < (addr + size); addridx += 4) {
ret = do_rom_fast_read(adapter, addridx, (int *)bytes);
+ *(int *)bytes = cpu_to_le32(*(int *)bytes);
if (ret != 0)
break;
bytes += 4;
@@ -490,7 +498,7 @@ static inline int do_rom_fast_write_words(struct netxen_adapter *adapter,
int timeout = 0;
int data;
- data = *(u32*)bytes;
+ data = le32_to_cpu((*(u32*)bytes));
ret = do_rom_fast_write(adapter, addridx, data);
if (ret < 0)
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
index 00ca0fdb837b..6ca4e4fa6b88 100644
--- a/drivers/net/pci-skeleton.c
+++ b/drivers/net/pci-skeleton.c
@@ -710,8 +710,8 @@ match:
tp->chipset,
rtl_chip_info[tp->chipset].name);
- i = register_netdev (dev);
- if (i)
+ rc = register_netdev (dev);
+ if (rc)
goto err_out_unmap;
DPRINTK ("EXIT, returning 0\n");
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index a956a51d284f..1060154ae750 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -138,7 +138,7 @@ static const struct ethtool_ops netdev_ethtool_ops = {
======================================================================*/
-static int ibmtr_attach(struct pcmcia_device *link)
+static int __devinit ibmtr_attach(struct pcmcia_device *link)
{
ibmtr_dev_t *info;
struct net_device *dev;
@@ -217,7 +217,7 @@ static void ibmtr_detach(struct pcmcia_device *link)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static int ibmtr_config(struct pcmcia_device *link)
+static int __devinit ibmtr_config(struct pcmcia_device *link)
{
ibmtr_dev_t *info = link->priv;
struct net_device *dev = info->dev;
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 11b575f89856..ef58e4128782 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -2544,6 +2544,9 @@ static void ppp_destroy_interface(struct ppp *ppp)
ppp->active_filter = NULL;
#endif /* CONFIG_PPP_FILTER */
+ if (ppp->xmit_pending)
+ kfree_skb(ppp->xmit_pending);
+
kfree(ppp);
}
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index d3f65dab306c..a8246eb2f8d9 100755
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -1691,6 +1691,27 @@ static int ql_populate_free_queue(struct ql3_adapter *qdev)
/*
* Caller holds hw_lock.
*/
+static void ql_update_small_bufq_prod_index(struct ql3_adapter *qdev)
+{
+ struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+ if (qdev->small_buf_release_cnt >= 16) {
+ while (qdev->small_buf_release_cnt >= 16) {
+ qdev->small_buf_q_producer_index++;
+
+ if (qdev->small_buf_q_producer_index ==
+ NUM_SBUFQ_ENTRIES)
+ qdev->small_buf_q_producer_index = 0;
+ qdev->small_buf_release_cnt -= 8;
+ }
+ wmb();
+ writel(qdev->small_buf_q_producer_index,
+ &port_regs->CommonRegs.rxSmallQProducerIndex);
+ }
+}
+
+/*
+ * Caller holds hw_lock.
+ */
static void ql_update_lrg_bufq_prod_index(struct ql3_adapter *qdev)
{
struct bufq_addr_element *lrg_buf_q_ele;
@@ -1732,13 +1753,10 @@ static void ql_update_lrg_bufq_prod_index(struct ql3_adapter *qdev)
lrg_buf_q_ele = qdev->lrg_buf_q_virt_addr;
}
}
-
+ wmb();
qdev->lrg_buf_next_free = lrg_buf_q_ele;
-
- ql_write_common_reg(qdev,
- &port_regs->CommonRegs.
- rxLargeQProducerIndex,
- qdev->lrg_buf_q_producer_index);
+ writel(qdev->lrg_buf_q_producer_index,
+ &port_regs->CommonRegs.rxLargeQProducerIndex);
}
}
@@ -1915,17 +1933,18 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev,
u16 checksum = le16_to_cpu(ib_ip_rsp_ptr->checksum);
if (checksum &
(IB_IP_IOCB_RSP_3032_ICE |
- IB_IP_IOCB_RSP_3032_CE |
- IB_IP_IOCB_RSP_3032_NUC)) {
+ IB_IP_IOCB_RSP_3032_CE)) {
printk(KERN_ERR
"%s: Bad checksum for this %s packet, checksum = %x.\n",
__func__,
((checksum &
IB_IP_IOCB_RSP_3032_TCP) ? "TCP" :
"UDP"),checksum);
- } else if (checksum & IB_IP_IOCB_RSP_3032_TCP) {
+ } else if ((checksum & IB_IP_IOCB_RSP_3032_TCP) ||
+ (checksum & IB_IP_IOCB_RSP_3032_UDP &&
+ !(checksum & IB_IP_IOCB_RSP_3032_NUC))) {
skb2->ip_summed = CHECKSUM_UNNECESSARY;
- }
+ }
}
skb2->dev = qdev->ndev;
skb2->protocol = eth_type_trans(skb2, qdev->ndev);
@@ -1944,16 +1963,12 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev,
static int ql_tx_rx_clean(struct ql3_adapter *qdev,
int *tx_cleaned, int *rx_cleaned, int work_to_do)
{
- struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
struct net_rsp_iocb *net_rsp;
struct net_device *ndev = qdev->ndev;
- unsigned long hw_flags;
int work_done = 0;
- u32 rsp_producer_index = le32_to_cpu(*(qdev->prsp_producer_index));
-
/* While there are entries in the completion queue. */
- while ((rsp_producer_index !=
+ while ((le32_to_cpu(*(qdev->prsp_producer_index)) !=
qdev->rsp_consumer_index) && (work_done < work_to_do)) {
net_rsp = qdev->rsp_current;
@@ -2009,33 +2024,7 @@ static int ql_tx_rx_clean(struct ql3_adapter *qdev,
work_done = *tx_cleaned + *rx_cleaned;
}
- if(work_done) {
- spin_lock_irqsave(&qdev->hw_lock, hw_flags);
-
- ql_update_lrg_bufq_prod_index(qdev);
-
- if (qdev->small_buf_release_cnt >= 16) {
- while (qdev->small_buf_release_cnt >= 16) {
- qdev->small_buf_q_producer_index++;
-
- if (qdev->small_buf_q_producer_index ==
- NUM_SBUFQ_ENTRIES)
- qdev->small_buf_q_producer_index = 0;
- qdev->small_buf_release_cnt -= 8;
- }
-
- wmb();
- ql_write_common_reg(qdev,
- &port_regs->CommonRegs.
- rxSmallQProducerIndex,
- qdev->small_buf_q_producer_index);
-
- }
-
- spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
- }
-
- return *tx_cleaned + *rx_cleaned;
+ return work_done;
}
static int ql_poll(struct net_device *ndev, int *budget)
@@ -2059,9 +2048,10 @@ quit_polling:
netif_rx_complete(ndev);
spin_lock_irqsave(&qdev->hw_lock, hw_flags);
- ql_write_common_reg(qdev,
- &port_regs->CommonRegs.rspQConsumerIndex,
- qdev->rsp_consumer_index);
+ ql_update_small_bufq_prod_index(qdev);
+ ql_update_lrg_bufq_prod_index(qdev);
+ writel(qdev->rsp_consumer_index,
+ &port_regs->CommonRegs.rspQConsumerIndex);
spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
ql_enable_interrupts(qdev);
@@ -2217,12 +2207,7 @@ static int ql_send_map(struct ql3_adapter *qdev,
int seg_cnt, seg = 0;
int frag_cnt = (int)skb_shinfo(skb)->nr_frags;
- seg_cnt = tx_cb->seg_count = ql_get_seg_count(qdev,
- (skb_shinfo(skb)->nr_frags));
- if(seg_cnt == -1) {
- printk(KERN_ERR PFX"%s: invalid segment count!\n",__func__);
- return NETDEV_TX_BUSY;
- }
+ seg_cnt = tx_cb->seg_count;
/*
* Map the skb buffer first.
*/
@@ -2278,7 +2263,7 @@ static int ql_send_map(struct ql3_adapter *qdev,
pci_unmap_addr_set(&tx_cb->map[seg], mapaddr,
map);
pci_unmap_len_set(&tx_cb->map[seg], maplen,
- len);
+ sizeof(struct oal));
oal_entry = (struct oal_entry *)oal;
oal++;
seg++;
@@ -2380,6 +2365,7 @@ static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev)
}
mac_iocb_ptr = tx_cb->queue_entry;
+ memset((void *)mac_iocb_ptr, 0, sizeof(struct ob_mac_iocb_req));
mac_iocb_ptr->opcode = qdev->mac_ob_opcode;
mac_iocb_ptr->flags = OB_MAC_IOCB_REQ_X;
mac_iocb_ptr->flags |= qdev->mb_bit_mask;
@@ -3054,15 +3040,6 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev)
goto out;
}
- if (qdev->mac_index)
- ql_write_page0_reg(qdev,
- &port_regs->mac1MaxFrameLengthReg,
- qdev->max_frame_size);
- else
- ql_write_page0_reg(qdev,
- &port_regs->mac0MaxFrameLengthReg,
- qdev->max_frame_size);
-
value = qdev->nvram_data.tcpMaxWindowSize;
ql_write_page0_reg(qdev, &port_regs->tcpMaxWindow, value);
@@ -3082,6 +3059,14 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev)
ql_sem_unlock(qdev, QL_FLASH_SEM_MASK);
}
+ if (qdev->mac_index)
+ ql_write_page0_reg(qdev,
+ &port_regs->mac1MaxFrameLengthReg,
+ qdev->max_frame_size);
+ else
+ ql_write_page0_reg(qdev,
+ &port_regs->mac0MaxFrameLengthReg,
+ qdev->max_frame_size);
if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK,
(QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
@@ -3152,7 +3137,8 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev)
if (qdev->device_id == QL3032_DEVICE_ID) {
value =
(QL3032_PORT_CONTROL_EF | QL3032_PORT_CONTROL_KIE |
- QL3032_PORT_CONTROL_EIv6 | QL3032_PORT_CONTROL_EIv4);
+ QL3032_PORT_CONTROL_EIv6 | QL3032_PORT_CONTROL_EIv4 |
+ QL3032_PORT_CONTROL_ET);
ql_write_page0_reg(qdev, &port_regs->functionControl,
((value << 16) | value));
} else {
diff --git a/drivers/net/qla3xxx.h b/drivers/net/qla3xxx.h
index 34cd6580fd07..0203f88f0544 100755
--- a/drivers/net/qla3xxx.h
+++ b/drivers/net/qla3xxx.h
@@ -1014,8 +1014,7 @@ struct eeprom_data {
/* Transmit and Receive Buffers */
#define NUM_LBUFQ_ENTRIES 128
-#define JUMBO_NUM_LBUFQ_ENTRIES \
-(NUM_LBUFQ_ENTRIES/(JUMBO_MTU_SIZE/NORMAL_MTU_SIZE))
+#define JUMBO_NUM_LBUFQ_ENTRIES 32
#define NUM_SBUFQ_ENTRIES 64
#define QL_SMALL_BUFFER_SIZE 32
#define QL_ADDR_ELE_PER_BUFQ_ENTRY \
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 15d954e50cae..6a77b8a92245 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -66,6 +66,7 @@ VERSION 2.2LK <2005/01/25>
#include <linux/init.h>
#include <linux/dma-mapping.h>
+#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -486,6 +487,7 @@ static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *,
void __iomem *);
static int rtl8169_change_mtu(struct net_device *dev, int new_mtu);
static void rtl8169_down(struct net_device *dev);
+static void rtl8169_rx_clear(struct rtl8169_private *tp);
#ifdef CONFIG_R8169_NAPI
static int rtl8169_poll(struct net_device *dev, int *budget);
@@ -572,8 +574,8 @@ static void rtl8169_xmii_reset_enable(void __iomem *ioaddr)
{
unsigned int val;
- mdio_write(ioaddr, MII_BMCR, BMCR_RESET);
- val = mdio_read(ioaddr, MII_BMCR);
+ val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET;
+ mdio_write(ioaddr, MII_BMCR, val & 0xffff);
}
static void rtl8169_check_link_status(struct net_device *dev,
@@ -1368,11 +1370,7 @@ static inline void rtl8169_request_timer(struct net_device *dev)
(tp->phy_version >= RTL_GIGA_PHY_VER_H))
return;
- init_timer(timer);
- timer->expires = jiffies + RTL8169_PHY_TIMEOUT;
- timer->data = (unsigned long)(dev);
- timer->function = rtl8169_phy_timer;
- add_timer(timer);
+ mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT);
}
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1685,6 +1683,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->mmio_addr = ioaddr;
tp->align = rtl_cfg_info[ent->driver_data].align;
+ init_timer(&tp->timer);
+ tp->timer.data = (unsigned long) dev;
+ tp->timer.function = rtl8169_phy_timer;
+
spin_lock_init(&tp->lock);
rc = register_netdev(dev);
@@ -1751,16 +1753,10 @@ static int rtl8169_open(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
struct pci_dev *pdev = tp->pci_dev;
- int retval;
-
- rtl8169_set_rxbufsize(tp, dev);
+ int retval = -ENOMEM;
- retval =
- request_irq(dev->irq, rtl8169_interrupt, IRQF_SHARED, dev->name, dev);
- if (retval < 0)
- goto out;
- retval = -ENOMEM;
+ rtl8169_set_rxbufsize(tp, dev);
/*
* Rx and Tx desscriptors needs 256 bytes alignment.
@@ -1769,19 +1765,26 @@ static int rtl8169_open(struct net_device *dev)
tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES,
&tp->TxPhyAddr);
if (!tp->TxDescArray)
- goto err_free_irq;
+ goto out;
tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES,
&tp->RxPhyAddr);
if (!tp->RxDescArray)
- goto err_free_tx;
+ goto err_free_tx_0;
retval = rtl8169_init_ring(dev);
if (retval < 0)
- goto err_free_rx;
+ goto err_free_rx_1;
INIT_DELAYED_WORK(&tp->task, NULL);
+ smp_mb();
+
+ retval = request_irq(dev->irq, rtl8169_interrupt, IRQF_SHARED,
+ dev->name, dev);
+ if (retval < 0)
+ goto err_release_ring_2;
+
rtl8169_hw_start(dev);
rtl8169_request_timer(dev);
@@ -1790,14 +1793,14 @@ static int rtl8169_open(struct net_device *dev)
out:
return retval;
-err_free_rx:
+err_release_ring_2:
+ rtl8169_rx_clear(tp);
+err_free_rx_1:
pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,
tp->RxPhyAddr);
-err_free_tx:
+err_free_tx_0:
pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray,
tp->TxPhyAddr);
-err_free_irq:
- free_irq(dev->irq, dev);
goto out;
}
@@ -2887,7 +2890,7 @@ static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state)
void __iomem *ioaddr = tp->mmio_addr;
if (!netif_running(dev))
- goto out;
+ goto out_pci_suspend;
netif_device_detach(dev);
netif_stop_queue(dev);
@@ -2901,10 +2904,11 @@ static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state)
spin_unlock_irq(&tp->lock);
+out_pci_suspend:
pci_save_state(pdev);
pci_enable_wake(pdev, pci_choose_state(pdev, state), tp->wol_enabled);
pci_set_power_state(pdev, pci_choose_state(pdev, state));
-out:
+
return 0;
}
@@ -2912,15 +2916,15 @@ static int rtl8169_resume(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+ pci_enable_wake(pdev, PCI_D0, 0);
+
if (!netif_running(dev))
goto out;
netif_device_attach(dev);
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
- pci_enable_wake(pdev, PCI_D0, 0);
-
rtl8169_schedule_work(dev, rtl8169_reset_task);
out:
return 0;
diff --git a/drivers/net/saa9730.c b/drivers/net/saa9730.c
index b269513cde45..143958f1ef0a 100644
--- a/drivers/net/saa9730.c
+++ b/drivers/net/saa9730.c
@@ -64,37 +64,37 @@ static unsigned int pci_irq_line;
static void evm_saa9730_enable_lan_int(struct lan_saa9730_private *lp)
{
- outl(readl(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT,
- &lp->evm_saa9730_regs->InterruptBlock1);
- outl(readl(&lp->evm_saa9730_regs->InterruptStatus1) | EVM_LAN_INT,
- &lp->evm_saa9730_regs->InterruptStatus1);
- outl(readl(&lp->evm_saa9730_regs->InterruptEnable1) | EVM_LAN_INT |
- EVM_MASTER_EN, &lp->evm_saa9730_regs->InterruptEnable1);
+ writel(readl(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT,
+ &lp->evm_saa9730_regs->InterruptBlock1);
+ writel(readl(&lp->evm_saa9730_regs->InterruptStatus1) | EVM_LAN_INT,
+ &lp->evm_saa9730_regs->InterruptStatus1);
+ writel(readl(&lp->evm_saa9730_regs->InterruptEnable1) | EVM_LAN_INT |
+ EVM_MASTER_EN, &lp->evm_saa9730_regs->InterruptEnable1);
}
static void evm_saa9730_disable_lan_int(struct lan_saa9730_private *lp)
{
- outl(readl(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT,
- &lp->evm_saa9730_regs->InterruptBlock1);
- outl(readl(&lp->evm_saa9730_regs->InterruptEnable1) & ~EVM_LAN_INT,
- &lp->evm_saa9730_regs->InterruptEnable1);
+ writel(readl(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT,
+ &lp->evm_saa9730_regs->InterruptBlock1);
+ writel(readl(&lp->evm_saa9730_regs->InterruptEnable1) & ~EVM_LAN_INT,
+ &lp->evm_saa9730_regs->InterruptEnable1);
}
static void evm_saa9730_clear_lan_int(struct lan_saa9730_private *lp)
{
- outl(EVM_LAN_INT, &lp->evm_saa9730_regs->InterruptStatus1);
+ writel(EVM_LAN_INT, &lp->evm_saa9730_regs->InterruptStatus1);
}
static void evm_saa9730_block_lan_int(struct lan_saa9730_private *lp)
{
- outl(readl(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT,
- &lp->evm_saa9730_regs->InterruptBlock1);
+ writel(readl(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT,
+ &lp->evm_saa9730_regs->InterruptBlock1);
}
static void evm_saa9730_unblock_lan_int(struct lan_saa9730_private *lp)
{
- outl(readl(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT,
- &lp->evm_saa9730_regs->InterruptBlock1);
+ writel(readl(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT,
+ &lp->evm_saa9730_regs->InterruptBlock1);
}
static void __attribute_used__ show_saa9730_regs(struct lan_saa9730_private *lp)
@@ -147,7 +147,7 @@ static void __attribute_used__ show_saa9730_regs(struct lan_saa9730_private *lp)
printk("lp->lan_saa9730_regs->RxStatus = %x\n",
readl(&lp->lan_saa9730_regs->RxStatus));
for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) {
- outl(i, &lp->lan_saa9730_regs->CamAddress);
+ writel(i, &lp->lan_saa9730_regs->CamAddress);
printk("lp->lan_saa9730_regs->CamData = %x\n",
readl(&lp->lan_saa9730_regs->CamData));
}
@@ -288,28 +288,27 @@ static int lan_saa9730_allocate_buffers(struct pci_dev *pdev,
* Set rx buffer A and rx buffer B to point to the first two buffer
* spaces.
*/
- outl(lp->dma_addr + rxoffset,
- &lp->lan_saa9730_regs->RxBuffA);
- outl(lp->dma_addr + rxoffset +
- LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_RCV_Q_SIZE,
- &lp->lan_saa9730_regs->RxBuffB);
+ writel(lp->dma_addr + rxoffset, &lp->lan_saa9730_regs->RxBuffA);
+ writel(lp->dma_addr + rxoffset +
+ LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_RCV_Q_SIZE,
+ &lp->lan_saa9730_regs->RxBuffB);
/*
* Set txm_buf_a and txm_buf_b to point to the first two buffer
* space
*/
- outl(lp->dma_addr + txoffset,
- &lp->lan_saa9730_regs->TxBuffA);
- outl(lp->dma_addr + txoffset +
- LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_TXM_Q_SIZE,
- &lp->lan_saa9730_regs->TxBuffB);
+ writel(lp->dma_addr + txoffset,
+ &lp->lan_saa9730_regs->TxBuffA);
+ writel(lp->dma_addr + txoffset +
+ LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_TXM_Q_SIZE,
+ &lp->lan_saa9730_regs->TxBuffB);
/* Set packet number */
- outl((lp->DmaRcvPackets << PK_COUNT_RX_A_SHF) |
- (lp->DmaRcvPackets << PK_COUNT_RX_B_SHF) |
- (lp->DmaTxmPackets << PK_COUNT_TX_A_SHF) |
- (lp->DmaTxmPackets << PK_COUNT_TX_B_SHF),
- &lp->lan_saa9730_regs->PacketCount);
+ writel((lp->DmaRcvPackets << PK_COUNT_RX_A_SHF) |
+ (lp->DmaRcvPackets << PK_COUNT_RX_B_SHF) |
+ (lp->DmaTxmPackets << PK_COUNT_TX_A_SHF) |
+ (lp->DmaTxmPackets << PK_COUNT_TX_B_SHF),
+ &lp->lan_saa9730_regs->PacketCount);
return 0;
@@ -326,10 +325,10 @@ static int lan_saa9730_cam_load(struct lan_saa9730_private *lp)
for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) {
/* First set address to where data is written */
- outl(i, &lp->lan_saa9730_regs->CamAddress);
- outl((NetworkAddress[0] << 24) | (NetworkAddress[1] << 16)
- | (NetworkAddress[2] << 8) | NetworkAddress[3],
- &lp->lan_saa9730_regs->CamData);
+ writel(i, &lp->lan_saa9730_regs->CamAddress);
+ writel((NetworkAddress[0] << 24) | (NetworkAddress[1] << 16) |
+ (NetworkAddress[2] << 8) | NetworkAddress[3],
+ &lp->lan_saa9730_regs->CamData);
NetworkAddress += 4;
}
return 0;
@@ -365,8 +364,8 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp)
}
/* Now set the control and address register. */
- outl(MD_CA_BUSY | PHY_STATUS | PHY_ADDRESS << MD_CA_PHY_SHF,
- &lp->lan_saa9730_regs->StationMgmtCtl);
+ writel(MD_CA_BUSY | PHY_STATUS | PHY_ADDRESS << MD_CA_PHY_SHF,
+ &lp->lan_saa9730_regs->StationMgmtCtl);
/* check link status, spin here till station is not busy */
i = 0;
@@ -391,23 +390,23 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp)
/* Link is down, reset the PHY first. */
/* set PHY address = 'CONTROL' */
- outl(PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR | PHY_CONTROL,
- &lp->lan_saa9730_regs->StationMgmtCtl);
+ writel(PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR | PHY_CONTROL,
+ &lp->lan_saa9730_regs->StationMgmtCtl);
/* Wait for 1 ms. */
mdelay(1);
/* set 'CONTROL' = force reset and renegotiate */
- outl(PHY_CONTROL_RESET | PHY_CONTROL_AUTO_NEG |
- PHY_CONTROL_RESTART_AUTO_NEG,
- &lp->lan_saa9730_regs->StationMgmtData);
+ writel(PHY_CONTROL_RESET | PHY_CONTROL_AUTO_NEG |
+ PHY_CONTROL_RESTART_AUTO_NEG,
+ &lp->lan_saa9730_regs->StationMgmtData);
/* Wait for 50 ms. */
mdelay(50);
/* set 'BUSY' to start operation */
- outl(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR |
- PHY_CONTROL, &lp->lan_saa9730_regs->StationMgmtCtl);
+ writel(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR |
+ PHY_CONTROL, &lp->lan_saa9730_regs->StationMgmtCtl);
/* await completion */
i = 0;
@@ -427,9 +426,9 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp)
for (l = 0; l < 2; l++) {
/* set PHY address = 'STATUS' */
- outl(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF |
- PHY_STATUS,
- &lp->lan_saa9730_regs->StationMgmtCtl);
+ writel(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF |
+ PHY_STATUS,
+ &lp->lan_saa9730_regs->StationMgmtCtl);
/* await completion */
i = 0;
@@ -462,35 +461,35 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp)
static int lan_saa9730_control_init(struct lan_saa9730_private *lp)
{
/* Initialize DMA control register. */
- outl((LANMB_ANY << DMA_CTL_MAX_XFER_SHF) |
- (LANEND_LITTLE << DMA_CTL_ENDIAN_SHF) |
- (LAN_SAA9730_RCV_Q_INT_THRESHOLD << DMA_CTL_RX_INT_COUNT_SHF)
- | DMA_CTL_RX_INT_TO_EN | DMA_CTL_RX_INT_EN |
- DMA_CTL_MAC_RX_INT_EN | DMA_CTL_MAC_TX_INT_EN,
- &lp->lan_saa9730_regs->LanDmaCtl);
+ writel((LANMB_ANY << DMA_CTL_MAX_XFER_SHF) |
+ (LANEND_LITTLE << DMA_CTL_ENDIAN_SHF) |
+ (LAN_SAA9730_RCV_Q_INT_THRESHOLD << DMA_CTL_RX_INT_COUNT_SHF)
+ | DMA_CTL_RX_INT_TO_EN | DMA_CTL_RX_INT_EN |
+ DMA_CTL_MAC_RX_INT_EN | DMA_CTL_MAC_TX_INT_EN,
+ &lp->lan_saa9730_regs->LanDmaCtl);
/* Initial MAC control register. */
- outl((MACCM_MII << MAC_CONTROL_CONN_SHF) | MAC_CONTROL_FULL_DUP,
- &lp->lan_saa9730_regs->MacCtl);
+ writel((MACCM_MII << MAC_CONTROL_CONN_SHF) | MAC_CONTROL_FULL_DUP,
+ &lp->lan_saa9730_regs->MacCtl);
/* Initialize CAM control register. */
- outl(CAM_CONTROL_COMP_EN | CAM_CONTROL_BROAD_ACC,
- &lp->lan_saa9730_regs->CamCtl);
+ writel(CAM_CONTROL_COMP_EN | CAM_CONTROL_BROAD_ACC,
+ &lp->lan_saa9730_regs->CamCtl);
/*
* Initialize CAM enable register, only turn on first entry, should
* contain own addr.
*/
- outl(0x0001, &lp->lan_saa9730_regs->CamEnable);
+ writel(0x0001, &lp->lan_saa9730_regs->CamEnable);
/* Initialize Tx control register */
- outl(TX_CTL_EN_COMP, &lp->lan_saa9730_regs->TxCtl);
+ writel(TX_CTL_EN_COMP, &lp->lan_saa9730_regs->TxCtl);
/* Initialize Rcv control register */
- outl(RX_CTL_STRIP_CRC, &lp->lan_saa9730_regs->RxCtl);
+ writel(RX_CTL_STRIP_CRC, &lp->lan_saa9730_regs->RxCtl);
/* Reset DMA engine */
- outl(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest);
+ writel(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest);
return 0;
}
@@ -500,14 +499,14 @@ static int lan_saa9730_stop(struct lan_saa9730_private *lp)
int i;
/* Stop DMA first */
- outl(readl(&lp->lan_saa9730_regs->LanDmaCtl) &
- ~(DMA_CTL_EN_TX_DMA | DMA_CTL_EN_RX_DMA),
- &lp->lan_saa9730_regs->LanDmaCtl);
+ writel(readl(&lp->lan_saa9730_regs->LanDmaCtl) &
+ ~(DMA_CTL_EN_TX_DMA | DMA_CTL_EN_RX_DMA),
+ &lp->lan_saa9730_regs->LanDmaCtl);
/* Set the SW Reset bits in DMA and MAC control registers */
- outl(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest);
- outl(readl(&lp->lan_saa9730_regs->MacCtl) | MAC_CONTROL_RESET,
- &lp->lan_saa9730_regs->MacCtl);
+ writel(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest);
+ writel(readl(&lp->lan_saa9730_regs->MacCtl) | MAC_CONTROL_RESET,
+ &lp->lan_saa9730_regs->MacCtl);
/*
* Wait for MAC reset to have finished. The reset bit is auto cleared
@@ -532,8 +531,8 @@ static int lan_saa9730_dma_init(struct lan_saa9730_private *lp)
/* Stop lan controller. */
lan_saa9730_stop(lp);
- outl(LAN_SAA9730_DEFAULT_TIME_OUT_CNT,
- &lp->lan_saa9730_regs->Timeout);
+ writel(LAN_SAA9730_DEFAULT_TIME_OUT_CNT,
+ &lp->lan_saa9730_regs->Timeout);
return 0;
}
@@ -552,19 +551,19 @@ static int lan_saa9730_start(struct lan_saa9730_private *lp)
lp->PendingTxmPacketIndex = 0;
lp->PendingTxmBufferIndex = 0;
- outl(readl(&lp->lan_saa9730_regs->LanDmaCtl) | DMA_CTL_EN_TX_DMA |
- DMA_CTL_EN_RX_DMA, &lp->lan_saa9730_regs->LanDmaCtl);
+ writel(readl(&lp->lan_saa9730_regs->LanDmaCtl) | DMA_CTL_EN_TX_DMA |
+ DMA_CTL_EN_RX_DMA, &lp->lan_saa9730_regs->LanDmaCtl);
/* For Tx, turn on MAC then DMA */
- outl(readl(&lp->lan_saa9730_regs->TxCtl) | TX_CTL_TX_EN,
- &lp->lan_saa9730_regs->TxCtl);
+ writel(readl(&lp->lan_saa9730_regs->TxCtl) | TX_CTL_TX_EN,
+ &lp->lan_saa9730_regs->TxCtl);
/* For Rx, turn on DMA then MAC */
- outl(readl(&lp->lan_saa9730_regs->RxCtl) | RX_CTL_RX_EN,
- &lp->lan_saa9730_regs->RxCtl);
+ writel(readl(&lp->lan_saa9730_regs->RxCtl) | RX_CTL_RX_EN,
+ &lp->lan_saa9730_regs->RxCtl);
/* Set Ok2Use to let hardware own the buffers. */
- outl(OK2USE_RX_A | OK2USE_RX_B, &lp->lan_saa9730_regs->Ok2Use);
+ writel(OK2USE_RX_A | OK2USE_RX_B, &lp->lan_saa9730_regs->Ok2Use);
return 0;
}
@@ -587,7 +586,7 @@ static int lan_saa9730_tx(struct net_device *dev)
printk("lan_saa9730_tx interrupt\n");
/* Clear interrupt. */
- outl(DMA_STATUS_MAC_TX_INT, &lp->lan_saa9730_regs->DmaStatus);
+ writel(DMA_STATUS_MAC_TX_INT, &lp->lan_saa9730_regs->DmaStatus);
while (1) {
pPacket = lp->TxmBuffer[lp->PendingTxmBufferIndex]
@@ -660,8 +659,8 @@ static int lan_saa9730_rx(struct net_device *dev)
printk("lan_saa9730_rx interrupt\n");
/* Clear receive interrupts. */
- outl(DMA_STATUS_MAC_RX_INT | DMA_STATUS_RX_INT |
- DMA_STATUS_RX_TO_INT, &lp->lan_saa9730_regs->DmaStatus);
+ writel(DMA_STATUS_MAC_RX_INT | DMA_STATUS_RX_INT |
+ DMA_STATUS_RX_TO_INT, &lp->lan_saa9730_regs->DmaStatus);
/* Address next packet */
BufferIndex = lp->NextRcvBufferIndex;
@@ -725,8 +724,8 @@ static int lan_saa9730_rx(struct net_device *dev)
*pPacket = cpu_to_le32(RXSF_READY << RX_STAT_CTL_OWNER_SHF);
/* Make sure A or B is available to hardware as appropriate. */
- outl(BufferIndex ? OK2USE_RX_B : OK2USE_RX_A,
- &lp->lan_saa9730_regs->Ok2Use);
+ writel(BufferIndex ? OK2USE_RX_B : OK2USE_RX_A,
+ &lp->lan_saa9730_regs->Ok2Use);
/* Go to next packet in sequence. */
lp->NextRcvPacketIndex++;
@@ -844,8 +843,8 @@ static int lan_saa9730_write(struct lan_saa9730_private *lp,
(len << TX_STAT_CTL_LENGTH_SHF));
/* Make sure A or B is available to hardware as appropriate. */
- outl(BufferIndex ? OK2USE_TX_B : OK2USE_TX_A,
- &lp->lan_saa9730_regs->Ok2Use);
+ writel(BufferIndex ? OK2USE_TX_B : OK2USE_TX_A,
+ &lp->lan_saa9730_regs->Ok2Use);
return 0;
}
@@ -938,15 +937,15 @@ static void lan_saa9730_set_multicast(struct net_device *dev)
if (dev->flags & IFF_PROMISC) {
/* accept all packets */
- outl(CAM_CONTROL_COMP_EN | CAM_CONTROL_STATION_ACC |
- CAM_CONTROL_GROUP_ACC | CAM_CONTROL_BROAD_ACC,
- &lp->lan_saa9730_regs->CamCtl);
+ writel(CAM_CONTROL_COMP_EN | CAM_CONTROL_STATION_ACC |
+ CAM_CONTROL_GROUP_ACC | CAM_CONTROL_BROAD_ACC,
+ &lp->lan_saa9730_regs->CamCtl);
} else {
if (dev->flags & IFF_ALLMULTI) {
/* accept all multicast packets */
- outl(CAM_CONTROL_COMP_EN | CAM_CONTROL_GROUP_ACC |
- CAM_CONTROL_BROAD_ACC,
- &lp->lan_saa9730_regs->CamCtl);
+ writel(CAM_CONTROL_COMP_EN | CAM_CONTROL_GROUP_ACC |
+ CAM_CONTROL_BROAD_ACC,
+ &lp->lan_saa9730_regs->CamCtl);
} else {
/*
* Will handle the multicast stuff later. -carstenl
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index 1eae16b72b4b..103c3174ab54 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -243,7 +243,7 @@ struct sbmac_softc {
* Controller-specific things
*/
- volatile void __iomem *sbm_base; /* MAC's base address */
+ void __iomem *sbm_base; /* MAC's base address */
sbmac_state_t sbm_state; /* current state */
volatile void __iomem *sbm_macenable; /* MAC Enable Register */
diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c
index 4a926f20b6ea..c32c21af3fdd 100644
--- a/drivers/net/sc92031.c
+++ b/drivers/net/sc92031.c
@@ -964,7 +964,7 @@ static int sc92031_start_xmit(struct sk_buff *skb, struct net_device *dev)
goto out;
}
- spin_lock_bh(&priv->lock);
+ spin_lock(&priv->lock);
if (unlikely(!netif_carrier_ok(dev))) {
err = -ENOLINK;
@@ -1005,7 +1005,7 @@ static int sc92031_start_xmit(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
out_unlock:
- spin_unlock_bh(&priv->lock);
+ spin_unlock(&priv->lock);
out:
dev_kfree_skb(skb);
@@ -1042,12 +1042,12 @@ static int sc92031_open(struct net_device *dev)
priv->pm_config = 0;
/* Interrupts already disabled by sc92031_stop or sc92031_probe */
- spin_lock(&priv->lock);
+ spin_lock_bh(&priv->lock);
_sc92031_reset(dev);
mmiowb();
- spin_unlock(&priv->lock);
+ spin_unlock_bh(&priv->lock);
sc92031_enable_interrupts(dev);
if (netif_carrier_ok(dev))
@@ -1077,13 +1077,13 @@ static int sc92031_stop(struct net_device *dev)
/* Disable interrupts, stop Tx and Rx. */
sc92031_disable_interrupts(dev);
- spin_lock(&priv->lock);
+ spin_lock_bh(&priv->lock);
_sc92031_disable_tx_rx(dev);
_sc92031_tx_clear(dev);
mmiowb();
- spin_unlock(&priv->lock);
+ spin_unlock_bh(&priv->lock);
free_irq(pdev->irq, dev);
pci_free_consistent(pdev, TX_BUF_TOT_LEN, priv->tx_bufs,
@@ -1539,13 +1539,13 @@ static int sc92031_suspend(struct pci_dev *pdev, pm_message_t state)
/* Disable interrupts, stop Tx and Rx. */
sc92031_disable_interrupts(dev);
- spin_lock(&priv->lock);
+ spin_lock_bh(&priv->lock);
_sc92031_disable_tx_rx(dev);
_sc92031_tx_clear(dev);
mmiowb();
- spin_unlock(&priv->lock);
+ spin_unlock_bh(&priv->lock);
out:
pci_set_power_state(pdev, pci_choose_state(pdev, state));
@@ -1565,12 +1565,12 @@ static int sc92031_resume(struct pci_dev *pdev)
goto out;
/* Interrupts already disabled by sc92031_suspend */
- spin_lock(&priv->lock);
+ spin_lock_bh(&priv->lock);
_sc92031_reset(dev);
mmiowb();
- spin_unlock(&priv->lock);
+ spin_unlock_bh(&priv->lock);
sc92031_enable_interrupts(dev);
netif_device_attach(dev);
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index b08508b35833..34463ce6f132 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -324,6 +324,7 @@ static struct mii_chip_info {
u32 feature;
} mii_chip_table[] = {
{ "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN, F_PHY_BCM5461 },
+ { "Broadcom PHY AC131", { 0x0143, 0xbc70 }, LAN, 0 },
{ "Agere PHY ET1101B", { 0x0282, 0xf010 }, LAN, 0 },
{ "Marvell PHY 88E1111", { 0x0141, 0x0cc0 }, LAN, F_PHY_88E1111 },
{ "Realtek PHY RTL8201", { 0x0000, 0x8200 }, LAN, 0 },
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index eea75a401b0c..d476a3cc2e94 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -105,7 +105,8 @@ static const int txqaddr[] = { Q_XA1, Q_XA2 };
static const int rxqaddr[] = { Q_R1, Q_R2 };
static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F };
static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F };
-static const u32 irqmask[] = { IS_R1_F|IS_XA1_F, IS_R2_F|IS_XA2_F };
+static const u32 napimask[] = { IS_R1_F|IS_XA1_F, IS_R2_F|IS_XA2_F };
+static const u32 portmask[] = { IS_PORT_1, IS_PORT_2 };
static int skge_get_regs_len(struct net_device *dev)
{
@@ -162,27 +163,46 @@ static void skge_wol_init(struct skge_port *skge)
{
struct skge_hw *hw = skge->hw;
int port = skge->port;
- enum pause_control save_mode;
- u32 ctrl;
+ u16 ctrl;
- /* Bring hardware out of reset */
skge_write16(hw, B0_CTST, CS_RST_CLR);
skge_write16(hw, SK_REG(port, GMAC_LINK_CTRL), GMLC_RST_CLR);
- skge_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR);
- skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR);
+ /* Turn on Vaux */
+ skge_write8(hw, B0_POWER_CTRL,
+ PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_ON | PC_VCC_OFF);
- /* Force to 10/100 skge_reset will re-enable on resume */
- save_mode = skge->flow_control;
- skge->flow_control = FLOW_MODE_SYMMETRIC;
+ /* WA code for COMA mode -- clear PHY reset */
+ if (hw->chip_id == CHIP_ID_YUKON_LITE &&
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
+ u32 reg = skge_read32(hw, B2_GP_IO);
+ reg |= GP_DIR_9;
+ reg &= ~GP_IO_9;
+ skge_write32(hw, B2_GP_IO, reg);
+ }
- ctrl = skge->advertising;
- skge->advertising &= ~(ADVERTISED_1000baseT_Half|ADVERTISED_1000baseT_Full);
+ skge_write32(hw, SK_REG(port, GPHY_CTRL),
+ GPC_DIS_SLEEP |
+ GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0 |
+ GPC_ANEG_1 | GPC_RST_SET);
- skge_phy_reset(skge);
+ skge_write32(hw, SK_REG(port, GPHY_CTRL),
+ GPC_DIS_SLEEP |
+ GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0 |
+ GPC_ANEG_1 | GPC_RST_CLR);
+
+ skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR);
+
+ /* Force to 10/100 skge_reset will re-enable on resume */
+ gm_phy_write(hw, port, PHY_MARV_AUNE_ADV,
+ PHY_AN_100FULL | PHY_AN_100HALF |
+ PHY_AN_10FULL | PHY_AN_10HALF| PHY_AN_CSMA);
+ /* no 1000 HD/FD */
+ gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, 0);
+ gm_phy_write(hw, port, PHY_MARV_CTRL,
+ PHY_CT_RESET | PHY_CT_SPS_LSB | PHY_CT_ANE |
+ PHY_CT_RE_CFG | PHY_CT_DUP_MD);
- skge->flow_control = save_mode;
- skge->advertising = ctrl;
/* Set GMAC to no flow control and auto update for speed/duplex */
gma_write16(hw, port, GM_GP_CTRL,
@@ -226,12 +246,10 @@ static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
struct skge_port *skge = netdev_priv(dev);
struct skge_hw *hw = skge->hw;
- if (wol->wolopts & wol_supported(hw))
+ if (wol->wolopts & ~wol_supported(hw))
return -EOPNOTSUPP;
skge->wol = wol->wolopts;
- if (!netif_running(dev))
- skge_wol_init(skge);
return 0;
}
@@ -671,7 +689,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
struct skge_hw *hw = skge->hw;
int port = skge->port;
- mutex_lock(&hw->phy_mutex);
+ spin_lock_bh(&hw->phy_lock);
if (hw->chip_id == CHIP_ID_GENESIS) {
switch (mode) {
case LED_MODE_OFF:
@@ -742,7 +760,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
PHY_M_LED_MO_RX(MO_LED_ON));
}
}
- mutex_unlock(&hw->phy_mutex);
+ spin_unlock_bh(&hw->phy_lock);
}
/* blink LED's for finding board */
@@ -1316,7 +1334,7 @@ static void xm_phy_init(struct skge_port *skge)
xm_phy_write(hw, port, PHY_XMAC_CTRL, ctrl);
/* Poll PHY for status changes */
- schedule_delayed_work(&skge->link_thread, LINK_HZ);
+ mod_timer(&skge->link_timer, jiffies + LINK_HZ);
}
static void xm_check_link(struct net_device *dev)
@@ -1391,10 +1409,9 @@ static void xm_check_link(struct net_device *dev)
* Since internal PHY is wired to a level triggered pin, can't
* get an interrupt when carrier is detected.
*/
-static void xm_link_timer(struct work_struct *work)
+static void xm_link_timer(unsigned long arg)
{
- struct skge_port *skge =
- container_of(work, struct skge_port, link_thread.work);
+ struct skge_port *skge = (struct skge_port *) arg;
struct net_device *dev = skge->netdev;
struct skge_hw *hw = skge->hw;
int port = skge->port;
@@ -1414,13 +1431,13 @@ static void xm_link_timer(struct work_struct *work)
goto nochange;
}
- mutex_lock(&hw->phy_mutex);
+ spin_lock(&hw->phy_lock);
xm_check_link(dev);
- mutex_unlock(&hw->phy_mutex);
+ spin_unlock(&hw->phy_lock);
nochange:
if (netif_running(dev))
- schedule_delayed_work(&skge->link_thread, LINK_HZ);
+ mod_timer(&skge->link_timer, jiffies + LINK_HZ);
}
static void genesis_mac_init(struct skge_hw *hw, int port)
@@ -2323,7 +2340,7 @@ static void skge_phy_reset(struct skge_port *skge)
netif_stop_queue(skge->netdev);
netif_carrier_off(skge->netdev);
- mutex_lock(&hw->phy_mutex);
+ spin_lock_bh(&hw->phy_lock);
if (hw->chip_id == CHIP_ID_GENESIS) {
genesis_reset(hw, port);
genesis_mac_init(hw, port);
@@ -2331,7 +2348,7 @@ static void skge_phy_reset(struct skge_port *skge)
yukon_reset(hw, port);
yukon_init(hw, port);
}
- mutex_unlock(&hw->phy_mutex);
+ spin_unlock_bh(&hw->phy_lock);
dev->set_multicast_list(dev);
}
@@ -2354,12 +2371,12 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
/* fallthru */
case SIOCGMIIREG: {
u16 val = 0;
- mutex_lock(&hw->phy_mutex);
+ spin_lock_bh(&hw->phy_lock);
if (hw->chip_id == CHIP_ID_GENESIS)
err = __xm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val);
else
err = __gm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val);
- mutex_unlock(&hw->phy_mutex);
+ spin_unlock_bh(&hw->phy_lock);
data->val_out = val;
break;
}
@@ -2368,14 +2385,14 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- mutex_lock(&hw->phy_mutex);
+ spin_lock_bh(&hw->phy_lock);
if (hw->chip_id == CHIP_ID_GENESIS)
err = xm_phy_write(hw, skge->port, data->reg_num & 0x1f,
data->val_in);
else
err = gm_phy_write(hw, skge->port, data->reg_num & 0x1f,
data->val_in);
- mutex_unlock(&hw->phy_mutex);
+ spin_unlock_bh(&hw->phy_lock);
break;
}
return err;
@@ -2481,12 +2498,12 @@ static int skge_up(struct net_device *dev)
goto free_rx_ring;
/* Initialize MAC */
- mutex_lock(&hw->phy_mutex);
+ spin_lock_bh(&hw->phy_lock);
if (hw->chip_id == CHIP_ID_GENESIS)
genesis_mac_init(hw, port);
else
yukon_mac_init(hw, port);
- mutex_unlock(&hw->phy_mutex);
+ spin_unlock_bh(&hw->phy_lock);
/* Configure RAMbuffers */
chunk = hw->ram_size / ((hw->ports + 1)*2);
@@ -2504,6 +2521,11 @@ static int skge_up(struct net_device *dev)
skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
skge_led(skge, LED_MODE_ON);
+ spin_lock_irq(&hw->hw_lock);
+ hw->intr_mask |= portmask[port];
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+ spin_unlock_irq(&hw->hw_lock);
+
netif_poll_enable(dev);
return 0;
@@ -2530,8 +2552,17 @@ static int skge_down(struct net_device *dev)
printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
netif_stop_queue(dev);
+
if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC)
- cancel_delayed_work(&skge->link_thread);
+ del_timer_sync(&skge->link_timer);
+
+ netif_poll_disable(dev);
+ netif_carrier_off(dev);
+
+ spin_lock_irq(&hw->hw_lock);
+ hw->intr_mask &= ~portmask[port];
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+ spin_unlock_irq(&hw->hw_lock);
skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
if (hw->chip_id == CHIP_ID_GENESIS)
@@ -2575,8 +2606,10 @@ static int skge_down(struct net_device *dev)
skge_led(skge, LED_MODE_OFF);
- netif_poll_disable(dev);
+ netif_tx_lock_bh(dev);
skge_tx_clean(dev);
+ netif_tx_unlock_bh(dev);
+
skge_rx_clean(skge);
kfree(skge->rx_ring.start);
@@ -2721,7 +2754,6 @@ static void skge_tx_clean(struct net_device *dev)
struct skge_port *skge = netdev_priv(dev);
struct skge_element *e;
- netif_tx_lock_bh(dev);
for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) {
struct skge_tx_desc *td = e->desc;
skge_tx_free(skge, e, td->control);
@@ -2730,7 +2762,6 @@ static void skge_tx_clean(struct net_device *dev)
skge->tx_ring.to_clean = e;
netif_wake_queue(dev);
- netif_tx_unlock_bh(dev);
}
static void skge_tx_timeout(struct net_device *dev)
@@ -3049,7 +3080,7 @@ static int skge_poll(struct net_device *dev, int *budget)
spin_lock_irqsave(&hw->hw_lock, flags);
__netif_rx_complete(dev);
- hw->intr_mask |= irqmask[skge->port];
+ hw->intr_mask |= napimask[skge->port];
skge_write32(hw, B0_IMSK, hw->intr_mask);
skge_read32(hw, B0_IMSK);
spin_unlock_irqrestore(&hw->hw_lock, flags);
@@ -3160,28 +3191,29 @@ static void skge_error_irq(struct skge_hw *hw)
}
/*
- * Interrupt from PHY are handled in work queue
+ * Interrupt from PHY are handled in tasklet (softirq)
* because accessing phy registers requires spin wait which might
* cause excess interrupt latency.
*/
-static void skge_extirq(struct work_struct *work)
+static void skge_extirq(unsigned long arg)
{
- struct skge_hw *hw = container_of(work, struct skge_hw, phy_work);
+ struct skge_hw *hw = (struct skge_hw *) arg;
int port;
- mutex_lock(&hw->phy_mutex);
for (port = 0; port < hw->ports; port++) {
struct net_device *dev = hw->dev[port];
- struct skge_port *skge = netdev_priv(dev);
if (netif_running(dev)) {
+ struct skge_port *skge = netdev_priv(dev);
+
+ spin_lock(&hw->phy_lock);
if (hw->chip_id != CHIP_ID_GENESIS)
yukon_phy_intr(skge);
else if (hw->phy_type == SK_PHY_BCOM)
bcom_phy_intr(skge);
+ spin_unlock(&hw->phy_lock);
}
}
- mutex_unlock(&hw->phy_mutex);
spin_lock_irq(&hw->hw_lock);
hw->intr_mask |= IS_EXT_REG;
@@ -3206,7 +3238,7 @@ static irqreturn_t skge_intr(int irq, void *dev_id)
status &= hw->intr_mask;
if (status & IS_EXT_REG) {
hw->intr_mask &= ~IS_EXT_REG;
- schedule_work(&hw->phy_work);
+ tasklet_schedule(&hw->phy_task);
}
if (status & (IS_XA1_F|IS_R1_F)) {
@@ -3275,24 +3307,35 @@ static int skge_set_mac_address(struct net_device *dev, void *p)
struct skge_hw *hw = skge->hw;
unsigned port = skge->port;
const struct sockaddr *addr = p;
+ u16 ctrl;
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
- mutex_lock(&hw->phy_mutex);
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
- memcpy_toio(hw->regs + B2_MAC_1 + port*8,
- dev->dev_addr, ETH_ALEN);
- memcpy_toio(hw->regs + B2_MAC_2 + port*8,
- dev->dev_addr, ETH_ALEN);
- if (hw->chip_id == CHIP_ID_GENESIS)
- xm_outaddr(hw, port, XM_SA, dev->dev_addr);
- else {
- gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr);
- gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr);
+ if (!netif_running(dev)) {
+ memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN);
+ memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN);
+ } else {
+ /* disable Rx */
+ spin_lock_bh(&hw->phy_lock);
+ ctrl = gma_read16(hw, port, GM_GP_CTRL);
+ gma_write16(hw, port, GM_GP_CTRL, ctrl & ~GM_GPCR_RX_ENA);
+
+ memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN);
+ memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN);
+
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ xm_outaddr(hw, port, XM_SA, dev->dev_addr);
+ else {
+ gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr);
+ gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr);
+ }
+
+ gma_write16(hw, port, GM_GP_CTRL, ctrl);
+ spin_unlock_bh(&hw->phy_lock);
}
- mutex_unlock(&hw->phy_mutex);
return 0;
}
@@ -3407,10 +3450,9 @@ static int skge_reset(struct skge_hw *hw)
else
hw->ram_size = t8 * 4096;
- hw->intr_mask = IS_HW_ERR | IS_PORT_1;
- if (hw->ports > 1)
- hw->intr_mask |= IS_PORT_2;
+ hw->intr_mask = IS_HW_ERR;
+ /* Use PHY IRQ for all but fiber based Genesis board */
if (!(hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC))
hw->intr_mask |= IS_EXT_REG;
@@ -3478,14 +3520,12 @@ static int skge_reset(struct skge_hw *hw)
skge_write32(hw, B0_IMSK, hw->intr_mask);
- mutex_lock(&hw->phy_mutex);
for (i = 0; i < hw->ports; i++) {
if (hw->chip_id == CHIP_ID_GENESIS)
genesis_reset(hw, i);
else
yukon_reset(hw, i);
}
- mutex_unlock(&hw->phy_mutex);
return 0;
}
@@ -3533,6 +3573,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
skge->netdev = dev;
skge->hw = hw;
skge->msg_enable = netif_msg_init(debug, default_msg);
+
skge->tx_ring.count = DEFAULT_TX_RING_SIZE;
skge->rx_ring.count = DEFAULT_RX_RING_SIZE;
@@ -3549,7 +3590,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
skge->port = port;
/* Only used for Genesis XMAC */
- INIT_DELAYED_WORK(&skge->link_thread, xm_link_timer);
+ setup_timer(&skge->link_timer, xm_link_timer, (unsigned long) skge);
if (hw->chip_id != CHIP_ID_GENESIS) {
dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
@@ -3631,9 +3672,9 @@ static int __devinit skge_probe(struct pci_dev *pdev,
}
hw->pdev = pdev;
- mutex_init(&hw->phy_mutex);
- INIT_WORK(&hw->phy_work, skge_extirq);
spin_lock_init(&hw->hw_lock);
+ spin_lock_init(&hw->phy_lock);
+ tasklet_init(&hw->phy_task, &skge_extirq, (unsigned long) hw);
hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
if (!hw->regs) {
@@ -3719,6 +3760,8 @@ static void __devexit skge_remove(struct pci_dev *pdev)
dev0 = hw->dev[0];
unregister_netdev(dev0);
+ tasklet_disable(&hw->phy_task);
+
spin_lock_irq(&hw->hw_lock);
hw->intr_mask = 0;
skge_write32(hw, B0_IMSK, 0);
@@ -3741,21 +3784,6 @@ static void __devexit skge_remove(struct pci_dev *pdev)
}
#ifdef CONFIG_PM
-static int vaux_avail(struct pci_dev *pdev)
-{
- int pm_cap;
-
- pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
- if (pm_cap) {
- u16 ctl;
- pci_read_config_word(pdev, pm_cap + PCI_PM_PMC, &ctl);
- if (ctl & PCI_PM_CAP_AUX_POWER)
- return 1;
- }
- return 0;
-}
-
-
static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct skge_hw *hw = pci_get_drvdata(pdev);
@@ -3777,10 +3805,6 @@ static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
wol |= skge->wol;
}
- if (wol && vaux_avail(pdev))
- skge_write8(hw, B0_POWER_CTRL,
- PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_ON | PC_VCC_OFF);
-
skge_write32(hw, B0_IMSK, 0);
pci_enable_wake(pdev, pci_choose_state(pdev, state), wol);
pci_set_power_state(pdev, pci_choose_state(pdev, state));
@@ -3826,6 +3850,28 @@ out:
}
#endif
+static void skge_shutdown(struct pci_dev *pdev)
+{
+ struct skge_hw *hw = pci_get_drvdata(pdev);
+ int i, wol = 0;
+
+ for (i = 0; i < hw->ports; i++) {
+ struct net_device *dev = hw->dev[i];
+ struct skge_port *skge = netdev_priv(dev);
+
+ if (skge->wol)
+ skge_wol_init(skge);
+ wol |= skge->wol;
+ }
+
+ pci_enable_wake(pdev, PCI_D3hot, wol);
+ pci_enable_wake(pdev, PCI_D3cold, wol);
+
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, PCI_D3hot);
+
+}
+
static struct pci_driver skge_driver = {
.name = DRV_NAME,
.id_table = skge_id_table,
@@ -3835,6 +3881,7 @@ static struct pci_driver skge_driver = {
.suspend = skge_suspend,
.resume = skge_resume,
#endif
+ .shutdown = skge_shutdown,
};
static int __init skge_init_module(void)
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index e9354dfa7e9a..86467ae74d45 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -2424,8 +2424,8 @@ struct skge_hw {
u32 ram_size;
u32 ram_offset;
u16 phy_addr;
- struct work_struct phy_work;
- struct mutex phy_mutex;
+ spinlock_t phy_lock;
+ struct tasklet_struct phy_task;
};
enum pause_control {
@@ -2457,7 +2457,7 @@ struct skge_port {
struct net_device_stats net_stats;
- struct delayed_work link_thread;
+ struct timer_list link_timer;
enum pause_control flow_control;
enum pause_status flow_status;
u8 rx_csum;
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 53839979cfb8..4a009b7b1777 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -510,9 +510,9 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
ledover &= ~PHY_M_LED_MO_RX;
}
- if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev == CHIP_REV_YU_EC_A1) {
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U &&
+ hw->chip_rev == CHIP_REV_YU_EC_U_A1) {
/* apply fixes in PHY AFE */
- pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 255);
/* increase differential signal amplitude in 10BASE-T */
@@ -524,7 +524,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
gm_phy_write(hw, port, 0x17, 0x2002);
/* set page register to 0 */
- gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0);
} else if (hw->chip_id != CHIP_ID_YUKON_EX) {
gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
@@ -1561,6 +1561,7 @@ static int sky2_down(struct net_device *dev)
/* Stop more packets from being queued */
netif_stop_queue(dev);
+ netif_carrier_off(dev);
/* Disable port IRQ */
imask = sky2_read32(hw, B0_IMSK);
@@ -2165,9 +2166,27 @@ force_update:
/* fall through */
#endif
case OP_RXCHKS:
- skb = sky2->rx_ring[sky2->rx_next].skb;
- skb->ip_summed = CHECKSUM_COMPLETE;
- skb->csum = status & 0xffff;
+ if (!sky2->rx_csum)
+ break;
+
+ /* Both checksum counters are programmed to start at
+ * the same offset, so unless there is a problem they
+ * should match. This failure is an early indication that
+ * hardware receive checksumming won't work.
+ */
+ if (likely(status >> 16 == (status & 0xffff))) {
+ skb = sky2->rx_ring[sky2->rx_next].skb;
+ skb->ip_summed = CHECKSUM_COMPLETE;
+ skb->csum = status & 0xffff;
+ } else {
+ printk(KERN_NOTICE PFX "%s: hardware receive "
+ "checksum problem (status = %#x)\n",
+ dev->name, status);
+ sky2->rx_csum = 0;
+ sky2_write32(sky2->hw,
+ Q_ADDR(rxqaddr[le->link], Q_CSR),
+ BMU_DIS_RX_CHKSUM);
+ }
break;
case OP_TXINDEXLE:
@@ -3751,6 +3770,11 @@ static int sky2_resume(struct pci_dev *pdev)
goto out;
pci_enable_wake(pdev, PCI_D0, 0);
+
+ /* Re-enable all clocks */
+ if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U)
+ sky2_pci_write32(hw, PCI_DEV_REG3, 0);
+
sky2_reset(hw);
sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
index c62e85d89f41..7bee45b42a2c 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/sun3lance.c
@@ -336,13 +336,27 @@ static int __init lance_probe( struct net_device *dev)
/* XXX - leak? */
MEM = dvma_malloc_align(sizeof(struct lance_memory), 0x10000);
+ if (MEM == NULL) {
+#ifdef CONFIG_SUN3
+ iounmap((void __iomem *)ioaddr);
+#endif
+ printk(KERN_WARNING "SUN3 Lance couldn't allocate DVMA memory\n");
+ return 0;
+ }
lp->iobase = (volatile unsigned short *)ioaddr;
dev->base_addr = (unsigned long)ioaddr; /* informational only */
REGA(CSR0) = CSR0_STOP;
- request_irq(LANCE_IRQ, lance_interrupt, IRQF_DISABLED, "SUN3 Lance", dev);
+ if (request_irq(LANCE_IRQ, lance_interrupt, IRQF_DISABLED, "SUN3 Lance", dev) < 0) {
+#ifdef CONFIG_SUN3
+ iounmap((void __iomem *)ioaddr);
+#endif
+ dvma_free((void *)MEM);
+ printk(KERN_WARNING "SUN3 Lance unable to allocate IRQ\n");
+ return 0;
+ }
dev->irq = (unsigned short)LANCE_IRQ;
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 616be8d0fa85..08ea61db46fe 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -2530,6 +2530,35 @@ static struct net_device_stats *gem_get_stats(struct net_device *dev)
return &gp->net_stats;
}
+static int gem_set_mac_address(struct net_device *dev, void *addr)
+{
+ struct sockaddr *macaddr = (struct sockaddr *) addr;
+ struct gem *gp = dev->priv;
+ unsigned char *e = &dev->dev_addr[0];
+
+ if (!is_valid_ether_addr(macaddr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ if (!netif_running(dev) || !netif_device_present(dev)) {
+ /* We'll just catch it later when the
+ * device is up'd or resumed.
+ */
+ memcpy(dev->dev_addr, macaddr->sa_data, dev->addr_len);
+ return 0;
+ }
+
+ mutex_lock(&gp->pm_mutex);
+ memcpy(dev->dev_addr, macaddr->sa_data, dev->addr_len);
+ if (gp->running) {
+ writel((e[4] << 8) | e[5], gp->regs + MAC_ADDR0);
+ writel((e[2] << 8) | e[3], gp->regs + MAC_ADDR1);
+ writel((e[0] << 8) | e[1], gp->regs + MAC_ADDR2);
+ }
+ mutex_unlock(&gp->pm_mutex);
+
+ return 0;
+}
+
static void gem_set_multicast(struct net_device *dev)
{
struct gem *gp = dev->priv;
@@ -3122,6 +3151,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
dev->change_mtu = gem_change_mtu;
dev->irq = pdev->irq;
dev->dma = 0;
+ dev->set_mac_address = gem_set_mac_address;
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = gem_poll_controller;
#endif
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 8c8f9f4d47a5..256969e1300c 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -64,8 +64,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.74"
-#define DRV_MODULE_RELDATE "February 20, 2007"
+#define DRV_MODULE_VERSION "3.75"
+#define DRV_MODULE_RELDATE "March 23, 2007"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -3568,32 +3568,34 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id)
* Reading the PCI State register will confirm whether the
* interrupt is ours and will flush the status block.
*/
- if ((sblk->status & SD_STATUS_UPDATED) ||
- !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
- /*
- * Writing any value to intr-mbox-0 clears PCI INTA# and
- * chip-internal interrupt pending events.
- * Writing non-zero to intr-mbox-0 additional tells the
- * NIC to stop sending us irqs, engaging "in-intr-handler"
- * event coalescing.
- */
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
- 0x00000001);
- if (tg3_irq_sync(tp))
+ if (unlikely(!(sblk->status & SD_STATUS_UPDATED))) {
+ if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) ||
+ (tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
+ handled = 0;
goto out;
- sblk->status &= ~SD_STATUS_UPDATED;
- if (likely(tg3_has_work(tp))) {
- prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
- netif_rx_schedule(dev); /* schedule NAPI poll */
- } else {
- /* No work, shared interrupt perhaps? re-enable
- * interrupts, and flush that PCI write
- */
- tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
- 0x00000000);
}
- } else { /* shared interrupt */
- handled = 0;
+ }
+
+ /*
+ * Writing any value to intr-mbox-0 clears PCI INTA# and
+ * chip-internal interrupt pending events.
+ * Writing non-zero to intr-mbox-0 additional tells the
+ * NIC to stop sending us irqs, engaging "in-intr-handler"
+ * event coalescing.
+ */
+ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
+ if (tg3_irq_sync(tp))
+ goto out;
+ sblk->status &= ~SD_STATUS_UPDATED;
+ if (likely(tg3_has_work(tp))) {
+ prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
+ netif_rx_schedule(dev); /* schedule NAPI poll */
+ } else {
+ /* No work, shared interrupt perhaps? re-enable
+ * interrupts, and flush that PCI write
+ */
+ tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+ 0x00000000);
}
out:
return IRQ_RETVAL(handled);
@@ -3611,31 +3613,33 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id)
* Reading the PCI State register will confirm whether the
* interrupt is ours and will flush the status block.
*/
- if ((sblk->status_tag != tp->last_tag) ||
- !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
- /*
- * writing any value to intr-mbox-0 clears PCI INTA# and
- * chip-internal interrupt pending events.
- * writing non-zero to intr-mbox-0 additional tells the
- * NIC to stop sending us irqs, engaging "in-intr-handler"
- * event coalescing.
- */
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
- 0x00000001);
- if (tg3_irq_sync(tp))
+ if (unlikely(sblk->status_tag == tp->last_tag)) {
+ if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) ||
+ (tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
+ handled = 0;
goto out;
- if (netif_rx_schedule_prep(dev)) {
- prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
- /* Update last_tag to mark that this status has been
- * seen. Because interrupt may be shared, we may be
- * racing with tg3_poll(), so only update last_tag
- * if tg3_poll() is not scheduled.
- */
- tp->last_tag = sblk->status_tag;
- __netif_rx_schedule(dev);
}
- } else { /* shared interrupt */
- handled = 0;
+ }
+
+ /*
+ * writing any value to intr-mbox-0 clears PCI INTA# and
+ * chip-internal interrupt pending events.
+ * writing non-zero to intr-mbox-0 additional tells the
+ * NIC to stop sending us irqs, engaging "in-intr-handler"
+ * event coalescing.
+ */
+ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
+ if (tg3_irq_sync(tp))
+ goto out;
+ if (netif_rx_schedule_prep(dev)) {
+ prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
+ /* Update last_tag to mark that this status has been
+ * seen. Because interrupt may be shared, we may be
+ * racing with tg3_poll(), so only update last_tag
+ * if tg3_poll() is not scheduled.
+ */
+ tp->last_tag = sblk->status_tag;
+ __netif_rx_schedule(dev);
}
out:
return IRQ_RETVAL(handled);
@@ -4823,6 +4827,21 @@ static int tg3_chip_reset(struct tg3 *tp)
if (write_op == tg3_write_flush_reg32)
tp->write32 = tg3_write32;
+ /* Prevent the irq handler from reading or writing PCI registers
+ * during chip reset when the memory enable bit in the PCI command
+ * register may be cleared. The chip does not generate interrupt
+ * at this time, but the irq handler may still be called due to irq
+ * sharing or irqpoll.
+ */
+ tp->tg3_flags |= TG3_FLAG_CHIP_RESETTING;
+ if (tp->hw_status) {
+ tp->hw_status->status = 0;
+ tp->hw_status->status_tag = 0;
+ }
+ tp->last_tag = 0;
+ smp_mb();
+ synchronize_irq(tp->pdev->irq);
+
/* do the reset */
val = GRC_MISC_CFG_CORECLK_RESET;
@@ -4904,6 +4923,8 @@ static int tg3_chip_reset(struct tg3 *tp)
pci_restore_state(tp->pdev);
+ tp->tg3_flags &= ~TG3_FLAG_CHIP_RESETTING;
+
/* Make sure PCI-X relaxed ordering bit is clear. */
pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val);
val &= ~PCIX_CAPS_RELAXED_ORDERING;
@@ -6321,8 +6342,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
RDMAC_MODE_ADDROFLOW_ENAB | RDMAC_MODE_FIFOOFLOW_ENAB |
RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB |
RDMAC_MODE_LNGREAD_ENAB);
- if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE)
- rdmac_mode |= RDMAC_MODE_SPLIT_ENABLE;
/* If statement applies to 5705 and 5750 PCI devices only */
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
@@ -6495,9 +6514,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
val &= ~(PCIX_CAPS_SPLIT_MASK | PCIX_CAPS_BURST_MASK);
val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT);
- if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE)
- val |= (tp->split_mode_max_reqs <<
- PCIX_CAPS_SPLIT_SHIFT);
}
tw32(TG3PCI_X_CAPS, val);
}
@@ -10863,14 +10879,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
grc_misc_cfg = tr32(GRC_MISC_CFG);
grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK;
- /* Broadcom's driver says that CIOBE multisplit has a bug */
-#if 0
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
- grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5704CIOBE) {
- tp->tg3_flags |= TG3_FLAG_SPLIT_MODE;
- tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ;
- }
-#endif
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
(grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 ||
grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M))
@@ -11968,14 +11976,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
i == 5 ? '\n' : ':');
printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] "
- "MIirq[%d] ASF[%d] Split[%d] WireSpeed[%d] "
- "TSOcap[%d] \n",
+ "MIirq[%d] ASF[%d] WireSpeed[%d] TSOcap[%d]\n",
dev->name,
(tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0,
(tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0,
(tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0,
(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0,
- (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) != 0,
(tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0,
(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0);
printk(KERN_INFO "%s: dma_rwctrl[%08x] dma_mask[%d-bit]\n",
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 086892d8c1f1..d515ed23841b 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2223,7 +2223,7 @@ struct tg3 {
#define TG3_FLAG_40BIT_DMA_BUG 0x08000000
#define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000
#define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000
-#define TG3_FLAG_SPLIT_MODE 0x40000000
+#define TG3_FLAG_CHIP_RESETTING 0x40000000
#define TG3_FLAG_INIT_COMPLETE 0x80000000
u32 tg3_flags2;
#define TG3_FLG2_RESTART_TIMER 0x00000001
@@ -2262,9 +2262,6 @@ struct tg3 {
#define TG3_FLG2_NO_FWARE_REPORTED 0x40000000
#define TG3_FLG2_PHY_ADJUST_TRIM 0x80000000
- u32 split_mode_max_reqs;
-#define SPLIT_MODE_5704_MAX_REQ 3
-
struct timer_list timer;
u16 timer_counter;
u16 timer_multiplier;
diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
index 0d97e10ccac5..01d55315ee8c 100644
--- a/drivers/net/tokenring/ibmtr.c
+++ b/drivers/net/tokenring/ibmtr.c
@@ -186,7 +186,6 @@ static char __devinit *adapter_def(char type)
#define TRC_INITV 0x02 /* verbose init trace points */
static unsigned char ibmtr_debug_trace = 0;
-static int ibmtr_probe(struct net_device *dev);
static int ibmtr_probe1(struct net_device *dev, int ioaddr);
static unsigned char get_sram_size(struct tok_info *adapt_info);
static int trdev_init(struct net_device *dev);
@@ -335,17 +334,6 @@ static void ibmtr_cleanup_card(struct net_device *dev)
#endif
}
-int ibmtr_probe_card(struct net_device *dev)
-{
- int err = ibmtr_probe(dev);
- if (!err) {
- err = register_netdev(dev);
- if (err)
- ibmtr_cleanup_card(dev);
- }
- return err;
-}
-
/****************************************************************************
* ibmtr_probe(): Routine specified in the network device structure
* to probe for an IBM Token Ring Adapter. Routine outline:
@@ -358,7 +346,7 @@ int ibmtr_probe_card(struct net_device *dev)
* which references it.
****************************************************************************/
-static int ibmtr_probe(struct net_device *dev)
+static int __devinit ibmtr_probe(struct net_device *dev)
{
int i;
int base_addr = dev->base_addr;
@@ -378,6 +366,17 @@ static int ibmtr_probe(struct net_device *dev)
return -ENODEV;
}
+int __devinit ibmtr_probe_card(struct net_device *dev)
+{
+ int err = ibmtr_probe(dev);
+ if (!err) {
+ err = register_netdev(dev);
+ if (err)
+ ibmtr_cleanup_card(dev);
+ }
+ return err;
+}
+
/*****************************************************************************/
static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr)
diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c
index 24a29c99ba94..9aeac76184f3 100644
--- a/drivers/net/tulip/dmfe.c
+++ b/drivers/net/tulip/dmfe.c
@@ -190,13 +190,13 @@
/* Structure/enum declaration ------------------------------- */
struct tx_desc {
- u32 tdes0, tdes1, tdes2, tdes3; /* Data for the card */
+ __le32 tdes0, tdes1, tdes2, tdes3; /* Data for the card */
char *tx_buf_ptr; /* Data for us */
struct tx_desc *next_tx_desc;
} __attribute__(( aligned(32) ));
struct rx_desc {
- u32 rdes0, rdes1, rdes2, rdes3; /* Data for the card */
+ __le32 rdes0, rdes1, rdes2, rdes3; /* Data for the card */
struct sk_buff *rx_skb_ptr; /* Data for us */
struct rx_desc *next_rx_desc;
} __attribute__(( aligned(32) ));
@@ -458,7 +458,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
/* read 64 word srom data */
for (i = 0; i < 64; i++)
- ((u16 *) db->srom)[i] =
+ ((__le16 *) db->srom)[i] =
cpu_to_le16(read_srom_word(db->ioaddr, i));
/* Set Node address */
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index dab88b958d6e..639e1e6913bf 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3607,7 +3607,6 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (bd == ugeth->confBd[txQ]) {
if (!netif_queue_stopped(dev))
netif_stop_queue(dev);
- return NETDEV_TX_BUSY;
}
ugeth->txBd[txQ] = bd;
@@ -3623,7 +3622,7 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev)
spin_unlock_irq(&ugeth->lock);
- return NETDEV_TX_OK;
+ return 0;
}
static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit)
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index ebbda1d8f542..f3a972e74e9a 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -30,8 +30,8 @@
*/
#define DRV_NAME "via-rhine"
-#define DRV_VERSION "1.4.2"
-#define DRV_RELDATE "Sept-11-2006"
+#define DRV_VERSION "1.4.3"
+#define DRV_RELDATE "2007-03-06"
/* A few user-configurable values.
@@ -105,6 +105,7 @@ static const int multicast_filter_limit = 32;
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
+#include <linux/dmi.h>
/* These identify the driver base version and may not be removed. */
static char version[] __devinitdata =
@@ -1995,6 +1996,23 @@ static struct pci_driver rhine_driver = {
.shutdown = rhine_shutdown,
};
+static struct dmi_system_id __initdata rhine_dmi_table[] = {
+ {
+ .ident = "EPIA-M",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR, "Award Software International, Inc."),
+ DMI_MATCH(DMI_BIOS_VERSION, "6.00 PG"),
+ },
+ },
+ {
+ .ident = "KV7",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"),
+ DMI_MATCH(DMI_BIOS_VERSION, "6.00 PG"),
+ },
+ },
+ { NULL }
+};
static int __init rhine_init(void)
{
@@ -2002,6 +2020,16 @@ static int __init rhine_init(void)
#ifdef MODULE
printk(version);
#endif
+ if (dmi_check_system(rhine_dmi_table)) {
+ /* these BIOSes fail at PXE boot if chip is in D3 */
+ avoid_D3 = 1;
+ printk(KERN_WARNING "%s: Broken BIOS detected, avoid_D3 "
+ "enabled.\n",
+ DRV_NAME);
+ }
+ else if (avoid_D3)
+ printk(KERN_INFO "%s: avoid_D3 set.\n", DRV_NAME);
+
return pci_register_driver(&rhine_driver);
}
diff --git a/drivers/net/wan/lmc/lmc_media.h b/drivers/net/wan/lmc/lmc_media.h
deleted file mode 100644
index ddcc00403563..000000000000
--- a/drivers/net/wan/lmc/lmc_media.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef _LMC_MEDIA_H_
-#define _LMC_MEDIA_H_
-
-lmc_media_t lmc_ds3_media = {
- lmc_ds3_init, /* special media init stuff */
- lmc_ds3_default, /* reset to default state */
- lmc_ds3_set_status, /* reset status to state provided */
- lmc_dummy_set_1, /* set clock source */
- lmc_dummy_set2_1, /* set line speed */
- lmc_ds3_set_100ft, /* set cable length */
- lmc_ds3_set_scram, /* set scrambler */
- lmc_ds3_get_link_status, /* get link status */
- lmc_dummy_set_1, /* set link status */
- lmc_ds3_set_crc_length, /* set CRC length */
- lmc_dummy_set_1, /* set T1 or E1 circuit type */
- lmc_ds3_watchdog
-};
-
-lmc_media_t lmc_hssi_media = {
- lmc_hssi_init, /* special media init stuff */
- lmc_hssi_default, /* reset to default state */
- lmc_hssi_set_status, /* reset status to state provided */
- lmc_hssi_set_clock, /* set clock source */
- lmc_dummy_set2_1, /* set line speed */
- lmc_dummy_set_1, /* set cable length */
- lmc_dummy_set_1, /* set scrambler */
- lmc_hssi_get_link_status, /* get link status */
- lmc_hssi_set_link_status, /* set link status */
- lmc_hssi_set_crc_length, /* set CRC length */
- lmc_dummy_set_1, /* set T1 or E1 circuit type */
- lmc_hssi_watchdog
-};
-
-lmc_media_t lmc_ssi_media = { lmc_ssi_init, /* special media init stuff */
- lmc_ssi_default, /* reset to default state */
- lmc_ssi_set_status, /* reset status to state provided */
- lmc_ssi_set_clock, /* set clock source */
- lmc_ssi_set_speed, /* set line speed */
- lmc_dummy_set_1, /* set cable length */
- lmc_dummy_set_1, /* set scrambler */
- lmc_ssi_get_link_status, /* get link status */
- lmc_ssi_set_link_status, /* set link status */
- lmc_ssi_set_crc_length, /* set CRC length */
- lmc_dummy_set_1, /* set T1 or E1 circuit type */
- lmc_ssi_watchdog
-};
-
-lmc_media_t lmc_t1_media = {
- lmc_t1_init, /* special media init stuff */
- lmc_t1_default, /* reset to default state */
- lmc_t1_set_status, /* reset status to state provided */
- lmc_t1_set_clock, /* set clock source */
- lmc_dummy_set2_1, /* set line speed */
- lmc_dummy_set_1, /* set cable length */
- lmc_dummy_set_1, /* set scrambler */
- lmc_t1_get_link_status, /* get link status */
- lmc_dummy_set_1, /* set link status */
- lmc_t1_set_crc_length, /* set CRC length */
- lmc_t1_set_circuit_type, /* set T1 or E1 circuit type */
- lmc_t1_watchdog
-};
-
-
-#endif
-
diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c
index 8dbcf83bb5f3..8b4540bfc1b0 100644
--- a/drivers/net/wan/z85230.c
+++ b/drivers/net/wan/z85230.c
@@ -407,7 +407,7 @@ static void z8530_tx(struct z8530_channel *c)
while(c->txcount) {
/* FIFO full ? */
if(!(read_zsreg(c, R0)&4))
- break;
+ return;
c->txcount--;
/*
* Shovel out the byte
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index a8c2bfe26c27..2ada76a93cb6 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -2852,7 +2852,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
if (rc) {
airo_print_err(dev->name, "register interrupt %d failed, rc %d",
irq, rc);
- goto err_out_unlink;
+ goto err_out_nets;
}
if (!is_pcmcia) {
if (!request_region( dev->base_addr, 64, dev->name )) {
@@ -2935,6 +2935,8 @@ err_out_res:
release_region( dev->base_addr, 64 );
err_out_irq:
free_irq(dev->irq, dev);
+err_out_nets:
+ airo_networks_free(ai);
err_out_unlink:
del_airo_dev(dev);
err_out_thr:
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index e594af46ff05..a38e7eec0e62 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -946,6 +946,7 @@ static int bcm43xx_geo_init(struct bcm43xx_private *bcm)
u8 channel;
struct bcm43xx_phyinfo *phy;
const char *iso_country;
+ u8 max_bg_channel;
geo = kzalloc(sizeof(*geo), GFP_KERNEL);
if (!geo)
@@ -967,6 +968,23 @@ static int bcm43xx_geo_init(struct bcm43xx_private *bcm)
}
iso_country = bcm43xx_locale_iso(bcm->sprom.locale);
+/* set the maximum channel based on locale set in sprom or witle locale option */
+ switch (bcm->sprom.locale) {
+ case BCM43xx_LOCALE_THAILAND:
+ case BCM43xx_LOCALE_ISRAEL:
+ case BCM43xx_LOCALE_JORDAN:
+ case BCM43xx_LOCALE_USA_CANADA_ANZ:
+ case BCM43xx_LOCALE_USA_LOW:
+ max_bg_channel = 11;
+ break;
+ case BCM43xx_LOCALE_JAPAN:
+ case BCM43xx_LOCALE_JAPAN_HIGH:
+ max_bg_channel = 14;
+ break;
+ default:
+ max_bg_channel = 13;
+ }
+
if (have_a) {
for (i = 0, channel = IEEE80211_52GHZ_MIN_CHANNEL;
channel <= IEEE80211_52GHZ_MAX_CHANNEL; channel++) {
@@ -978,7 +996,7 @@ static int bcm43xx_geo_init(struct bcm43xx_private *bcm)
}
if (have_bg) {
for (i = 0, channel = IEEE80211_24GHZ_MIN_CHANNEL;
- channel <= IEEE80211_24GHZ_MAX_CHANNEL; channel++) {
+ channel <= max_bg_channel; channel++) {
chan = &geo->bg[i++];
chan->freq = bcm43xx_channel_to_freq_bg(channel);
chan->channel = channel;
@@ -1858,9 +1876,6 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id)
spin_lock(&bcm->irq_lock);
- assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
- assert(bcm->current_core->id == BCM43xx_COREID_80211);
-
reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
if (reason == 0xffffffff) {
/* irq not for us (shared irq) */
@@ -1871,6 +1886,9 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id)
if (!reason)
goto out;
+ assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
+ assert(bcm->current_core->id == BCM43xx_COREID_80211);
+
bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA0_REASON)
& 0x0001DC00;
bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
index 3a5c9c2b2150..72529a440f15 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -757,7 +757,7 @@ static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm)
if (radio->version == 0x2050)
bcm43xx_phy_write(bcm, 0x0038, 0x0667);
- if (phy->type == BCM43xx_PHYTYPE_G) {
+ if (phy->connected) {
if (radio->version == 0x2050) {
bcm43xx_radio_write16(bcm, 0x007A,
bcm43xx_radio_read16(bcm, 0x007A)
@@ -859,6 +859,11 @@ static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm)
bcm43xx_radio_write16(bcm, 0x005D, 0x0088);
bcm43xx_radio_write16(bcm, 0x005E, 0x0088);
bcm43xx_radio_write16(bcm, 0x007D, 0x0088);
+ bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+ BCM43xx_UCODEFLAGS_OFFSET,
+ (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+ BCM43xx_UCODEFLAGS_OFFSET)
+ | 0x00000200));
}
if (radio->revision == 8) {
bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
@@ -941,7 +946,8 @@ static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm)
bcm43xx_phy_write(bcm, 0x0038, 0x0668);
bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
if (radio->revision <= 5)
- bcm43xx_phy_write(bcm, 0x005D, bcm43xx_phy_read(bcm, 0x005D) | 0x0003);
+ bcm43xx_phy_write(bcm, 0x005D, (bcm43xx_phy_read(bcm, 0x005D)
+ & 0xFF80) | 0x0003);
if (radio->revision <= 2)
bcm43xx_radio_write16(bcm, 0x005D, 0x000D);
@@ -958,7 +964,7 @@ static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm)
bcm43xx_phy_write(bcm, 0x0016, 0x0410);
bcm43xx_phy_write(bcm, 0x0017, 0x0820);
bcm43xx_phy_write(bcm, 0x0062, 0x0007);
- (void) bcm43xx_radio_calibrationvalue(bcm);
+ bcm43xx_radio_init2050(bcm);
bcm43xx_phy_lo_g_measure(bcm);
if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
bcm43xx_calc_nrssi_slope(bcm);
@@ -972,7 +978,7 @@ static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm)
{
struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
- u16 backup_phy[15];
+ u16 backup_phy[15] = {0};
u16 backup_radio[3];
u16 backup_bband;
u16 i;
@@ -983,8 +989,10 @@ static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm)
backup_phy[1] = bcm43xx_phy_read(bcm, 0x0001);
backup_phy[2] = bcm43xx_phy_read(bcm, 0x0811);
backup_phy[3] = bcm43xx_phy_read(bcm, 0x0812);
- backup_phy[4] = bcm43xx_phy_read(bcm, 0x0814);
- backup_phy[5] = bcm43xx_phy_read(bcm, 0x0815);
+ if (phy->rev != 1) {
+ backup_phy[4] = bcm43xx_phy_read(bcm, 0x0814);
+ backup_phy[5] = bcm43xx_phy_read(bcm, 0x0815);
+ }
backup_phy[6] = bcm43xx_phy_read(bcm, 0x005A);
backup_phy[7] = bcm43xx_phy_read(bcm, 0x0059);
backup_phy[8] = bcm43xx_phy_read(bcm, 0x0058);
@@ -1012,14 +1020,16 @@ static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm)
bcm43xx_phy_read(bcm, 0x0811) | 0x0001);
bcm43xx_phy_write(bcm, 0x0812,
bcm43xx_phy_read(bcm, 0x0812) & 0xFFFE);
- bcm43xx_phy_write(bcm, 0x0814,
- bcm43xx_phy_read(bcm, 0x0814) | 0x0001);
- bcm43xx_phy_write(bcm, 0x0815,
- bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE);
- bcm43xx_phy_write(bcm, 0x0814,
- bcm43xx_phy_read(bcm, 0x0814) | 0x0002);
- bcm43xx_phy_write(bcm, 0x0815,
- bcm43xx_phy_read(bcm, 0x0815) & 0xFFFD);
+ if (phy->rev != 1) {
+ bcm43xx_phy_write(bcm, 0x0814,
+ bcm43xx_phy_read(bcm, 0x0814) | 0x0001);
+ bcm43xx_phy_write(bcm, 0x0815,
+ bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE);
+ bcm43xx_phy_write(bcm, 0x0814,
+ bcm43xx_phy_read(bcm, 0x0814) | 0x0002);
+ bcm43xx_phy_write(bcm, 0x0815,
+ bcm43xx_phy_read(bcm, 0x0815) & 0xFFFD);
+ }
bcm43xx_phy_write(bcm, 0x0811,
bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
bcm43xx_phy_write(bcm, 0x0812,
@@ -1042,10 +1052,12 @@ static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm)
bcm43xx_phy_read(bcm, 0x000A)
| 0x2000);
}
- bcm43xx_phy_write(bcm, 0x0814,
- bcm43xx_phy_read(bcm, 0x0814) | 0x0004);
- bcm43xx_phy_write(bcm, 0x0815,
- bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB);
+ if (phy->rev != 1) {
+ bcm43xx_phy_write(bcm, 0x0814,
+ bcm43xx_phy_read(bcm, 0x0814) | 0x0004);
+ bcm43xx_phy_write(bcm, 0x0815,
+ bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB);
+ }
bcm43xx_phy_write(bcm, 0x0003,
(bcm43xx_phy_read(bcm, 0x0003)
& 0xFF9F) | 0x0040);
@@ -1132,8 +1144,10 @@ static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm)
}
}
- bcm43xx_phy_write(bcm, 0x0814, backup_phy[4]);
- bcm43xx_phy_write(bcm, 0x0815, backup_phy[5]);
+ if (phy->rev != 1) {
+ bcm43xx_phy_write(bcm, 0x0814, backup_phy[4]);
+ bcm43xx_phy_write(bcm, 0x0815, backup_phy[5]);
+ }
bcm43xx_phy_write(bcm, 0x005A, backup_phy[6]);
bcm43xx_phy_write(bcm, 0x0059, backup_phy[7]);
bcm43xx_phy_write(bcm, 0x0058, backup_phy[8]);
@@ -1182,24 +1196,23 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
bcm43xx_phy_write(bcm, 0x0811, 0x0000);
bcm43xx_phy_write(bcm, 0x0015, 0x00C0);
}
- if (phy->rev >= 3) {
+ if (phy->rev > 5) {
bcm43xx_phy_write(bcm, 0x0811, 0x0400);
bcm43xx_phy_write(bcm, 0x0015, 0x00C0);
}
- if (phy->connected) {
+ if (phy->rev >= 2 && phy->connected) {
tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF;
- if (tmp < 6) {
+ if (tmp ==3 || tmp == 5) {
bcm43xx_phy_write(bcm, 0x04C2, 0x1816);
bcm43xx_phy_write(bcm, 0x04C3, 0x8006);
- if (tmp != 3) {
+ if (tmp == 5) {
bcm43xx_phy_write(bcm, 0x04CC,
(bcm43xx_phy_read(bcm, 0x04CC)
& 0x00FF) | 0x1F00);
}
}
- }
- if (phy->rev < 3 && phy->connected)
bcm43xx_phy_write(bcm, 0x047E, 0x0078);
+ }
if (radio->revision == 8) {
bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) | 0x0080);
bcm43xx_phy_write(bcm, 0x043E, bcm43xx_phy_read(bcm, 0x043E) | 0x0004);
@@ -1226,7 +1239,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
if (phy->rev >= 6) {
bcm43xx_phy_write(bcm, 0x0036,
(bcm43xx_phy_read(bcm, 0x0036)
- & 0xF000) | (radio->txctl2 << 12));
+ & 0x0FFF) | (radio->txctl2 << 12));
}
if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
bcm43xx_phy_write(bcm, 0x002E, 0x8075);
@@ -1237,7 +1250,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
else
bcm43xx_phy_write(bcm, 0x002F, 0x0202);
}
- if (phy->connected) {
+ if (phy->connected || phy->rev >= 2) {
bcm43xx_phy_lo_adjust(bcm, 0);
bcm43xx_phy_write(bcm, 0x080F, 0x8078);
}
@@ -1251,7 +1264,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
*/
bcm43xx_nrssi_hw_update(bcm, 0xFFFF);
bcm43xx_calc_nrssi_threshold(bcm);
- } else if (phy->connected) {
+ } else if (phy->connected || phy->rev >= 2) {
if (radio->nrssi[0] == -1000) {
assert(radio->nrssi[1] == -1000);
bcm43xx_calc_nrssi_slope(bcm);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
index 32beb91b7164..4025dd0089d2 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
@@ -458,7 +458,7 @@ static void bcm43xx_calc_nrssi_offset(struct bcm43xx_private *bcm)
bcm43xx_phy_write(bcm, 0x005A, 0x0480);
bcm43xx_phy_write(bcm, 0x0059, 0x0810);
bcm43xx_phy_write(bcm, 0x0058, 0x000D);
- if (phy->rev == 0) {
+ if (phy->analog == 0) {
bcm43xx_phy_write(bcm, 0x0003, 0x0122);
} else {
bcm43xx_phy_write(bcm, 0x000A,
@@ -570,9 +570,9 @@ void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm)
nrssi0 = (s16)bcm43xx_phy_read(bcm, 0x0027);
bcm43xx_radio_write16(bcm, 0x007A,
bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
- if (phy->rev >= 2) {
+ if (phy->analog >= 2) {
bcm43xx_write16(bcm, 0x03E6, 0x0040);
- } else if (phy->rev == 0) {
+ } else if (phy->analog == 0) {
bcm43xx_write16(bcm, 0x03E6, 0x0122);
} else {
bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
@@ -596,7 +596,7 @@ void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm)
bcm43xx_phy_write(bcm, 0x0015, backup[5]);
bcm43xx_phy_write(bcm, 0x002A, backup[6]);
bcm43xx_synth_pu_workaround(bcm, radio->channel);
- if (phy->rev != 0)
+ if (phy->analog != 0)
bcm43xx_write16(bcm, 0x03F4, backup[13]);
bcm43xx_phy_write(bcm, 0x0020, backup[7]);
@@ -692,7 +692,7 @@ void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm)
bcm43xx_radio_write16(bcm, 0x007A,
bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
- if (phy->rev >= 2) {
+ if (phy->analog >= 2) {
bcm43xx_phy_write(bcm, 0x0003,
(bcm43xx_phy_read(bcm, 0x0003)
& 0xFF9F) | 0x0040);
@@ -882,10 +882,10 @@ static void _stack_save(u32 *_stackptr, size_t *stackidx,
{
u32 *stackptr = &(_stackptr[*stackidx]);
- assert((offset & 0xF000) == 0x0000);
- assert((id & 0xF0) == 0x00);
+ assert((offset & 0xE000) == 0x0000);
+ assert((id & 0xF8) == 0x00);
*stackptr = offset;
- *stackptr |= ((u32)id) << 12;
+ *stackptr |= ((u32)id) << 13;
*stackptr |= ((u32)value) << 16;
(*stackidx)++;
assert(*stackidx < BCM43xx_INTERFSTACK_SIZE);
@@ -896,12 +896,12 @@ static u16 _stack_restore(u32 *stackptr,
{
size_t i;
- assert((offset & 0xF000) == 0x0000);
- assert((id & 0xF0) == 0x00);
+ assert((offset & 0xE000) == 0x0000);
+ assert((id & 0xF8) == 0x00);
for (i = 0; i < BCM43xx_INTERFSTACK_SIZE; i++, stackptr++) {
- if ((*stackptr & 0x00000FFF) != offset)
+ if ((*stackptr & 0x00001FFF) != offset)
continue;
- if (((*stackptr & 0x0000F000) >> 12) != id)
+ if (((*stackptr & 0x00007000) >> 13) != id)
continue;
return ((*stackptr & 0xFFFF0000) >> 16);
}
@@ -1579,7 +1579,7 @@ void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm)
for (i = 0; i < 5; i++) {
for (j = 0; j < 5; j++) {
- if (tmp == (data_high[i] << 4 | data_low[j])) {
+ if (tmp == (data_high[i] | data_low[j])) {
bcm43xx_phy_write(bcm, 0x0069, (i - j) << 8 | 0x00C0);
return;
}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
index 7b665e2386a8..d6d9413d7f23 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -105,18 +105,24 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
unsigned long flags;
u8 channel;
+ s8 expon;
int freq;
int err = -EINVAL;
mutex_lock(&bcm->mutex);
spin_lock_irqsave(&bcm->irq_lock, flags);
- if ((data->freq.m >= 0) && (data->freq.m <= 1000)) {
+ if ((data->freq.e == 0) &&
+ (data->freq.m >= 0) && (data->freq.m <= 1000)) {
channel = data->freq.m;
freq = bcm43xx_channel_to_freq(bcm, channel);
} else {
- channel = bcm43xx_freq_to_channel(bcm, data->freq.m);
freq = data->freq.m;
+ expon = 6 - data->freq.e;
+ while (--expon >= 0) /* scale down the frequency to MHz */
+ freq /= 10;
+ assert(freq > 1000);
+ channel = bcm43xx_freq_to_channel(bcm, freq);
}
if (!ieee80211_is_valid_channel(bcm->ieee, channel))
goto out_unlock;
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 9c64f894b71b..87ee3ee020fe 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -337,6 +337,7 @@ static int read_pod(struct zd_chip *chip, u8 *rf_type)
chip->patch_cr157 = (value >> 13) & 0x1;
chip->patch_6m_band_edge = (value >> 21) & 0x1;
chip->new_phy_layout = (value >> 31) & 0x1;
+ chip->al2230s_bit = (value >> 7) & 0x1;
chip->link_led = ((value >> 4) & 1) ? LED1 : LED2;
chip->supports_tx_led = 1;
if (value & (1 << 24)) { /* LED scenario */
@@ -591,16 +592,16 @@ int zd_chip_unlock_phy_regs(struct zd_chip *chip)
return r;
}
-/* CR157 can be optionally patched by the EEPROM */
+/* CR157 can be optionally patched by the EEPROM for original ZD1211 */
static int patch_cr157(struct zd_chip *chip)
{
int r;
- u32 value;
+ u16 value;
if (!chip->patch_cr157)
return 0;
- r = zd_ioread32_locked(chip, &value, E2P_PHY_REG);
+ r = zd_ioread16_locked(chip, &value, E2P_PHY_REG);
if (r)
return r;
@@ -790,11 +791,6 @@ static int zd1211b_hw_reset_phy(struct zd_chip *chip)
goto out;
r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
- if (r)
- goto unlock;
-
- r = patch_cr157(chip);
-unlock:
t = zd_chip_unlock_phy_regs(chip);
if (t && !r)
r = t;
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index b07569e391ee..e57ed75d9425 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -641,8 +641,8 @@ enum {
* also only 11 channels. */
#define E2P_ALLOWED_CHANNEL E2P_DATA(0x18)
-#define E2P_PHY_REG E2P_DATA(0x1a)
#define E2P_DEVICE_VER E2P_DATA(0x20)
+#define E2P_PHY_REG E2P_DATA(0x25)
#define E2P_36M_CAL_VALUE1 E2P_DATA(0x28)
#define E2P_36M_CAL_VALUE2 E2P_DATA(0x2a)
#define E2P_36M_CAL_VALUE3 E2P_DATA(0x2c)
@@ -711,7 +711,7 @@ struct zd_chip {
u16 link_led;
unsigned int pa_type:4,
patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1,
- new_phy_layout:1,
+ new_phy_layout:1, al2230s_bit:1,
is_zd1211b:1, supports_tx_led:1;
};
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
index 25323a13a3db..5235a7827ac5 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
@@ -358,6 +358,12 @@ int zd_rf_init_al2230(struct zd_rf *rf)
{
struct zd_chip *chip = zd_rf_to_chip(rf);
+ if (chip->al2230s_bit) {
+ dev_err(zd_chip_dev(chip), "AL2230S devices are not yet "
+ "supported by this driver.\n");
+ return -ENODEV;
+ }
+
rf->switch_radio_off = al2230_switch_radio_off;
if (chip->is_zd1211b) {
rf->init_hw = zd1211b_al2230_init_hw;
diff --git a/drivers/oprofile/event_buffer.c b/drivers/oprofile/event_buffer.c
index 00e937e9240e..e7fbac529935 100644
--- a/drivers/oprofile/event_buffer.c
+++ b/drivers/oprofile/event_buffer.c
@@ -70,11 +70,12 @@ void wake_up_buffer_waiter(void)
int alloc_event_buffer(void)
{
int err = -ENOMEM;
+ unsigned long flags;
- spin_lock(&oprofilefs_lock);
+ spin_lock_irqsave(&oprofilefs_lock, flags);
buffer_size = fs_buffer_size;
buffer_watershed = fs_buffer_watershed;
- spin_unlock(&oprofilefs_lock);
+ spin_unlock_irqrestore(&oprofilefs_lock, flags);
if (buffer_watershed >= buffer_size)
return -EINVAL;
diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c
index 6e67b42ca46d..8543cb26cf34 100644
--- a/drivers/oprofile/oprofilefs.c
+++ b/drivers/oprofile/oprofilefs.c
@@ -65,6 +65,7 @@ ssize_t oprofilefs_ulong_to_user(unsigned long val, char __user * buf, size_t co
int oprofilefs_ulong_from_user(unsigned long * val, char const __user * buf, size_t count)
{
char tmpbuf[TMPBUFSIZE];
+ unsigned long flags;
if (!count)
return 0;
@@ -77,9 +78,9 @@ int oprofilefs_ulong_from_user(unsigned long * val, char const __user * buf, siz
if (copy_from_user(tmpbuf, buf, count))
return -EFAULT;
- spin_lock(&oprofilefs_lock);
+ spin_lock_irqsave(&oprofilefs_lock, flags);
*val = simple_strtoul(tmpbuf, NULL, 0);
- spin_unlock(&oprofilefs_lock);
+ spin_unlock_irqrestore(&oprofilefs_lock, flags);
return 0;
}
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 01869b1782e4..435c1958a7b7 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -94,12 +94,14 @@ static void msi_set_mask_bit(unsigned int irq, int flag)
int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET;
writel(flag, entry->mask_base + offset);
+ readl(entry->mask_base + offset);
break;
}
default:
BUG();
break;
}
+ entry->msi_attrib.masked = !!flag;
}
void read_msi_msg(unsigned int irq, struct msi_msg *msg)
@@ -179,6 +181,7 @@ void write_msi_msg(unsigned int irq, struct msi_msg *msg)
default:
BUG();
}
+ entry->msg = *msg;
}
void mask_msi_irq(unsigned int irq)
@@ -225,164 +228,60 @@ static struct msi_desc* alloc_msi_entry(void)
}
#ifdef CONFIG_PM
-static int __pci_save_msi_state(struct pci_dev *dev)
-{
- int pos, i = 0;
- u16 control;
- struct pci_cap_saved_state *save_state;
- u32 *cap;
-
- if (!dev->msi_enabled)
- return 0;
-
- pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
- if (pos <= 0)
- return 0;
-
- save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u32) * 5,
- GFP_KERNEL);
- if (!save_state) {
- printk(KERN_ERR "Out of memory in pci_save_msi_state\n");
- return -ENOMEM;
- }
- cap = &save_state->data[0];
-
- pci_read_config_dword(dev, pos, &cap[i++]);
- control = cap[0] >> 16;
- pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, &cap[i++]);
- if (control & PCI_MSI_FLAGS_64BIT) {
- pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, &cap[i++]);
- pci_read_config_dword(dev, pos + PCI_MSI_DATA_64, &cap[i++]);
- } else
- pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, &cap[i++]);
- if (control & PCI_MSI_FLAGS_MASKBIT)
- pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, &cap[i++]);
- save_state->cap_nr = PCI_CAP_ID_MSI;
- pci_add_saved_cap(dev, save_state);
- return 0;
-}
-
static void __pci_restore_msi_state(struct pci_dev *dev)
{
- int i = 0, pos;
+ int pos;
u16 control;
- struct pci_cap_saved_state *save_state;
- u32 *cap;
+ struct msi_desc *entry;
if (!dev->msi_enabled)
return;
- save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSI);
- pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
- if (!save_state || pos <= 0)
- return;
- cap = &save_state->data[0];
+ entry = get_irq_msi(dev->irq);
+ pos = entry->msi_attrib.pos;
pci_intx(dev, 0); /* disable intx */
- control = cap[i++] >> 16;
msi_set_enable(dev, 0);
- pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, cap[i++]);
- if (control & PCI_MSI_FLAGS_64BIT) {
- pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, cap[i++]);
- pci_write_config_dword(dev, pos + PCI_MSI_DATA_64, cap[i++]);
- } else
- pci_write_config_dword(dev, pos + PCI_MSI_DATA_32, cap[i++]);
- if (control & PCI_MSI_FLAGS_MASKBIT)
- pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT, cap[i++]);
+ write_msi_msg(dev->irq, &entry->msg);
+ if (entry->msi_attrib.maskbit)
+ msi_set_mask_bit(dev->irq, entry->msi_attrib.masked);
+
+ pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
+ control &= ~(PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE);
+ if (entry->msi_attrib.maskbit || !entry->msi_attrib.masked)
+ control |= PCI_MSI_FLAGS_ENABLE;
pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
- pci_remove_saved_cap(save_state);
- kfree(save_state);
-}
-
-static int __pci_save_msix_state(struct pci_dev *dev)
-{
- int pos;
- int irq, head, tail = 0;
- u16 control;
- struct pci_cap_saved_state *save_state;
-
- if (!dev->msix_enabled)
- return 0;
-
- pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
- if (pos <= 0)
- return 0;
-
- /* save the capability */
- pci_read_config_word(dev, msi_control_reg(pos), &control);
- save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u16),
- GFP_KERNEL);
- if (!save_state) {
- printk(KERN_ERR "Out of memory in pci_save_msix_state\n");
- return -ENOMEM;
- }
- *((u16 *)&save_state->data[0]) = control;
-
- /* save the table */
- irq = head = dev->first_msi_irq;
- while (head != tail) {
- struct msi_desc *entry;
-
- entry = get_irq_msi(irq);
- read_msi_msg(irq, &entry->msg_save);
-
- tail = entry->link.tail;
- irq = tail;
- }
-
- save_state->cap_nr = PCI_CAP_ID_MSIX;
- pci_add_saved_cap(dev, save_state);
- return 0;
-}
-
-int pci_save_msi_state(struct pci_dev *dev)
-{
- int rc;
-
- rc = __pci_save_msi_state(dev);
- if (rc)
- return rc;
-
- rc = __pci_save_msix_state(dev);
-
- return rc;
}
static void __pci_restore_msix_state(struct pci_dev *dev)
{
- u16 save;
int pos;
int irq, head, tail = 0;
struct msi_desc *entry;
- struct pci_cap_saved_state *save_state;
+ u16 control;
if (!dev->msix_enabled)
return;
- save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSIX);
- if (!save_state)
- return;
- save = *((u16 *)&save_state->data[0]);
- pci_remove_saved_cap(save_state);
- kfree(save_state);
-
- pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
- if (pos <= 0)
- return;
-
/* route the table */
pci_intx(dev, 0); /* disable intx */
msix_set_enable(dev, 0);
irq = head = dev->first_msi_irq;
+ entry = get_irq_msi(irq);
+ pos = entry->msi_attrib.pos;
while (head != tail) {
entry = get_irq_msi(irq);
- write_msi_msg(irq, &entry->msg_save);
+ write_msi_msg(irq, &entry->msg);
+ msi_set_mask_bit(irq, entry->msi_attrib.masked);
tail = entry->link.tail;
irq = tail;
}
- pci_write_config_word(dev, msi_control_reg(pos), save);
+ pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
+ control &= ~PCI_MSIX_FLAGS_MASKALL;
+ control |= PCI_MSIX_FLAGS_ENABLE;
+ pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
}
void pci_restore_msi_state(struct pci_dev *dev)
@@ -420,6 +319,7 @@ static int msi_capability_init(struct pci_dev *dev)
entry->msi_attrib.is_64 = is_64bit_address(control);
entry->msi_attrib.entry_nr = 0;
entry->msi_attrib.maskbit = is_mask_bit_support(control);
+ entry->msi_attrib.masked = 1;
entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */
entry->msi_attrib.pos = pos;
if (is_mask_bit_support(control)) {
@@ -507,6 +407,7 @@ static int msix_capability_init(struct pci_dev *dev,
entry->msi_attrib.is_64 = 1;
entry->msi_attrib.entry_nr = j;
entry->msi_attrib.maskbit = 1;
+ entry->msi_attrib.masked = 1;
entry->msi_attrib.default_irq = dev->irq;
entry->msi_attrib.pos = pos;
entry->dev = dev;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index df495300ce3d..d3eab057b2d3 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -551,7 +551,9 @@ static int pci_save_pcie_state(struct pci_dev *dev)
if (pos <= 0)
return 0;
- save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL);
+ save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
+ if (!save_state)
+ save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL);
if (!save_state) {
dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
return -ENOMEM;
@@ -582,8 +584,6 @@ static void pci_restore_pcie_state(struct pci_dev *dev)
pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, cap[i++]);
pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]);
pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]);
- pci_remove_saved_cap(save_state);
- kfree(save_state);
}
@@ -597,7 +597,9 @@ static int pci_save_pcix_state(struct pci_dev *dev)
if (pos <= 0)
return 0;
- save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL);
+ save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
+ if (!save_state)
+ save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL);
if (!save_state) {
dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
return -ENOMEM;
@@ -622,8 +624,6 @@ static void pci_restore_pcix_state(struct pci_dev *dev)
cap = (u16 *)&save_state->data[0];
pci_write_config_word(dev, pos + PCI_X_CMD, cap[i++]);
- pci_remove_saved_cap(save_state);
- kfree(save_state);
}
@@ -638,8 +638,6 @@ pci_save_state(struct pci_dev *dev)
/* XXX: 100% dword access ok here? */
for (i = 0; i < 16; i++)
pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]);
- if ((i = pci_save_msi_state(dev)) != 0)
- return i;
if ((i = pci_save_pcie_state(dev)) != 0)
return i;
if ((i = pci_save_pcix_state(dev)) != 0)
@@ -757,7 +755,8 @@ int pci_enable_device(struct pci_dev *dev)
* when a device is enabled using managed PCI device enable interface.
*/
struct pci_devres {
- unsigned int disable:1;
+ unsigned int enabled:1;
+ unsigned int pinned:1;
unsigned int orig_intx:1;
unsigned int restore_intx:1;
u32 region_mask;
@@ -781,7 +780,7 @@ static void pcim_release(struct device *gendev, void *res)
if (this->restore_intx)
pci_intx(dev, this->orig_intx);
- if (this->disable)
+ if (this->enabled && !this->pinned)
pci_disable_device(dev);
}
@@ -820,12 +819,12 @@ int pcim_enable_device(struct pci_dev *pdev)
dr = get_pci_dr(pdev);
if (unlikely(!dr))
return -ENOMEM;
- WARN_ON(!!dr->disable);
+ WARN_ON(!!dr->enabled);
rc = pci_enable_device(pdev);
if (!rc) {
pdev->is_managed = 1;
- dr->disable = 1;
+ dr->enabled = 1;
}
return rc;
}
@@ -843,9 +842,9 @@ void pcim_pin_device(struct pci_dev *pdev)
struct pci_devres *dr;
dr = find_pci_dr(pdev);
- WARN_ON(!dr || !dr->disable);
+ WARN_ON(!dr || !dr->enabled);
if (dr)
- dr->disable = 0;
+ dr->pinned = 1;
}
/**
@@ -876,7 +875,7 @@ pci_disable_device(struct pci_dev *dev)
dr = find_pci_dr(dev);
if (dr)
- dr->disable = 0;
+ dr->enabled = 0;
if (atomic_sub_return(1, &dev->enable_cnt) != 0)
return;
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index ae7a975995a5..62ea04c8af64 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -52,10 +52,8 @@ static inline void pci_no_msi(void) { }
#endif
#if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM)
-int pci_save_msi_state(struct pci_dev *dev);
void pci_restore_msi_state(struct pci_dev *dev);
#else
-static inline int pci_save_msi_state(struct pci_dev *dev) { return 0; }
static inline void pci_restore_msi_state(struct pci_dev *dev) {}
#endif
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
index b164de050d4f..db6ad8e763ac 100644
--- a/drivers/pci/pcie/aer/aerdrv.c
+++ b/drivers/pci/pcie/aer/aerdrv.c
@@ -66,7 +66,7 @@ static struct pci_error_handlers aer_error_handlers = {
.resume = aer_error_resume,
};
-static struct pcie_port_service_driver aerdrv = {
+static struct pcie_port_service_driver aerdriver = {
.name = "aer",
.id_table = &aer_id[0],
@@ -328,7 +328,7 @@ static void aer_error_resume(struct pci_dev *dev)
**/
static int __init aer_service_init(void)
{
- return pcie_port_service_register(&aerdrv);
+ return pcie_port_service_register(&aerdriver);
}
/**
@@ -338,7 +338,7 @@ static int __init aer_service_init(void)
**/
static void __exit aer_service_exit(void)
{
- pcie_port_service_unregister(&aerdrv);
+ pcie_port_service_unregister(&aerdriver);
}
module_init(aer_service_init);
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index f17e7ed2b2a5..df383645e366 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -93,7 +93,7 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev,
if (!dev->irq && dev->pin) {
printk(KERN_WARNING
"%s->Dev[%04x:%04x] has invalid IRQ. Check vendor BIOS\n",
- __FUNCTION__, dev->device, dev->vendor);
+ __FUNCTION__, dev->vendor, dev->device);
}
if (pcie_port_device_register(dev)) {
pci_disable_device(dev);
@@ -276,7 +276,7 @@ static struct pci_error_handlers pcie_portdrv_err_handler = {
.resume = pcie_portdrv_err_resume,
};
-static struct pci_driver pcie_portdrv = {
+static struct pci_driver pcie_portdriver = {
.name = (char *)device_name,
.id_table = &port_pci_ids[0],
@@ -298,7 +298,7 @@ static int __init pcie_portdrv_init(void)
printk(KERN_WARNING "PCIE: bus_register error: %d\n", retval);
goto out;
}
- retval = pci_register_driver(&pcie_portdrv);
+ retval = pci_register_driver(&pcie_portdriver);
if (retval)
pcie_port_bus_unregister();
out:
@@ -307,7 +307,7 @@ static int __init pcie_portdrv_init(void)
static void __exit pcie_portdrv_exit(void)
{
- pci_unregister_driver(&pcie_portdrv);
+ pci_unregister_driver(&pcie_portdriver);
pcie_port_bus_unregister();
}
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 7f94fc098cd3..65d6f23ead41 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -963,6 +963,13 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_ho
* bridge. Unfortunately, this device has no subvendor/subdevice ID. So it
* becomes necessary to do this tweak in two steps -- I've chosen the Host
* bridge as trigger.
+ *
+ * Note that we used to unhide the SMBus that way on Toshiba laptops
+ * (Satellite A40 and Tecra M2) but then found that the thermal management
+ * was done by SMM code, which could cause unsynchronized concurrent
+ * accesses to the SMBus registers, with potentially bad effects. Thus you
+ * should be very careful when adding new entries: if SMM is accessing the
+ * Intel SMBus, this is a very good reason to leave it hidden.
*/
static int asus_hides_smbus;
@@ -1040,17 +1047,6 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
case 0x099c: /* HP Compaq nx6110 */
asus_hides_smbus = 1;
}
- } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_TOSHIBA)) {
- if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB)
- switch(dev->subsystem_device) {
- case 0x0001: /* Toshiba Satellite A40 */
- asus_hides_smbus = 1;
- }
- else if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB)
- switch(dev->subsystem_device) {
- case 0x0001: /* Toshiba Tecra M2 */
- asus_hides_smbus = 1;
- }
} else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG)) {
if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB)
switch(dev->subsystem_device) {
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index ff98eaddaa73..2dd8681d6b31 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -15,7 +15,7 @@
DECLARE_RWSEM(pci_bus_sem);
-static struct pci_bus * __devinit
+static struct pci_bus *
pci_do_find_bus(struct pci_bus* bus, unsigned char busnr)
{
struct pci_bus* child;
diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c
index 551bde5d9430..b693367d38cd 100644
--- a/drivers/pcmcia/au1000_generic.c
+++ b/drivers/pcmcia/au1000_generic.c
@@ -372,7 +372,7 @@ int au1x00_pcmcia_socket_probe(struct device *dev, struct pcmcia_low_level *ops,
skt->socket.resource_ops = &pccard_static_ops;
skt->socket.ops = &au1x00_pcmcia_operations;
skt->socket.owner = ops->owner;
- skt->socket.dev.dev = dev;
+ skt->socket.dev.parent = dev;
init_timer(&skt->poll_timer);
skt->poll_timer.function = au1x00_pcmcia_poll_event;
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
index d77f75129f8a..2df216b00817 100644
--- a/drivers/pcmcia/omap_cf.c
+++ b/drivers/pcmcia/omap_cf.c
@@ -202,15 +202,14 @@ static struct pccard_operations omap_cf_ops = {
* "what chipselect is used". Boards could want more.
*/
-static int __devinit omap_cf_probe(struct device *dev)
+static int __init omap_cf_probe(struct platform_device *pdev)
{
unsigned seg;
struct omap_cf_socket *cf;
- struct platform_device *pdev = to_platform_device(dev);
int irq;
int status;
- seg = (int) dev->platform_data;
+ seg = (int) pdev->dev.platform_data;
if (seg == 0 || seg > 3)
return -ENODEV;
@@ -227,7 +226,7 @@ static int __devinit omap_cf_probe(struct device *dev)
cf->timer.data = (unsigned long) cf;
cf->pdev = pdev;
- dev_set_drvdata(dev, cf);
+ platform_set_drvdata(pdev, cf);
/* this primarily just shuts up irq handling noise */
status = request_irq(irq, omap_cf_irq, IRQF_SHARED,
@@ -291,7 +290,7 @@ static int __devinit omap_cf_probe(struct device *dev)
omap_cf_present() ? "present" : "(not present)");
cf->socket.owner = THIS_MODULE;
- cf->socket.dev.parent = dev;
+ cf->socket.dev.parent = &pdev->dev;
cf->socket.ops = &omap_cf_ops;
cf->socket.resource_ops = &pccard_static_ops;
cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
@@ -318,9 +317,9 @@ fail0:
return status;
}
-static int __devexit omap_cf_remove(struct device *dev)
+static int __exit omap_cf_remove(struct platform_device *pdev)
{
- struct omap_cf_socket *cf = dev_get_drvdata(dev);
+ struct omap_cf_socket *cf = platform_get_drvdata(pdev);
cf->active = 0;
pcmcia_unregister_socket(&cf->socket);
@@ -332,26 +331,36 @@ static int __devexit omap_cf_remove(struct device *dev)
return 0;
}
-static struct device_driver omap_cf_driver = {
- .name = (char *) driver_name,
- .bus = &platform_bus_type,
- .probe = omap_cf_probe,
- .remove = __devexit_p(omap_cf_remove),
- .suspend = pcmcia_socket_dev_suspend,
- .resume = pcmcia_socket_dev_resume,
+static int omap_cf_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+ return pcmcia_socket_dev_suspend(&pdev->dev, mesg);
+}
+
+static int omap_cf_resume(struct platform_device *pdev)
+{
+ return pcmcia_socket_dev_resume(&pdev->dev);
+}
+
+static struct platform_driver omap_cf_driver = {
+ .driver = {
+ .name = (char *) driver_name,
+ },
+ .remove = __exit_p(omap_cf_remove),
+ .suspend = omap_cf_suspend,
+ .resume = omap_cf_resume,
};
static int __init omap_cf_init(void)
{
if (cpu_is_omap16xx())
- return driver_register(&omap_cf_driver);
+ return platform_driver_probe(&omap_cf_driver, omap_cf_probe);
return -ENODEV;
}
static void __exit omap_cf_exit(void)
{
if (cpu_is_omap16xx())
- driver_unregister(&omap_cf_driver);
+ platform_driver_unregister(&omap_cf_driver);
}
module_init(omap_cf_init);
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index 5026b345cb30..57e6ab1004d0 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -451,7 +451,7 @@ int pnp_auto_config_dev(struct pnp_dev *dev)
return -EINVAL;
if(!pnp_can_configure(dev)) {
- pnp_info("Device %s does not support resource configuration.", dev->dev.bus_id);
+ pnp_dbg("Device %s does not support resource configuration.", dev->dev.bus_id);
return -ENODEV;
}
@@ -482,7 +482,7 @@ int pnp_auto_config_dev(struct pnp_dev *dev)
int pnp_start_dev(struct pnp_dev *dev)
{
if (!pnp_can_write(dev)) {
- pnp_info("Device %s does not support activation.", dev->dev.bus_id);
+ pnp_dbg("Device %s does not support activation.", dev->dev.bus_id);
return -EINVAL;
}
@@ -506,7 +506,7 @@ int pnp_start_dev(struct pnp_dev *dev)
int pnp_stop_dev(struct pnp_dev *dev)
{
if (!pnp_can_disable(dev)) {
- pnp_info("Device %s does not support disabling.", dev->dev.bus_id);
+ pnp_dbg("Device %s does not support disabling.", dev->dev.bus_id);
return -EINVAL;
}
if (dev->protocol->disable(dev)<0) {
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 7a535542fe92..118ac9779b3c 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -89,6 +89,7 @@ pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, u32 gsi,
return;
res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag
+ res->irq_resource[i].flags |= irq_flags(triggering, polarity);
irq = acpi_register_gsi(gsi, triggering, polarity);
if (irq < 0) {
res->irq_resource[i].flags |= IORESOURCE_DISABLED;
@@ -103,8 +104,52 @@ pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, u32 gsi,
pcibios_penalize_isa_irq(irq, 1);
}
+static int dma_flags(int type, int bus_master, int transfer)
+{
+ int flags = 0;
+
+ if (bus_master)
+ flags |= IORESOURCE_DMA_MASTER;
+ switch (type) {
+ case ACPI_COMPATIBILITY:
+ flags |= IORESOURCE_DMA_COMPATIBLE;
+ break;
+ case ACPI_TYPE_A:
+ flags |= IORESOURCE_DMA_TYPEA;
+ break;
+ case ACPI_TYPE_B:
+ flags |= IORESOURCE_DMA_TYPEB;
+ break;
+ case ACPI_TYPE_F:
+ flags |= IORESOURCE_DMA_TYPEF;
+ break;
+ default:
+ /* Set a default value ? */
+ flags |= IORESOURCE_DMA_COMPATIBLE;
+ pnp_err("Invalid DMA type");
+ }
+ switch (transfer) {
+ case ACPI_TRANSFER_8:
+ flags |= IORESOURCE_DMA_8BIT;
+ break;
+ case ACPI_TRANSFER_8_16:
+ flags |= IORESOURCE_DMA_8AND16BIT;
+ break;
+ case ACPI_TRANSFER_16:
+ flags |= IORESOURCE_DMA_16BIT;
+ break;
+ default:
+ /* Set a default value ? */
+ flags |= IORESOURCE_DMA_8AND16BIT;
+ pnp_err("Invalid DMA transfer type");
+ }
+
+ return flags;
+}
+
static void
-pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, u32 dma)
+pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, u32 dma,
+ int type, int bus_master, int transfer)
{
int i = 0;
while (i < PNP_MAX_DMA &&
@@ -112,6 +157,7 @@ pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, u32 dma)
i++;
if (i < PNP_MAX_DMA) {
res->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag
+ res->dma_resource[i].flags |= dma_flags(type, bus_master, transfer);
if (dma == -1) {
res->dma_resource[i].flags |= IORESOURCE_DISABLED;
return;
@@ -123,7 +169,7 @@ pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, u32 dma)
static void
pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res,
- u64 io, u64 len)
+ u64 io, u64 len, int io_decode)
{
int i = 0;
while (!(res->port_resource[i].flags & IORESOURCE_UNSET) &&
@@ -131,6 +177,8 @@ pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res,
i++;
if (i < PNP_MAX_PORT) {
res->port_resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag
+ if (io_decode == ACPI_DECODE_16)
+ res->port_resource[i].flags |= PNP_PORT_FLAG_16BITADDR;
if (len <= 0 || (io + len -1) >= 0x10003) {
res->port_resource[i].flags |= IORESOURCE_DISABLED;
return;
@@ -142,7 +190,7 @@ pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res,
static void
pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res,
- u64 mem, u64 len)
+ u64 mem, u64 len, int write_protect)
{
int i = 0;
while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) &&
@@ -154,6 +202,9 @@ pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res,
res->mem_resource[i].flags |= IORESOURCE_DISABLED;
return;
}
+ if(write_protect == ACPI_READ_WRITE_MEMORY)
+ res->mem_resource[i].flags |= IORESOURCE_MEM_WRITEABLE;
+
res->mem_resource[i].start = mem;
res->mem_resource[i].end = mem + len - 1;
}
@@ -178,10 +229,11 @@ pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table,
if (p->resource_type == ACPI_MEMORY_RANGE)
pnpacpi_parse_allocated_memresource(res_table,
- p->minimum, p->address_length);
+ p->minimum, p->address_length, p->info.mem.write_protect);
else if (p->resource_type == ACPI_IO_RANGE)
pnpacpi_parse_allocated_ioresource(res_table,
- p->minimum, p->address_length);
+ p->minimum, p->address_length,
+ p->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16);
}
static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
@@ -208,13 +260,17 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
case ACPI_RESOURCE_TYPE_DMA:
if (res->data.dma.channel_count > 0)
pnpacpi_parse_allocated_dmaresource(res_table,
- res->data.dma.channels[0]);
+ res->data.dma.channels[0],
+ res->data.dma.type,
+ res->data.dma.bus_master,
+ res->data.dma.transfer);
break;
case ACPI_RESOURCE_TYPE_IO:
pnpacpi_parse_allocated_ioresource(res_table,
res->data.io.minimum,
- res->data.io.address_length);
+ res->data.io.address_length,
+ res->data.io.io_decode);
break;
case ACPI_RESOURCE_TYPE_START_DEPENDENT:
@@ -224,7 +280,8 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
case ACPI_RESOURCE_TYPE_FIXED_IO:
pnpacpi_parse_allocated_ioresource(res_table,
res->data.fixed_io.address,
- res->data.fixed_io.address_length);
+ res->data.fixed_io.address_length,
+ ACPI_DECODE_10);
break;
case ACPI_RESOURCE_TYPE_VENDOR:
@@ -236,17 +293,20 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
case ACPI_RESOURCE_TYPE_MEMORY24:
pnpacpi_parse_allocated_memresource(res_table,
res->data.memory24.minimum,
- res->data.memory24.address_length);
+ res->data.memory24.address_length,
+ res->data.memory24.write_protect);
break;
case ACPI_RESOURCE_TYPE_MEMORY32:
pnpacpi_parse_allocated_memresource(res_table,
res->data.memory32.minimum,
- res->data.memory32.address_length);
+ res->data.memory32.address_length,
+ res->data.memory32.write_protect);
break;
case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
pnpacpi_parse_allocated_memresource(res_table,
res->data.fixed_memory32.address,
- res->data.fixed_memory32.address_length);
+ res->data.fixed_memory32.address_length,
+ res->data.fixed_memory32.write_protect);
break;
case ACPI_RESOURCE_TYPE_ADDRESS16:
case ACPI_RESOURCE_TYPE_ADDRESS32:
@@ -304,42 +364,8 @@ static void pnpacpi_parse_dma_option(struct pnp_option *option, struct acpi_reso
for(i = 0; i < p->channel_count; i++)
dma->map |= 1 << p->channels[i];
- dma->flags = 0;
- if (p->bus_master)
- dma->flags |= IORESOURCE_DMA_MASTER;
- switch (p->type) {
- case ACPI_COMPATIBILITY:
- dma->flags |= IORESOURCE_DMA_COMPATIBLE;
- break;
- case ACPI_TYPE_A:
- dma->flags |= IORESOURCE_DMA_TYPEA;
- break;
- case ACPI_TYPE_B:
- dma->flags |= IORESOURCE_DMA_TYPEB;
- break;
- case ACPI_TYPE_F:
- dma->flags |= IORESOURCE_DMA_TYPEF;
- break;
- default:
- /* Set a default value ? */
- dma->flags |= IORESOURCE_DMA_COMPATIBLE;
- pnp_err("Invalid DMA type");
- }
- switch (p->transfer) {
- case ACPI_TRANSFER_8:
- dma->flags |= IORESOURCE_DMA_8BIT;
- break;
- case ACPI_TRANSFER_8_16:
- dma->flags |= IORESOURCE_DMA_8AND16BIT;
- break;
- case ACPI_TRANSFER_16:
- dma->flags |= IORESOURCE_DMA_16BIT;
- break;
- default:
- /* Set a default value ? */
- dma->flags |= IORESOURCE_DMA_8AND16BIT;
- pnp_err("Invalid DMA transfer type");
- }
+
+ dma->flags = dma_flags(p->type, p->bus_master, p->transfer);
pnp_register_dma_resource(option, dma);
return;
diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c
index 2065e74bb63f..a8a95540b1ef 100644
--- a/drivers/pnp/system.c
+++ b/drivers/pnp/system.c
@@ -22,7 +22,7 @@ static const struct pnp_device_id pnp_dev_table[] = {
{ "", 0 }
};
-static void reserve_range(char *pnpid, int start, int end, int port)
+static void reserve_range(const char *pnpid, resource_size_t start, resource_size_t end, int port)
{
struct resource *res;
char *regionid;
@@ -32,9 +32,9 @@ static void reserve_range(char *pnpid, int start, int end, int port)
return;
snprintf(regionid, 16, "pnp %s", pnpid);
if (port)
- res = request_region(start,end-start+1,regionid);
+ res = request_region(start, end-start+1, regionid);
else
- res = request_mem_region(start,end-start+1,regionid);
+ res = request_mem_region(start, end-start+1, regionid);
if (res == NULL)
kfree(regionid);
else
@@ -45,12 +45,13 @@ static void reserve_range(char *pnpid, int start, int end, int port)
* have double reservations.
*/
printk(KERN_INFO
- "pnp: %s: %s range 0x%x-0x%x %s reserved\n",
- pnpid, port ? "ioport" : "iomem", start, end,
+ "pnp: %s: %s range 0x%llx-0x%llx %s reserved\n",
+ pnpid, port ? "ioport" : "iomem",
+ (unsigned long long)start, (unsigned long long)end,
NULL != res ? "has been" : "could not be");
}
-static void reserve_resources_of_dev(struct pnp_dev *dev)
+static void reserve_resources_of_dev(const struct pnp_dev *dev)
{
int i;
diff --git a/drivers/ps3/ps3av_cmd.c b/drivers/ps3/ps3av_cmd.c
index 21c97c80aa2e..bc70e81f8cb0 100644
--- a/drivers/ps3/ps3av_cmd.c
+++ b/drivers/ps3/ps3av_cmd.c
@@ -485,12 +485,12 @@ static u8 ps3av_cnv_mclk(u32 fs)
static const u32 ps3av_ns_table[][5] = {
/* D1, D2, D3, D4, D5 */
- [PS3AV_CMD_AUDIO_FS_44K-BASE] { 6272, 6272, 17836, 17836, 8918 },
- [PS3AV_CMD_AUDIO_FS_48K-BASE] { 6144, 6144, 11648, 11648, 5824 },
- [PS3AV_CMD_AUDIO_FS_88K-BASE] { 12544, 12544, 35672, 35672, 17836 },
- [PS3AV_CMD_AUDIO_FS_96K-BASE] { 12288, 12288, 23296, 23296, 11648 },
- [PS3AV_CMD_AUDIO_FS_176K-BASE] { 25088, 25088, 71344, 71344, 35672 },
- [PS3AV_CMD_AUDIO_FS_192K-BASE] { 24576, 24576, 46592, 46592, 23296 }
+ [PS3AV_CMD_AUDIO_FS_44K-BASE] = { 6272, 6272, 17836, 17836, 8918 },
+ [PS3AV_CMD_AUDIO_FS_48K-BASE] = { 6144, 6144, 11648, 11648, 5824 },
+ [PS3AV_CMD_AUDIO_FS_88K-BASE] = { 12544, 12544, 35672, 35672, 17836 },
+ [PS3AV_CMD_AUDIO_FS_96K-BASE] = { 12288, 12288, 23296, 23296, 11648 },
+ [PS3AV_CMD_AUDIO_FS_176K-BASE] = { 25088, 25088, 71344, 71344, 35672 },
+ [PS3AV_CMD_AUDIO_FS_192K-BASE] = { 24576, 24576, 46592, 46592, 23296 }
};
static void ps3av_cnv_ns(u8 *ns, u32 fs, u32 video_vid)
@@ -543,9 +543,10 @@ static void ps3av_cnv_ns(u8 *ns, u32 fs, u32 video_vid)
#undef BASE
-static u8 ps3av_cnv_enable(u32 source, u8 *enable)
+static u8 ps3av_cnv_enable(u32 source, const u8 *enable)
{
- u8 *p, ret = 0;
+ const u8 *p;
+ u8 ret = 0;
if (source == PS3AV_CMD_AUDIO_SOURCE_SPDIF) {
ret = 0x03;
@@ -559,9 +560,10 @@ static u8 ps3av_cnv_enable(u32 source, u8 *enable)
return ret;
}
-static u8 ps3av_cnv_fifomap(u8 *map)
+static u8 ps3av_cnv_fifomap(const u8 *map)
{
- u8 *p, ret = 0;
+ const u8 *p;
+ u8 ret = 0;
p = map;
ret = p[0] + (p[1] << 2) + (p[2] << 4) + (p[3] << 6);
@@ -615,7 +617,7 @@ static void ps3av_cnv_info(struct ps3av_audio_info_frame *info,
info->pb5.lsv = mode->audio_downmix_level;
}
-static void ps3av_cnv_chstat(u8 *chstat, u8 *cs_info)
+static void ps3av_cnv_chstat(u8 *chstat, const u8 *cs_info)
{
memcpy(chstat, cs_info, 5);
}
diff --git a/drivers/ps3/vuart.c b/drivers/ps3/vuart.c
index 1adf186bfaf5..6c12744eeb9d 100644
--- a/drivers/ps3/vuart.c
+++ b/drivers/ps3/vuart.c
@@ -952,7 +952,7 @@ fail_alloc_irq:
kfree(dev->priv);
dev->priv = NULL;
fail_alloc:
- vuart_bus_priv.devices[port_number] = 0;
+ vuart_bus_priv.devices[port_number] = NULL;
fail_match:
up(&vuart_bus_priv.probe_mutex);
dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__);
@@ -978,7 +978,7 @@ static int ps3_vuart_remove(struct device *_dev)
dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__,
__LINE__, dev->core.bus_id);
- vuart_bus_priv.devices[dev->priv->port_number] = 0;
+ vuart_bus_priv.devices[dev->priv->port_number] = NULL;
if (--vuart_bus_priv.use_count == 0) {
BUG();
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index 85bf795abdcc..7c0d60910077 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -59,6 +59,19 @@ struct cmos_rtc {
static const char driver_name[] = "rtc_cmos";
+/* The RTC_INTR register may have e.g. RTC_PF set even if RTC_PIE is clear;
+ * always mask it against the irq enable bits in RTC_CONTROL. Bit values
+ * are the same: PF==PIE, AF=AIE, UF=UIE; so RTC_IRQMASK works with both.
+ */
+#define RTC_IRQMASK (RTC_PF | RTC_AF | RTC_UF)
+
+static inline int is_intr(u8 rtc_intr)
+{
+ if (!(rtc_intr & RTC_IRQF))
+ return 0;
+ return rtc_intr & RTC_IRQMASK;
+}
+
/*----------------------------------------------------------------*/
static int cmos_read_time(struct device *dev, struct rtc_time *t)
@@ -188,7 +201,8 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
rtc_control &= ~RTC_AIE;
CMOS_WRITE(rtc_control, RTC_CONTROL);
rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
- if (rtc_intr)
+ rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
+ if (is_intr(rtc_intr))
rtc_update_irq(&cmos->rtc->class_dev, 1, rtc_intr);
/* update alarm */
@@ -207,7 +221,8 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
rtc_control |= RTC_AIE;
CMOS_WRITE(rtc_control, RTC_CONTROL);
rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
- if (rtc_intr)
+ rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
+ if (is_intr(rtc_intr))
rtc_update_irq(&cmos->rtc->class_dev, 1, rtc_intr);
}
@@ -287,7 +302,8 @@ cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
}
CMOS_WRITE(rtc_control, RTC_CONTROL);
rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
- if (rtc_intr)
+ rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
+ if (is_intr(rtc_intr))
rtc_update_irq(&cmos->rtc->class_dev, 1, rtc_intr);
spin_unlock_irqrestore(&rtc_lock, flags);
return 0;
@@ -353,12 +369,10 @@ static irqreturn_t cmos_interrupt(int irq, void *p)
spin_lock(&rtc_lock);
irqstat = CMOS_READ(RTC_INTR_FLAGS);
+ irqstat &= (CMOS_READ(RTC_CONTROL) & RTC_IRQMASK) | RTC_IRQF;
spin_unlock(&rtc_lock);
- if (irqstat) {
- /* NOTE: irqstat may have e.g. RTC_PF set
- * even when RTC_PIE is clear...
- */
+ if (is_intr(irqstat)) {
rtc_update_irq(p, 1, irqstat);
return IRQ_HANDLED;
} else
@@ -525,25 +539,26 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg)
{
struct cmos_rtc *cmos = dev_get_drvdata(dev);
int do_wake = device_may_wakeup(dev);
- unsigned char tmp, irqstat;
+ unsigned char tmp;
/* only the alarm might be a wakeup event source */
spin_lock_irq(&rtc_lock);
cmos->suspend_ctrl = tmp = CMOS_READ(RTC_CONTROL);
if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) {
+ unsigned char irqstat;
+
if (do_wake)
tmp &= ~(RTC_PIE|RTC_UIE);
else
tmp &= ~(RTC_PIE|RTC_AIE|RTC_UIE);
CMOS_WRITE(tmp, RTC_CONTROL);
irqstat = CMOS_READ(RTC_INTR_FLAGS);
- } else
- irqstat = 0;
+ irqstat &= (tmp & RTC_IRQMASK) | RTC_IRQF;
+ if (is_intr(irqstat))
+ rtc_update_irq(&cmos->rtc->class_dev, 1, irqstat);
+ }
spin_unlock_irq(&rtc_lock);
- if (irqstat)
- rtc_update_irq(&cmos->rtc->class_dev, 1, irqstat);
-
/* ACPI HOOK: enable ACPI_EVENT_RTC when (tmp & RTC_AIE)
* ... it'd be best if we could do that under rtc_lock.
*/
@@ -573,9 +588,10 @@ static int cmos_resume(struct device *dev)
spin_lock_irq(&rtc_lock);
CMOS_WRITE(tmp, RTC_CONTROL);
tmp = CMOS_READ(RTC_INTR_FLAGS);
- spin_unlock_irq(&rtc_lock);
- if (tmp)
+ tmp &= (cmos->suspend_ctrl & RTC_IRQMASK) | RTC_IRQF;
+ if (is_intr(tmp))
rtc_update_irq(&cmos->rtc->class_dev, 1, tmp);
+ spin_unlock_irq(&rtc_lock);
}
pr_debug("%s: resume, ctrl %02x\n",
@@ -594,7 +610,7 @@ static int cmos_resume(struct device *dev)
/*----------------------------------------------------------------*/
/* The "CMOS" RTC normally lives on the platform_bus. On ACPI systems,
- * the device node may alternatively be created as a PNP device.
+ * the device node will always be created as a PNPACPI device.
*/
#ifdef CONFIG_PNPACPI
@@ -673,7 +689,7 @@ module_exit(cmos_exit);
/*----------------------------------------------------------------*/
/* Platform setup should have set up an RTC device, when PNPACPI is
- * unavailable ... this is the normal case, common even on PCs.
+ * unavailable ... this could happen even on (older) PCs.
*/
static int __init cmos_platform_probe(struct platform_device *pdev)
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index ab782bb46ac1..e810e4a44ed4 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -65,7 +65,7 @@ static const u8 DASD_DIAG_CMS1[] = { 0xc3, 0xd4, 0xe2, 0xf1 };/* EBCDIC CMS1 */
* resulting condition code and DIAG return code. */
static inline int dia250(void *iob, int cmd)
{
- register unsigned long reg0 asm ("0") = (unsigned long) iob;
+ register unsigned long reg2 asm ("2") = (unsigned long) iob;
typedef union {
struct dasd_diag_init_io init_io;
struct dasd_diag_rw_io rw_io;
@@ -74,15 +74,15 @@ static inline int dia250(void *iob, int cmd)
rc = 3;
asm volatile(
- " diag 0,%2,0x250\n"
+ " diag 2,%2,0x250\n"
"0: ipm %0\n"
" srl %0,28\n"
- " or %0,1\n"
+ " or %0,3\n"
"1:\n"
EX_TABLE(0b,1b)
: "+d" (rc), "=m" (*(addr_type *) iob)
- : "d" (cmd), "d" (reg0), "m" (*(addr_type *) iob)
- : "1", "cc");
+ : "d" (cmd), "d" (reg2), "m" (*(addr_type *) iob)
+ : "3", "cc");
return rc;
}
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index d48e3ca4752c..5aeb68e732b0 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -71,19 +71,31 @@ __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
* Provide an 'ungroup' attribute so the user can remove group devices no
* longer needed or accidentially created. Saves memory :)
*/
+static void ccwgroup_ungroup_callback(struct device *dev)
+{
+ struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
+
+ __ccwgroup_remove_symlinks(gdev);
+ device_unregister(dev);
+}
+
static ssize_t
ccwgroup_ungroup_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct ccwgroup_device *gdev;
+ int rc;
gdev = to_ccwgroupdev(dev);
if (gdev->state != CCWGROUP_OFFLINE)
return -EINVAL;
- __ccwgroup_remove_symlinks(gdev);
- device_unregister(dev);
-
+ /* Note that we cannot unregister the device from one of its
+ * attribute methods, so we have to use this roundabout approach.
+ */
+ rc = device_schedule_callback(dev, ccwgroup_ungroup_callback);
+ if (rc)
+ count = rc;
return count;
}
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
index 6b1caea622ea..aa96e6752592 100644
--- a/drivers/s390/cio/device_status.c
+++ b/drivers/s390/cio/device_status.c
@@ -221,6 +221,14 @@ ccw_device_accumulate_irb(struct ccw_device *cdev, struct irb *irb)
cdev_irb = &cdev->private->irb;
+ /*
+ * If the clear function had been performed, all formerly pending
+ * status at the subchannel has been cleared and we must not pass
+ * intermediate accumulated status to the device driver.
+ */
+ if (irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC)
+ memset(&cdev->private->irb, 0, sizeof(struct irb));
+
/* Copy bits which are valid only for the start function. */
if (irb->scsw.fctl & SCSW_FCTL_START_FUNC) {
/* Copy key. */
@@ -263,7 +271,11 @@ ccw_device_accumulate_irb(struct ccw_device *cdev, struct irb *irb)
cdev_irb->scsw.cpa = irb->scsw.cpa;
/* Accumulate device status, but not the device busy flag. */
cdev_irb->scsw.dstat &= ~DEV_STAT_BUSY;
- cdev_irb->scsw.dstat |= irb->scsw.dstat;
+ /* dstat is not always valid. */
+ if (irb->scsw.stctl &
+ (SCSW_STCTL_PRIM_STATUS | SCSW_STCTL_SEC_STATUS
+ | SCSW_STCTL_INTER_STATUS | SCSW_STCTL_ALERT_STATUS))
+ cdev_irb->scsw.dstat |= irb->scsw.dstat;
/* Accumulate subchannel status. */
cdev_irb->scsw.cstat |= irb->scsw.cstat;
/* Copy residual count if it is valid. */
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 5b1e3ff26c0b..05fac0733f3d 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -210,9 +210,11 @@ again:
goto again;
}
if (rc < 0) {
- QDIO_DBF_TEXT3(1,trace,"sqberr");
- sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt,*cnt,ccq,q_no);
- QDIO_DBF_TEXT3(1,trace,dbf_text);
+ QDIO_DBF_TEXT3(1,trace,"sqberr");
+ sprintf(dbf_text,"%2x,%2x",tmp_cnt,*cnt);
+ QDIO_DBF_TEXT3(1,trace,dbf_text);
+ sprintf(dbf_text,"%d,%d",ccq,q_no);
+ QDIO_DBF_TEXT3(1,trace,dbf_text);
q->handler(q->cdev,QDIO_STATUS_ACTIVATE_CHECK_CONDITION|
QDIO_STATUS_LOOK_FOR_ERROR,
0, 0, 0, -1, -1, q->int_parm);
@@ -1250,7 +1252,6 @@ qdio_is_inbound_q_done(struct qdio_q *q)
if (!no_used) {
QDIO_DBF_TEXT4(0,trace,"inqisdnA");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
- QDIO_DBF_TEXT4(0,trace,dbf_text);
return 1;
}
if (irq->is_qebsm) {
@@ -3371,10 +3372,15 @@ qdio_do_qdio_fill_input(struct qdio_q *q, unsigned int qidx,
unsigned int count, struct qdio_buffer *buffers)
{
struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
+ int tmp = 0;
+
qidx &= (QDIO_MAX_BUFFERS_PER_Q - 1);
if (irq->is_qebsm) {
- while (count)
- set_slsb(q, &qidx, SLSB_CU_INPUT_EMPTY, &count);
+ while (count) {
+ tmp = set_slsb(q, &qidx, SLSB_CU_INPUT_EMPTY, &count);
+ if (!tmp)
+ return;
+ }
return;
}
for (;;) {
@@ -3390,11 +3396,15 @@ qdio_do_qdio_fill_output(struct qdio_q *q, unsigned int qidx,
unsigned int count, struct qdio_buffer *buffers)
{
struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
+ int tmp = 0;
qidx &= (QDIO_MAX_BUFFERS_PER_Q - 1);
if (irq->is_qebsm) {
- while (count)
- set_slsb(q, &qidx, SLSB_CU_OUTPUT_PRIMED, &count);
+ while (count) {
+ tmp = set_slsb(q, &qidx, SLSB_CU_OUTPUT_PRIMED, &count);
+ if (!tmp)
+ return;
+ }
return;
}
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index c7d1355237b6..bf37cdf43fae 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -65,6 +65,8 @@ module_param_named(poll_thread, ap_thread_flag, int, 0000);
MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 1 (on).");
static struct device *ap_root_device = NULL;
+static DEFINE_SPINLOCK(ap_device_lock);
+static LIST_HEAD(ap_device_list);
/**
* Workqueue & timer for bus rescan.
@@ -457,6 +459,9 @@ static int ap_device_probe(struct device *dev)
int rc;
ap_dev->drv = ap_drv;
+ spin_lock_bh(&ap_device_lock);
+ list_add(&ap_dev->list, &ap_device_list);
+ spin_unlock_bh(&ap_device_lock);
rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
return rc;
}
@@ -497,6 +502,12 @@ static int ap_device_remove(struct device *dev)
ap_flush_queue(ap_dev);
if (ap_drv->remove)
ap_drv->remove(ap_dev);
+ spin_lock_bh(&ap_device_lock);
+ list_del_init(&ap_dev->list);
+ spin_unlock_bh(&ap_device_lock);
+ spin_lock_bh(&ap_dev->lock);
+ atomic_sub(ap_dev->queue_count, &ap_poll_requests);
+ spin_unlock_bh(&ap_dev->lock);
return 0;
}
@@ -749,10 +760,16 @@ static void ap_scan_bus(struct work_struct *unused)
(void *)(unsigned long)qid,
__ap_scan_bus);
rc = ap_query_queue(qid, &queue_depth, &device_type);
- if (dev && rc) {
- put_device(dev);
- device_unregister(dev);
- continue;
+ if (dev) {
+ ap_dev = to_ap_dev(dev);
+ spin_lock_bh(&ap_dev->lock);
+ if (rc || ap_dev->unregistered) {
+ spin_unlock_bh(&ap_dev->lock);
+ put_device(dev);
+ device_unregister(dev);
+ continue;
+ } else
+ spin_unlock_bh(&ap_dev->lock);
}
if (dev) {
put_device(dev);
@@ -772,6 +789,7 @@ static void ap_scan_bus(struct work_struct *unused)
spin_lock_init(&ap_dev->lock);
INIT_LIST_HEAD(&ap_dev->pendingq);
INIT_LIST_HEAD(&ap_dev->requestq);
+ INIT_LIST_HEAD(&ap_dev->list);
if (device_type == 0)
ap_probe_device_type(ap_dev);
else
@@ -852,6 +870,7 @@ static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
case AP_RESPONSE_NO_PENDING_REPLY:
if (status.queue_empty) {
/* The card shouldn't forget requests but who knows. */
+ atomic_sub(ap_dev->queue_count, &ap_poll_requests);
ap_dev->queue_count = 0;
list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
ap_dev->requestq_count += ap_dev->pendingq_count;
@@ -985,7 +1004,7 @@ void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
ap_dev->unregistered = 1;
} else {
ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
- rc = 0;
+ rc = -ENODEV;
}
spin_unlock_bh(&ap_dev->lock);
if (rc == -ENODEV)
@@ -1033,31 +1052,29 @@ static void ap_poll_timeout(unsigned long unused)
* polling until bit 2^0 of the control flags is not set. If bit 2^1
* of the control flags has been set arm the poll timer.
*/
-static int __ap_poll_all(struct device *dev, void *data)
+static int __ap_poll_all(struct ap_device *ap_dev, unsigned long *flags)
{
- struct ap_device *ap_dev = to_ap_dev(dev);
- int rc;
-
spin_lock(&ap_dev->lock);
if (!ap_dev->unregistered) {
- rc = ap_poll_queue(to_ap_dev(dev), (unsigned long *) data);
- if (rc)
+ if (ap_poll_queue(ap_dev, flags))
ap_dev->unregistered = 1;
- } else
- rc = 0;
+ }
spin_unlock(&ap_dev->lock);
- if (rc)
- device_unregister(&ap_dev->device);
return 0;
}
static void ap_poll_all(unsigned long dummy)
{
unsigned long flags;
+ struct ap_device *ap_dev;
do {
flags = 0;
- bus_for_each_dev(&ap_bus_type, NULL, &flags, __ap_poll_all);
+ spin_lock(&ap_device_lock);
+ list_for_each_entry(ap_dev, &ap_device_list, list) {
+ __ap_poll_all(ap_dev, &flags);
+ }
+ spin_unlock(&ap_device_lock);
} while (flags & 1);
if (flags & 2)
ap_schedule_poll_timer();
@@ -1075,6 +1092,7 @@ static int ap_poll_thread(void *data)
DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
int requests;
+ struct ap_device *ap_dev;
set_user_nice(current, 19);
while (1) {
@@ -1092,10 +1110,12 @@ static int ap_poll_thread(void *data)
set_current_state(TASK_RUNNING);
remove_wait_queue(&ap_poll_wait, &wait);
- local_bh_disable();
flags = 0;
- bus_for_each_dev(&ap_bus_type, NULL, &flags, __ap_poll_all);
- local_bh_enable();
+ spin_lock_bh(&ap_device_lock);
+ list_for_each_entry(ap_dev, &ap_device_list, list) {
+ __ap_poll_all(ap_dev, &flags);
+ }
+ spin_unlock_bh(&ap_device_lock);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&ap_poll_wait, &wait);
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index 83b69c01cd6e..008559ea742b 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -106,6 +106,7 @@ struct ap_device {
struct device device;
struct ap_driver *drv; /* Pointer to AP device driver. */
spinlock_t lock; /* Per device lock. */
+ struct list_head list; /* private list of all AP devices. */
ap_qid_t qid; /* AP queue id. */
int queue_depth; /* AP queue depth.*/
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 99761391f340..e3625a47a596 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -298,14 +298,14 @@ static long zcrypt_rsa_modexpo(struct ica_rsa_modexpo *mex)
get_device(&zdev->ap_dev->device);
zdev->request_count++;
__zcrypt_decrease_preference(zdev);
- spin_unlock_bh(&zcrypt_device_lock);
if (try_module_get(zdev->ap_dev->drv->driver.owner)) {
+ spin_unlock_bh(&zcrypt_device_lock);
rc = zdev->ops->rsa_modexpo(zdev, mex);
+ spin_lock_bh(&zcrypt_device_lock);
module_put(zdev->ap_dev->drv->driver.owner);
}
else
rc = -EAGAIN;
- spin_lock_bh(&zcrypt_device_lock);
zdev->request_count--;
__zcrypt_increase_preference(zdev);
put_device(&zdev->ap_dev->device);
@@ -373,14 +373,14 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt)
get_device(&zdev->ap_dev->device);
zdev->request_count++;
__zcrypt_decrease_preference(zdev);
- spin_unlock_bh(&zcrypt_device_lock);
if (try_module_get(zdev->ap_dev->drv->driver.owner)) {
+ spin_unlock_bh(&zcrypt_device_lock);
rc = zdev->ops->rsa_modexpo_crt(zdev, crt);
+ spin_lock_bh(&zcrypt_device_lock);
module_put(zdev->ap_dev->drv->driver.owner);
}
else
rc = -EAGAIN;
- spin_lock_bh(&zcrypt_device_lock);
zdev->request_count--;
__zcrypt_increase_preference(zdev);
put_device(&zdev->ap_dev->device);
@@ -408,14 +408,14 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB)
get_device(&zdev->ap_dev->device);
zdev->request_count++;
__zcrypt_decrease_preference(zdev);
- spin_unlock_bh(&zcrypt_device_lock);
if (try_module_get(zdev->ap_dev->drv->driver.owner)) {
+ spin_unlock_bh(&zcrypt_device_lock);
rc = zdev->ops->send_cprb(zdev, xcRB);
+ spin_lock_bh(&zcrypt_device_lock);
module_put(zdev->ap_dev->drv->driver.owner);
}
else
rc = -EAGAIN;
- spin_lock_bh(&zcrypt_device_lock);
zdev->request_count--;
__zcrypt_increase_preference(zdev);
put_device(&zdev->ap_dev->device);
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index e95c281f1e36..84b108d7c7fd 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -873,7 +873,7 @@ qeth_realloc_headroom(struct qeth_card *card, struct sk_buff *skb, int size)
}
static inline struct sk_buff *
-qeth_pskb_unshare(struct sk_buff *skb, int pri)
+qeth_pskb_unshare(struct sk_buff *skb, gfp_t pri)
{
struct sk_buff *nskb;
if (!skb_cloned(skb))
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 8c81cec85298..60446b88f721 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -3091,6 +3091,7 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
cmdp->u.raw64.direction =
gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN;
memcpy(cmdp->u.raw64.cmd,scp->cmnd,16);
+ cmdp->u.raw64.sg_ranz = 0;
} else {
cmdp->u.raw.reserved = 0;
cmdp->u.raw.mdisc_time = 0;
@@ -3107,6 +3108,7 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
cmdp->u.raw.direction =
gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN;
memcpy(cmdp->u.raw.cmd,scp->cmnd,12);
+ cmdp->u.raw.sg_ranz = 0;
}
if (scp->use_sg) {
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 9d014e5a81c4..057fd7e0e379 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -1817,10 +1817,9 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev,
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring;
- if (state == pci_channel_io_perm_failure) {
- lpfc_pci_remove_one(pdev);
+ if (state == pci_channel_io_perm_failure)
return PCI_ERS_RESULT_DISCONNECT;
- }
+
pci_disable_device(pdev);
/*
* There may be I/Os dropped by the firmware.
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index b8edcf5b5451..918bb6019540 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -716,7 +716,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
*/
if (copy_sense) {
if (!SCSI_SENSE_VALID(scmd)) {
- memcpy(scmd->sense_buffer, scmd->request_buffer,
+ memcpy(scmd->sense_buffer, page_address(sgl.page),
sizeof(scmd->sense_buffer));
}
__free_page(sgl.page);
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index c275dcac3f18..939de0de18bc 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -452,10 +452,22 @@ store_rescan_field (struct device *dev, struct device_attribute *attr, const cha
}
static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field);
+static void sdev_store_delete_callback(struct device *dev)
+{
+ scsi_remove_device(to_scsi_device(dev));
+}
+
static ssize_t sdev_store_delete(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
- scsi_remove_device(to_scsi_device(dev));
+ int rc;
+
+ /* An attribute cannot be unregistered by one of its own methods,
+ * so we have to use this roundabout approach.
+ */
+ rc = device_schedule_callback(dev, sdev_store_delete_callback);
+ if (rc)
+ count = rc;
return count;
};
static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c
index cde5db44abf6..301c8c0be9d7 100644
--- a/drivers/serial/8250_pnp.c
+++ b/drivers/serial/8250_pnp.c
@@ -340,6 +340,9 @@ static const struct pnp_device_id pnp_dev_table[] = {
{ "FUJ02B8", 0 },
{ "FUJ02B9", 0 },
{ "FUJ02BC", 0 },
+ /* Fujitsu Wacom Tablet PC devices */
+ { "FUJ02E5", 0 },
+ { "FUJ02E6", 0 },
/* Rockwell's (PORALiNK) 33600 INT PNP */
{ "WCI0003", 0 },
/* Unkown PnP modems */
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index c53b69610a51..46c40bbc4bc6 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -17,6 +17,9 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
+#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
#undef DEBUG
@@ -49,11 +52,6 @@
#endif
#include <asm/sci.h>
-
-#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
#include "sh-sci.h"
struct sci_port {
@@ -645,6 +643,9 @@ static inline int sci_handle_breaks(struct uart_port *port)
struct tty_struct *tty = port->info->tty;
struct sci_port *s = &sci_ports[port->line];
+ if (uart_handle_break(port))
+ return 0;
+
if (!s->break_flag && status & SCxSR_BRK(port)) {
#if defined(CONFIG_CPU_SH3)
/* Debounce break */
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index 253ceb895ca7..a27e9e92cb5e 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -636,25 +636,6 @@ static irqreturn_t sn_sal_interrupt(int irq, void *dev_id)
}
/**
- * sn_sal_connect_interrupt - Request interrupt, handled by sn_sal_interrupt
- * @port: Our sn_cons_port (which contains the uart port)
- *
- * returns the console irq if interrupt is successfully registered, else 0
- *
- */
-static int sn_sal_connect_interrupt(struct sn_cons_port *port)
-{
- if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt,
- IRQF_DISABLED | IRQF_SHARED,
- "SAL console driver", port) >= 0) {
- return SGI_UART_VECTOR;
- }
-
- printk(KERN_INFO "sn_console: console proceeding in polled mode\n");
- return 0;
-}
-
-/**
* sn_sal_timer_poll - this function handles polled console mode
* @data: A pointer to our sn_cons_port (which contains the uart port)
*
@@ -746,30 +727,31 @@ static void __init sn_sal_switch_to_asynch(struct sn_cons_port *port)
* mode. We were previously in asynch/polling mode (using init_timer).
*
* We attempt to switch to interrupt mode here by calling
- * sn_sal_connect_interrupt. If that works out, we enable receive interrupts.
+ * request_irq. If that works out, we enable receive interrupts.
*/
static void __init sn_sal_switch_to_interrupts(struct sn_cons_port *port)
{
- int irq;
unsigned long flags;
- if (!port)
- return;
-
- DPRINTF("sn_console: switching to interrupt driven console\n");
-
- spin_lock_irqsave(&port->sc_port.lock, flags);
+ if (port) {
+ DPRINTF("sn_console: switching to interrupt driven console\n");
- irq = sn_sal_connect_interrupt(port);
+ if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt,
+ IRQF_DISABLED | IRQF_SHARED,
+ "SAL console driver", port) >= 0) {
+ spin_lock_irqsave(&port->sc_port.lock, flags);
+ port->sc_port.irq = SGI_UART_VECTOR;
+ port->sc_ops = &intr_ops;
- if (irq) {
- port->sc_port.irq = irq;
- port->sc_ops = &intr_ops;
-
- /* turn on receive interrupts */
- ia64_sn_console_intr_enable(SAL_CONSOLE_INTR_RECV);
+ /* turn on receive interrupts */
+ ia64_sn_console_intr_enable(SAL_CONSOLE_INTR_RECV);
+ spin_unlock_irqrestore(&port->sc_port.lock, flags);
+ }
+ else {
+ printk(KERN_INFO
+ "sn_console: console proceeding in polled mode\n");
+ }
}
- spin_unlock_irqrestore(&port->sc_port.lock, flags);
}
/*
diff --git a/drivers/spi/at25.c b/drivers/spi/at25.c
index 48e4f48e779f..8efa07e8b8c2 100644
--- a/drivers/spi/at25.c
+++ b/drivers/spi/at25.c
@@ -291,7 +291,7 @@ static int at25_probe(struct spi_device *spi)
*/
sr = spi_w8r8(spi, AT25_RDSR);
if (sr < 0 || sr & AT25_SR_nRDY) {
- dev_dbg(&at25->spi->dev, "rdsr --> %d (%02x)\n", sr, sr);
+ dev_dbg(&spi->dev, "rdsr --> %d (%02x)\n", sr, sr);
err = -ENXIO;
goto fail;
}
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index 6fa260d1a9be..66e7bc985797 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -425,7 +425,7 @@ static int atmel_spi_setup(struct spi_device *spi)
if (ret)
return ret;
spi->controller_state = (void *)npcs_pin;
- gpio_direction_output(npcs_pin);
+ gpio_direction_output(npcs_pin, !(spi->mode & SPI_CS_HIGH));
}
dev_dbg(&spi->dev,
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 2328128728be..6657331eed93 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -189,8 +189,8 @@ static DECLARE_MUTEX(board_lock);
* this is exported so that for example a USB or parport based adapter
* driver could add devices (which it would learn about out-of-band).
*/
-struct spi_device *__init_or_module
-spi_new_device(struct spi_master *master, struct spi_board_info *chip)
+struct spi_device *spi_new_device(struct spi_master *master,
+ struct spi_board_info *chip)
{
struct spi_device *proxy;
struct device *dev = master->cdev.dev;
@@ -352,8 +352,7 @@ static struct class spi_master_class = {
* the master's methods before calling spi_register_master(); and (after errors
* adding the device) calling spi_master_put() to prevent a memory leak.
*/
-struct spi_master * __init_or_module
-spi_alloc_master(struct device *dev, unsigned size)
+struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
{
struct spi_master *master;
@@ -392,8 +391,7 @@ EXPORT_SYMBOL_GPL(spi_alloc_master);
* After a successful return, the caller is responsible for calling
* spi_unregister_master().
*/
-int __init_or_module
-spi_register_master(struct spi_master *master)
+int spi_register_master(struct spi_master *master)
{
static atomic_t dyn_bus_id = ATOMIC_INIT((1<<16) - 1);
struct device *dev = master->cdev.dev;
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c
index 24a330d82395..88425e1af4d3 100644
--- a/drivers/spi/spi_bitbang.c
+++ b/drivers/spi/spi_bitbang.c
@@ -302,10 +302,6 @@ static void bitbang_work(struct work_struct *work)
setup_transfer = NULL;
list_for_each_entry (t, &m->transfers, transfer_list) {
- if (bitbang->shutdown) {
- status = -ESHUTDOWN;
- break;
- }
/* override or restore speed and wordsize */
if (t->speed_hz || t->bits_per_word) {
@@ -410,8 +406,6 @@ int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)
m->status = -EINPROGRESS;
bitbang = spi_master_get_devdata(spi->master);
- if (bitbang->shutdown)
- return -ESHUTDOWN;
spin_lock_irqsave(&bitbang->lock, flags);
if (!spi->max_speed_hz)
@@ -507,28 +501,12 @@ EXPORT_SYMBOL_GPL(spi_bitbang_start);
*/
int spi_bitbang_stop(struct spi_bitbang *bitbang)
{
- unsigned limit = 500;
-
- spin_lock_irq(&bitbang->lock);
- bitbang->shutdown = 0;
- while (!list_empty(&bitbang->queue) && limit--) {
- spin_unlock_irq(&bitbang->lock);
+ spi_unregister_master(bitbang->master);
- dev_dbg(bitbang->master->cdev.dev, "wait for queue\n");
- msleep(10);
-
- spin_lock_irq(&bitbang->lock);
- }
- spin_unlock_irq(&bitbang->lock);
- if (!list_empty(&bitbang->queue)) {
- dev_err(bitbang->master->cdev.dev, "queue didn't empty\n");
- return -EBUSY;
- }
+ WARN_ON(!list_empty(&bitbang->queue));
destroy_workqueue(bitbang->workqueue);
- spi_unregister_master(bitbang->master);
-
return 0;
}
EXPORT_SYMBOL_GPL(spi_bitbang_stop);
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c
index 651379c51ae6..220abce63e4a 100644
--- a/drivers/spi/spi_s3c24xx.c
+++ b/drivers/spi/spi_s3c24xx.c
@@ -41,7 +41,7 @@ struct s3c24xx_spi {
int len;
int count;
- int (*set_cs)(struct s3c2410_spi_info *spi,
+ void (*set_cs)(struct s3c2410_spi_info *spi,
int cs, int pol);
/* data buffers */
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index 3d72aa5cfc71..3524e3fc08b9 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -70,7 +70,6 @@
#include <asm/dec/machtype.h>
#include <asm/dec/serial.h>
#include <asm/dec/system.h>
-#include <asm/dec/tc.h>
#ifdef CONFIG_KGDB
#include <asm/kgdb.h>
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index d38a25f36ea5..31ae661e586a 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -332,9 +332,9 @@ static void acm_rx_tasklet(unsigned long _acm)
if (!ACM_READY(acm))
return;
- spin_lock(&acm->throttle_lock);
+ spin_lock_irqsave(&acm->throttle_lock, flags);
throttled = acm->throttle;
- spin_unlock(&acm->throttle_lock);
+ spin_unlock_irqrestore(&acm->throttle_lock, flags);
if (throttled)
return;
@@ -352,9 +352,9 @@ next_buffer:
dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size);
tty_buffer_request_room(tty, buf->size);
- spin_lock(&acm->throttle_lock);
+ spin_lock_irqsave(&acm->throttle_lock, flags);
throttled = acm->throttle;
- spin_unlock(&acm->throttle_lock);
+ spin_unlock_irqrestore(&acm->throttle_lock, flags);
if (!throttled)
tty_insert_flip_string(tty, buf->base, buf->size);
tty_flip_buffer_push(tty);
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 63e50a1f1396..6584cf00f7f3 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -202,6 +202,7 @@ struct quirk_printer_struct {
#define USBLP_QUIRK_BIDIR 0x1 /* reports bidir but requires unidirectional mode (no INs/reads) */
#define USBLP_QUIRK_USB_INIT 0x2 /* needs vendor USB init string */
+#define USBLP_QUIRK_BAD_CLASS 0x4 /* descriptor uses vendor-specific Class or SubClass */
static const struct quirk_printer_struct quirk_printers[] = {
{ 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */
@@ -218,6 +219,7 @@ static const struct quirk_printer_struct quirk_printers[] = {
{ 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */
{ 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */
{ 0x0482, 0x0010, USBLP_QUIRK_BIDIR }, /* Kyocera Mita FS 820, by zut <kernel@zut.de> */
+ { 0x04b8, 0x0202, USBLP_QUIRK_BAD_CLASS }, /* Seiko Epson Receipt Printer M129C */
{ 0, 0 }
};
@@ -1048,7 +1050,8 @@ static int usblp_select_alts(struct usblp *usblp)
ifd = &if_alt->altsetting[i];
if (ifd->desc.bInterfaceClass != 7 || ifd->desc.bInterfaceSubClass != 1)
- continue;
+ if (!(usblp->quirks & USBLP_QUIRK_BAD_CLASS))
+ continue;
if (ifd->desc.bInterfaceProtocol < USBLP_FIRST_PROTOCOL ||
ifd->desc.bInterfaceProtocol > USBLP_LAST_PROTOCOL)
@@ -1232,6 +1235,7 @@ static struct usb_device_id usblp_ids [] = {
{ USB_INTERFACE_INFO(7, 1, 1) },
{ USB_INTERFACE_INFO(7, 1, 2) },
{ USB_INTERFACE_INFO(7, 1, 3) },
+ { USB_DEVICE(0x04b8, 0x0202) }, /* Seiko Epson Receipt Printer M129C */
{ } /* Terminating entry */
};
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 274f14f1633e..36e7a843bf91 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -912,7 +912,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
struct async *as;
struct usb_ctrlrequest *dr = NULL;
unsigned int u, totlen, isofrmlen;
- int ret, interval = 0, ifnum = -1;
+ int ret, ifnum = -1;
if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK|
URB_NO_FSBR|URB_ZERO_PACKET))
@@ -992,7 +992,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
!= USB_ENDPOINT_XFER_ISOC)
return -EINVAL;
- interval = 1 << min (15, ep->desc.bInterval - 1);
isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets;
if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
return -ENOMEM;
@@ -1021,10 +1020,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
!= USB_ENDPOINT_XFER_INT)
return -EINVAL;
- if (ps->dev->speed == USB_SPEED_HIGH)
- interval = 1 << min (15, ep->desc.bInterval - 1);
- else
- interval = ep->desc.bInterval;
if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
return -EINVAL;
if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length))
@@ -1053,7 +1048,11 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
as->urb->setup_packet = (unsigned char*)dr;
as->urb->start_frame = uurb->start_frame;
as->urb->number_of_packets = uurb->number_of_packets;
- as->urb->interval = interval;
+ if (uurb->type == USBDEVFS_URB_TYPE_ISO ||
+ ps->dev->speed == USB_SPEED_HIGH)
+ as->urb->interval = 1 << min(15, ep->desc.bInterval - 1);
+ else
+ as->urb->interval = ep->desc.bInterval;
as->urb->context = as;
as->urb->complete = async_completed;
for (totlen = u = 0; u < uurb->number_of_packets; u++) {
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 41400743ce2c..b89a98e61323 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1281,12 +1281,6 @@ int usb_new_device(struct usb_device *udev)
{
int err;
- /* Lock ourself into memory in order to keep a probe sequence
- * sleeping in a new thread from allowing us to be unloaded.
- */
- if (!try_module_get(THIS_MODULE))
- return -EINVAL;
-
/* Determine quirks */
usb_detect_quirks(udev);
@@ -1390,7 +1384,6 @@ int usb_new_device(struct usb_device *udev)
usb_autoresume_device(udev->parent);
exit:
- module_put(THIS_MODULE);
return err;
fail:
@@ -2443,7 +2436,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
if (portchange & USB_PORT_STAT_C_CONNECTION) {
status = hub_port_debounce(hub, port1);
- if (status < 0) {
+ if (status < 0 && printk_ratelimit()) {
dev_err (hub_dev,
"connect-debounce failed, port %d disabled\n",
port1);
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 2f17468b5c1e..217a3d6d0a06 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -221,10 +221,15 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_INT) {
+ int interval;
+
+ if (usb_dev->speed == USB_SPEED_HIGH)
+ interval = 1 << min(15, ep->desc.bInterval - 1);
+ else
+ interval = ep->desc.bInterval;
pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
usb_fill_int_urb(urb, usb_dev, pipe, data, len,
- usb_api_blocking_completion, NULL,
- ep->desc.bInterval);
+ usb_api_blocking_completion, NULL, interval);
} else
usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
usb_api_blocking_completion, NULL);
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 0e5c646cb4f6..f08ec85a6d64 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -30,7 +30,8 @@
static const struct usb_device_id usb_quirk_list[] = {
/* HP 5300/5370C scanner */
{ USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 },
-
+ /* Seiko Epson Corp - Perfection 1670 */
+ { USB_DEVICE(0x04b8, 0x011f), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Elsa MicroLink 56k (V.250) */
{ USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index a4677802fb20..2a6e3163d944 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -1835,7 +1835,7 @@ static int at91udc_resume(struct platform_device *pdev)
#define at91udc_resume NULL
#endif
-static struct platform_driver at91_udc = {
+static struct platform_driver at91_udc_driver = {
.remove = __exit_p(at91udc_remove),
.shutdown = at91udc_shutdown,
.suspend = at91udc_suspend,
@@ -1848,13 +1848,13 @@ static struct platform_driver at91_udc = {
static int __init udc_init_module(void)
{
- return platform_driver_probe(&at91_udc, at91udc_probe);
+ return platform_driver_probe(&at91_udc_driver, at91udc_probe);
}
module_init(udc_init_module);
static void __exit udc_exit_module(void)
{
- platform_driver_unregister(&at91_udc);
+ platform_driver_unregister(&at91_udc_driver);
}
module_exit(udc_exit_module);
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 7b3a326b57ab..65c91d3735de 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -297,27 +297,6 @@ goku_free_request(struct usb_ep *_ep, struct usb_request *_req)
/*-------------------------------------------------------------------------*/
-#undef USE_KMALLOC
-
-/* many common platforms have dma-coherent caches, which means that it's
- * safe to use kmalloc() memory for all i/o buffers without using any
- * cache flushing calls. (unless you're trying to share cache lines
- * between dma and non-dma activities, which is a slow idea in any case.)
- *
- * other platforms need more care, with 2.6 having a moderately general
- * solution except for the common "buffer is smaller than a page" case.
- */
-#if defined(CONFIG_X86)
-#define USE_KMALLOC
-
-#elif defined(CONFIG_MIPS) && !defined(CONFIG_DMA_NONCOHERENT)
-#define USE_KMALLOC
-
-#elif defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE)
-#define USE_KMALLOC
-
-#endif
-
/* allocating buffers this way eliminates dma mapping overhead, which
* on some platforms will mean eliminating a per-io buffer copy. with
* some kinds of system caches, further tweaks may still be needed.
@@ -334,11 +313,6 @@ goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
return NULL;
*dma = DMA_ADDR_INVALID;
-#if defined(USE_KMALLOC)
- retval = kmalloc(bytes, gfp_flags);
- if (retval)
- *dma = virt_to_phys(retval);
-#else
if (ep->dma) {
/* the main problem with this call is that it wastes memory
* on typical 1/N page allocations: it allocates 1-N pages.
@@ -348,7 +322,6 @@ goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
bytes, dma, gfp_flags);
} else
retval = kmalloc(bytes, gfp_flags);
-#endif
return retval;
}
@@ -356,7 +329,6 @@ static void
goku_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes)
{
/* free memory into the right allocator */
-#ifndef USE_KMALLOC
if (dma != DMA_ADDR_INVALID) {
struct goku_ep *ep;
@@ -365,7 +337,6 @@ goku_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes)
return;
dma_free_coherent(&ep->dev->pdev->dev, bytes, buf, dma);
} else
-#endif
kfree (buf);
}
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 8f9a2b615422..b394e63894d2 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -296,6 +296,15 @@ omap_free_request(struct usb_ep *ep, struct usb_request *_req)
/*-------------------------------------------------------------------------*/
+/*
+ * dma-coherent memory allocation (for dma-capable endpoints)
+ *
+ * NOTE: the dma_*_coherent() API calls suck. Most implementations are
+ * (a) page-oriented, so small buffers lose big; and (b) asymmetric with
+ * respect to calls with irqs disabled: alloc is safe, free is not.
+ * We currently work around (b), but not (a).
+ */
+
static void *
omap_alloc_buffer(
struct usb_ep *_ep,
@@ -307,6 +316,9 @@ omap_alloc_buffer(
void *retval;
struct omap_ep *ep;
+ if (!_ep)
+ return NULL;
+
ep = container_of(_ep, struct omap_ep, ep);
if (use_dma && ep->has_dma) {
static int warned;
@@ -326,6 +338,35 @@ omap_alloc_buffer(
return retval;
}
+static DEFINE_SPINLOCK(buflock);
+static LIST_HEAD(buffers);
+
+struct free_record {
+ struct list_head list;
+ struct device *dev;
+ unsigned bytes;
+ dma_addr_t dma;
+};
+
+static void do_free(unsigned long ignored)
+{
+ spin_lock_irq(&buflock);
+ while (!list_empty(&buffers)) {
+ struct free_record *buf;
+
+ buf = list_entry(buffers.next, struct free_record, list);
+ list_del(&buf->list);
+ spin_unlock_irq(&buflock);
+
+ dma_free_coherent(buf->dev, buf->bytes, buf, buf->dma);
+
+ spin_lock_irq(&buflock);
+ }
+ spin_unlock_irq(&buflock);
+}
+
+static DECLARE_TASKLET(deferred_free, do_free, 0);
+
static void omap_free_buffer(
struct usb_ep *_ep,
void *buf,
@@ -333,13 +374,29 @@ static void omap_free_buffer(
unsigned bytes
)
{
- struct omap_ep *ep;
+ if (!_ep) {
+ WARN_ON(1);
+ return;
+ }
- ep = container_of(_ep, struct omap_ep, ep);
- if (use_dma && _ep && ep->has_dma)
- dma_free_coherent(ep->udc->gadget.dev.parent, bytes, buf, dma);
- else
- kfree (buf);
+ /* free memory into the right allocator */
+ if (dma != DMA_ADDR_INVALID) {
+ struct omap_ep *ep;
+ struct free_record *rec = buf;
+ unsigned long flags;
+
+ ep = container_of(_ep, struct omap_ep, ep);
+
+ rec->dev = ep->udc->gadget.dev.parent;
+ rec->bytes = bytes;
+ rec->dma = dma;
+
+ spin_lock_irqsave(&buflock, flags);
+ list_add_tail(&rec->list, &buffers);
+ tasklet_schedule(&deferred_free);
+ spin_unlock_irqrestore(&buflock, flags);
+ } else
+ kfree(buf);
}
/*-------------------------------------------------------------------------*/
@@ -1691,12 +1748,38 @@ ep0out_status_stage:
udc->ep0_pending = 0;
break;
case USB_REQ_GET_STATUS:
+ /* USB_ENDPOINT_HALT status? */
+ if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT))
+ goto intf_status;
+
+ /* ep0 never stalls */
+ if (!(w_index & 0xf))
+ goto zero_status;
+
+ /* only active endpoints count */
+ ep = &udc->ep[w_index & 0xf];
+ if (w_index & USB_DIR_IN)
+ ep += 16;
+ if (!ep->desc)
+ goto do_stall;
+
+ /* iso never stalls */
+ if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)
+ goto zero_status;
+
+ /* FIXME don't assume non-halted endpoints!! */
+ ERR("%s status, can't report\n", ep->ep.name);
+ goto do_stall;
+
+intf_status:
/* return interface status. if we were pedantic,
* we'd detect non-existent interfaces, and stall.
*/
if (u.r.bRequestType
!= (USB_DIR_IN|USB_RECIP_INTERFACE))
goto delegate;
+
+zero_status:
/* return two zero bytes */
UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR;
UDC_DATA_REG = 0;
@@ -2068,7 +2151,7 @@ static irqreturn_t omap_udc_iso_irq(int irq, void *_dev)
/*-------------------------------------------------------------------------*/
-static inline int machine_needs_vbus_session(void)
+static inline int machine_without_vbus_sense(void)
{
return (machine_is_omap_innovator()
|| machine_is_omap_osk()
@@ -2156,7 +2239,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
/* boards that don't have VBUS sensing can't autogate 48MHz;
* can't enter deep sleep while a gadget driver is active.
*/
- if (machine_needs_vbus_session())
+ if (machine_without_vbus_sense())
omap_vbus_session(&udc->gadget, 1);
done:
@@ -2179,7 +2262,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
if (udc->dc_clk != NULL)
omap_udc_enable_clock(1);
- if (machine_needs_vbus_session())
+ if (machine_without_vbus_sense())
omap_vbus_session(&udc->gadget, 0);
if (udc->transceiver)
@@ -2822,7 +2905,7 @@ static int __init omap_udc_probe(struct platform_device *pdev)
hmc = HMC_1510;
type = "(unknown)";
- if (machine_is_omap_innovator() || machine_is_sx1()) {
+ if (machine_without_vbus_sense()) {
/* just set up software VBUS detect, and then
* later rig it so we always report VBUS.
* FIXME without really sensing VBUS, we can't
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index a74056488234..c7458f7e56cc 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -669,6 +669,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
*/
ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
+ mod_timer(&hcd->rh_timer, ehci->reset_done[i]);
}
}
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 9af529d22b3e..1813b7cac294 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -653,8 +653,7 @@ static int ehci_hub_control (
if (status & ~0xffff) /* only if wPortChange is interesting */
#endif
dbg_port (ehci, "GetStatus", wIndex + 1, temp);
- // we "know" this alignment is good, caller used kmalloc()...
- *((__le32 *) buf) = cpu_to_le32 (status);
+ put_unaligned(cpu_to_le32 (status), (__le32 *) buf);
break;
case SetHubFeature:
switch (wValue) {
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index 8d24d3dc0a61..1497371583b9 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -145,7 +145,8 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space)
return out - buf;
}
-static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
+static int uhci_show_qh(struct uhci_hcd *uhci,
+ struct uhci_qh *qh, char *buf, int len, int space)
{
char *out = buf;
int i, nurbs;
@@ -190,6 +191,9 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
if (list_empty(&qh->queue)) {
out += sprintf(out, "%*s queue is empty\n", space, "");
+ if (qh == uhci->skel_async_qh)
+ out += uhci_show_td(uhci->term_td, out,
+ len - (out - buf), 0);
} else {
struct urb_priv *urbp = list_entry(qh->queue.next,
struct urb_priv, node);
@@ -343,6 +347,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
struct list_head *tmp, *head;
int nframes, nerrs;
__le32 link;
+ __le32 fsbr_link;
static const char * const qh_names[] = {
"unlink", "iso", "int128", "int64", "int32", "int16",
@@ -424,21 +429,22 @@ check_link:
out += sprintf(out, "Skeleton QHs\n");
+ fsbr_link = 0;
for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
int cnt = 0;
- __le32 fsbr_link = 0;
qh = uhci->skelqh[i];
out += sprintf(out, "- skel_%s_qh\n", qh_names[i]); \
- out += uhci_show_qh(qh, out, len - (out - buf), 4);
+ out += uhci_show_qh(uhci, qh, out, len - (out - buf), 4);
/* Last QH is the Terminating QH, it's different */
if (i == SKEL_TERM) {
if (qh_element(qh) != LINK_TO_TD(uhci->term_td))
out += sprintf(out, " skel_term_qh element is not set to term_td!\n");
- if (link == LINK_TO_QH(uhci->skel_term_qh))
- goto check_qh_link;
- continue;
+ link = fsbr_link;
+ if (!link)
+ link = LINK_TO_QH(uhci->skel_term_qh);
+ goto check_qh_link;
}
head = &qh->node;
@@ -448,7 +454,7 @@ check_link:
qh = list_entry(tmp, struct uhci_qh, node);
tmp = tmp->next;
if (++cnt <= 10)
- out += uhci_show_qh(qh, out,
+ out += uhci_show_qh(uhci, qh, out,
len - (out - buf), 4);
if (!fsbr_link && qh->skel >= SKEL_FSBR)
fsbr_link = LINK_TO_QH(qh);
@@ -463,8 +469,6 @@ check_link:
link = LINK_TO_QH(uhci->skel_async_qh);
else if (!uhci->fsbr_is_on)
;
- else if (fsbr_link)
- link = fsbr_link;
else
link = LINK_TO_QH(uhci->skel_term_qh);
check_qh_link:
@@ -573,8 +577,8 @@ static const struct file_operations uhci_debug_operations = {
static inline void lprintk(char *buf)
{}
-static inline int uhci_show_qh(struct uhci_qh *qh, char *buf,
- int len, int space)
+static inline int uhci_show_qh(struct uhci_hcd *uhci,
+ struct uhci_qh *qh, char *buf, int len, int space)
{
return 0;
}
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 44da4334f1d6..d22da26ff167 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -632,7 +632,8 @@ static int uhci_start(struct usb_hcd *hcd)
*/
for (i = SKEL_ISO + 1; i < SKEL_ASYNC; ++i)
uhci->skelqh[i]->link = LINK_TO_QH(uhci->skel_async_qh);
- uhci->skel_async_qh->link = uhci->skel_term_qh->link = UHCI_PTR_TERM;
+ uhci->skel_async_qh->link = UHCI_PTR_TERM;
+ uhci->skel_term_qh->link = LINK_TO_QH(uhci->skel_term_qh);
/* This dummy TD is to work around a bug in Intel PIIX controllers */
uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index bacc25c53ba3..8e4427aebb14 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -33,6 +33,9 @@ static __u8 root_hub_hub_des[] =
/* status change bits: nonzero writes will clear */
#define RWC_BITS (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC)
+/* suspend/resume bits: port suspended or port resuming */
+#define SUSPEND_BITS (USBPORTSC_SUSP | USBPORTSC_RD)
+
/* A port that either is connected or has a changed-bit set will prevent
* us from AUTO_STOPPING.
*/
@@ -96,8 +99,8 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
int status;
int i;
- if (inw(port_addr) & (USBPORTSC_SUSP | USBPORTSC_RD)) {
- CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD);
+ if (inw(port_addr) & SUSPEND_BITS) {
+ CLR_RH_PORTSTAT(SUSPEND_BITS);
if (test_bit(port, &uhci->resuming_ports))
set_bit(port, &uhci->port_c_suspend);
@@ -107,7 +110,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
* Experiments show that some controllers take longer, so
* we'll poll for completion. */
for (i = 0; i < 10; ++i) {
- if (!(inw(port_addr) & USBPORTSC_RD))
+ if (!(inw(port_addr) & SUSPEND_BITS))
break;
udelay(1);
}
@@ -289,7 +292,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
wPortStatus |= USB_PORT_STAT_CONNECTION;
if (status & USBPORTSC_PE) {
wPortStatus |= USB_PORT_STAT_ENABLE;
- if (status & (USBPORTSC_SUSP | USBPORTSC_RD))
+ if (status & SUSPEND_BITS)
wPortStatus |= USB_PORT_STAT_SUSPEND;
}
if (status & USBPORTSC_OC)
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index f4ebdb3e488f..19a0cc02b9a2 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -45,43 +45,27 @@ static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci)
*/
static void uhci_fsbr_on(struct uhci_hcd *uhci)
{
- struct uhci_qh *fsbr_qh, *lqh, *tqh;
+ struct uhci_qh *lqh;
+ /* The terminating skeleton QH always points back to the first
+ * FSBR QH. Make the last async QH point to the terminating
+ * skeleton QH. */
uhci->fsbr_is_on = 1;
lqh = list_entry(uhci->skel_async_qh->node.prev,
struct uhci_qh, node);
-
- /* Find the first FSBR QH. Linear search through the list is
- * acceptable because normally FSBR gets turned on as soon as
- * one QH needs it. */
- fsbr_qh = NULL;
- list_for_each_entry_reverse(tqh, &uhci->skel_async_qh->node, node) {
- if (tqh->skel < SKEL_FSBR)
- break;
- fsbr_qh = tqh;
- }
-
- /* No FSBR QH means we must insert the terminating skeleton QH */
- if (!fsbr_qh) {
- uhci->skel_term_qh->link = LINK_TO_QH(uhci->skel_term_qh);
- wmb();
- lqh->link = uhci->skel_term_qh->link;
-
- /* Otherwise loop the last QH to the first FSBR QH */
- } else
- lqh->link = LINK_TO_QH(fsbr_qh);
+ lqh->link = LINK_TO_QH(uhci->skel_term_qh);
}
static void uhci_fsbr_off(struct uhci_hcd *uhci)
{
struct uhci_qh *lqh;
+ /* Remove the link from the last async QH to the terminating
+ * skeleton QH. */
uhci->fsbr_is_on = 0;
lqh = list_entry(uhci->skel_async_qh->node.prev,
struct uhci_qh, node);
-
- /* End the async list normally and unlink the terminating QH */
- lqh->link = uhci->skel_term_qh->link = UHCI_PTR_TERM;
+ lqh->link = UHCI_PTR_TERM;
}
static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb)
@@ -464,9 +448,8 @@ static void link_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh)
*/
static void link_async(struct uhci_hcd *uhci, struct uhci_qh *qh)
{
- struct uhci_qh *pqh, *lqh;
+ struct uhci_qh *pqh;
__le32 link_to_new_qh;
- __le32 *extra_link = &link_to_new_qh;
/* Find the predecessor QH for our new one and insert it in the list.
* The list of QHs is expected to be short, so linear search won't
@@ -476,31 +459,17 @@ static void link_async(struct uhci_hcd *uhci, struct uhci_qh *qh)
break;
}
list_add(&qh->node, &pqh->node);
- qh->link = pqh->link;
-
- link_to_new_qh = LINK_TO_QH(qh);
-
- /* If this is now the first FSBR QH, take special action */
- if (uhci->fsbr_is_on && pqh->skel < SKEL_FSBR &&
- qh->skel >= SKEL_FSBR) {
- lqh = list_entry(uhci->skel_async_qh->node.prev,
- struct uhci_qh, node);
-
- /* If the new QH is also the last one, we must unlink
- * the terminating skeleton QH and make the new QH point
- * back to itself. */
- if (qh == lqh) {
- qh->link = link_to_new_qh;
- extra_link = &uhci->skel_term_qh->link;
-
- /* Otherwise the last QH must point to the new QH */
- } else
- extra_link = &lqh->link;
- }
/* Link it into the schedule */
+ qh->link = pqh->link;
wmb();
- *extra_link = pqh->link = link_to_new_qh;
+ link_to_new_qh = LINK_TO_QH(qh);
+ pqh->link = link_to_new_qh;
+
+ /* If this is now the first FSBR QH, link the terminating skeleton
+ * QH to it. */
+ if (pqh->skel < SKEL_FSBR && qh->skel >= SKEL_FSBR)
+ uhci->skel_term_qh->link = link_to_new_qh;
}
/*
@@ -561,31 +530,16 @@ static void unlink_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh)
*/
static void unlink_async(struct uhci_hcd *uhci, struct uhci_qh *qh)
{
- struct uhci_qh *pqh, *lqh;
+ struct uhci_qh *pqh;
__le32 link_to_next_qh = qh->link;
pqh = list_entry(qh->node.prev, struct uhci_qh, node);
-
- /* If this is the first FSBQ QH, take special action */
- if (uhci->fsbr_is_on && pqh->skel < SKEL_FSBR &&
- qh->skel >= SKEL_FSBR) {
- lqh = list_entry(uhci->skel_async_qh->node.prev,
- struct uhci_qh, node);
-
- /* If this QH is also the last one, we must link in
- * the terminating skeleton QH. */
- if (qh == lqh) {
- link_to_next_qh = LINK_TO_QH(uhci->skel_term_qh);
- uhci->skel_term_qh->link = link_to_next_qh;
- wmb();
- qh->link = link_to_next_qh;
-
- /* Otherwise the last QH must point to the new first FSBR QH */
- } else
- lqh->link = link_to_next_qh;
- }
-
pqh->link = link_to_next_qh;
+
+ /* If this was the old first FSBR QH, link the terminating skeleton
+ * QH to the next (new first FSBR) QH. */
+ if (pqh->skel < SKEL_FSBR && qh->skel >= SKEL_FSBR)
+ uhci->skel_term_qh->link = link_to_next_qh;
mb();
}
@@ -1217,7 +1171,7 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
if (debug > 1 && errbuf) {
/* Print the chain for debugging */
- uhci_show_qh(urbp->qh, errbuf,
+ uhci_show_qh(uhci, urbp->qh, errbuf,
ERRBUF_LEN, 0);
lprintk(errbuf);
}
diff --git a/drivers/usb/misc/berry_charge.c b/drivers/usb/misc/berry_charge.c
index 60893c6c8221..b15f2fd8dab4 100644
--- a/drivers/usb/misc/berry_charge.c
+++ b/drivers/usb/misc/berry_charge.c
@@ -69,7 +69,7 @@ static int magic_charge(struct usb_device *udev)
return retval;
}
- dbg(&udev->dev, "Sending first magic command\n");
+ dbg(&udev->dev, "Sending second magic command\n");
retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
0xa2, 0x40, 0, 1, dummy_buffer, 0, 100);
if (retval != 0) {
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index 0c1d66ddb812..bc3327e3dd78 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -2905,17 +2905,31 @@ static int __init ftdi_elan_init(void)
{
int result;
printk(KERN_INFO "driver %s built at %s on %s\n", ftdi_elan_driver.name,
- __TIME__, __DATE__);
+ __TIME__, __DATE__);
init_MUTEX(&ftdi_module_lock);
INIT_LIST_HEAD(&ftdi_static_list);
status_queue = create_singlethread_workqueue("ftdi-status-control");
+ if (!status_queue)
+ goto err1;
command_queue = create_singlethread_workqueue("ftdi-command-engine");
+ if (!command_queue)
+ goto err2;
respond_queue = create_singlethread_workqueue("ftdi-respond-engine");
+ if (!respond_queue)
+ goto err3;
result = usb_register(&ftdi_elan_driver);
if (result)
printk(KERN_ERR "usb_register failed. Error number %d\n",
- result);
+ result);
return result;
+
+ err3:
+ destroy_workqueue(command_queue);
+ err2:
+ destroy_workqueue(status_queue);
+ err1:
+ printk(KERN_ERR "%s couldn't create workqueue\n", ftdi_elan_driver.name);
+ return -ENOMEM;
}
static void __exit ftdi_elan_exit(void)
diff --git a/drivers/usb/net/dm9601.c b/drivers/usb/net/dm9601.c
index 4a932e1cd93b..5130cc7eb314 100644
--- a/drivers/usb/net/dm9601.c
+++ b/drivers/usb/net/dm9601.c
@@ -571,9 +571,21 @@ static const struct driver_info dm9601_info = {
static const struct usb_device_id products[] = {
{
+ USB_DEVICE(0x07aa, 0x9601), /* Corega FEther USB-TXC */
+ .driver_info = (unsigned long)&dm9601_info,
+ },
+ {
USB_DEVICE(0x0a46, 0x9601), /* Davicom USB-100 */
.driver_info = (unsigned long)&dm9601_info,
},
+ {
+ USB_DEVICE(0x0a46, 0x6688), /* ZT6688 USB NIC */
+ .driver_info = (unsigned long)&dm9601_info,
+ },
+ {
+ USB_DEVICE(0x0a46, 0x0268), /* ShanTou ST268 USB NIC */
+ .driver_info = (unsigned long)&dm9601_info,
+ },
{}, // END
};
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 18816bf96a4d..39a498362594 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -18,11 +18,6 @@
static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
- { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */
- { USB_DEVICE(0x1410, 0x1130) }, /* Novatel Wireless S720 CDMA/EV-DO */
- { USB_DEVICE(0x1410, 0x2110) }, /* Novatel Wireless U720 CDMA/EV-DO */
- { USB_DEVICE(0x1410, 0x1430) }, /* Novatel Merlin XU870 HSDPA/3G */
- { USB_DEVICE(0x1410, 0x1100) }, /* ExpressCard34 Qualcomm 3G CDMA */
{ USB_DEVICE(0x413c, 0x8115) }, /* Dell Wireless HSDPA 5500 */
{ },
};
@@ -44,8 +39,43 @@ struct airprime_private {
int outstanding_urbs;
int throttled;
struct urb *read_urbp[NUM_READ_URBS];
+
+ /* Settings for the port */
+ int rts_state; /* Handshaking pins (outputs) */
+ int dtr_state;
+ int cts_state; /* Handshaking pins (inputs) */
+ int dsr_state;
+ int dcd_state;
+ int ri_state;
};
+static int airprime_send_setup(struct usb_serial_port *port)
+{
+ struct usb_serial *serial = port->serial;
+ struct airprime_private *priv;
+
+ dbg("%s", __FUNCTION__);
+
+ if (port->number != 0)
+ return 0;
+
+ priv = usb_get_serial_port_data(port);
+
+ if (port->tty) {
+ int val = 0;
+ if (priv->dtr_state)
+ val |= 0x01;
+ if (priv->rts_state)
+ val |= 0x02;
+
+ return usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
+ }
+
+ return 0;
+}
+
static void airprime_read_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
@@ -118,6 +148,10 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
usb_set_serial_port_data(port, priv);
}
+ /* Set some sane defaults */
+ priv->rts_state = 1;
+ priv->dtr_state = 1;
+
for (i = 0; i < NUM_READ_URBS; ++i) {
buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!buffer) {
@@ -151,6 +185,9 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
/* remember this urb so we can kill it when the port is closed */
priv->read_urbp[i] = urb;
}
+
+ airprime_send_setup(port);
+
goto out;
errout:
@@ -176,6 +213,11 @@ static void airprime_close(struct usb_serial_port *port, struct file * filp)
dbg("%s - port %d", __FUNCTION__, port->number);
+ priv->rts_state = 0;
+ priv->dtr_state = 0;
+
+ airprime_send_setup(port);
+
for (i = 0; i < NUM_READ_URBS; ++i) {
usb_kill_urb (priv->read_urbp[i]);
kfree (priv->read_urbp[i]->transfer_buffer);
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index db623e754899..d7d0ba986a80 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -63,6 +63,8 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
{ USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
{ USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */
+ { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
+ { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
{ USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
{ USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
{ USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index c525b42dadde..8ff9d54b21e6 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -315,6 +315,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_232RL_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
@@ -420,6 +421,14 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_ELV_ALC8500_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_PYRAMID_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1000PC_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_IBS_US485_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_IBS_PICPRO_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_IBS_PCMCIA_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_IBS_PK1_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_IBS_RS232MON_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_IBS_APP70_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) },
/*
* These will probably use user-space drivers. Uncomment them if
* you need them or use the user-specified vendor/product module
@@ -459,6 +468,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) },
{ USB_DEVICE(FALCOM_VID, FALCOM_SAMBA_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) },
+ { USB_DEVICE(TTI_VID, TTI_QL355P_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) },
{ USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
{ USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },
@@ -533,6 +543,7 @@ static const char *ftdi_chip_name[] = {
[FT8U232AM] = "FT8U232AM",
[FT232BM] = "FT232BM",
[FT2232C] = "FT2232C",
+ [FT232RL] = "FT232RL",
};
@@ -588,6 +599,8 @@ struct ftdi_private {
static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id);
static int ftdi_sio_attach (struct usb_serial *serial);
static void ftdi_shutdown (struct usb_serial *serial);
+static int ftdi_sio_port_probe (struct usb_serial_port *port);
+static int ftdi_sio_port_remove (struct usb_serial_port *port);
static int ftdi_open (struct usb_serial_port *port, struct file *filp);
static void ftdi_close (struct usb_serial_port *port, struct file *filp);
static int ftdi_write (struct usb_serial_port *port, const unsigned char *buf, int count);
@@ -622,6 +635,8 @@ static struct usb_serial_driver ftdi_sio_device = {
.num_bulk_out = 1,
.num_ports = 1,
.probe = ftdi_sio_probe,
+ .port_probe = ftdi_sio_port_probe,
+ .port_remove = ftdi_sio_port_remove,
.open = ftdi_open,
.close = ftdi_close,
.throttle = ftdi_throttle,
@@ -864,6 +879,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
break;
case FT232BM: /* FT232BM chip */
case FT2232C: /* FT2232C chip */
+ case FT232RL:
if (baud <= 3000000) {
div_value = ftdi_232bm_baud_to_divisor(baud);
} else {
@@ -1006,9 +1022,12 @@ static void ftdi_determine_type(struct usb_serial_port *port)
/* (It might be a BM because of the iSerialNumber bug,
* but it will still work as an AM device.) */
priv->chip_type = FT8U232AM;
- } else {
+ } else if (version < 0x600) {
/* Assume its an FT232BM (or FT245BM) */
priv->chip_type = FT232BM;
+ } else {
+ /* Assume its an FT232R */
+ priv->chip_type = FT232RL;
}
info("Detected %s", ftdi_chip_name[priv->chip_type]);
}
@@ -1024,11 +1043,10 @@ static ssize_t show_latency_timer(struct device *dev, struct device_attribute *a
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
- struct usb_device *udev;
+ struct usb_device *udev = port->serial->dev;
unsigned short latency = 0;
int rv = 0;
- udev = to_usb_device(dev);
dbg("%s",__FUNCTION__);
@@ -1052,13 +1070,11 @@ static ssize_t store_latency_timer(struct device *dev, struct device_attribute *
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
- struct usb_device *udev;
+ struct usb_device *udev = port->serial->dev;
char buf[1];
int v = simple_strtoul(valbuf, NULL, 10);
int rv = 0;
- udev = to_usb_device(dev);
-
dbg("%s: setting latency timer = %i", __FUNCTION__, v);
rv = usb_control_msg(udev,
@@ -1083,13 +1099,11 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
- struct usb_device *udev;
+ struct usb_device *udev = port->serial->dev;
char buf[1];
int v = simple_strtoul(valbuf, NULL, 10);
int rv = 0;
- udev = to_usb_device(dev);
-
dbg("%s: setting event char = %i", __FUNCTION__, v);
rv = usb_control_msg(udev,
@@ -1110,46 +1124,38 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att
static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer);
static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char);
-static int create_sysfs_attrs(struct usb_serial *serial)
+static int create_sysfs_attrs(struct usb_serial_port *port)
{
- struct ftdi_private *priv;
- struct usb_device *udev;
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
int retval = 0;
dbg("%s",__FUNCTION__);
- priv = usb_get_serial_port_data(serial->port[0]);
- udev = serial->dev;
-
/* XXX I've no idea if the original SIO supports the event_char
* sysfs parameter, so I'm playing it safe. */
if (priv->chip_type != SIO) {
dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]);
- retval = device_create_file(&udev->dev, &dev_attr_event_char);
+ retval = device_create_file(&port->dev, &dev_attr_event_char);
if ((!retval) &&
(priv->chip_type == FT232BM || priv->chip_type == FT2232C)) {
- retval = device_create_file(&udev->dev,
+ retval = device_create_file(&port->dev,
&dev_attr_latency_timer);
}
}
return retval;
}
-static void remove_sysfs_attrs(struct usb_serial *serial)
+static void remove_sysfs_attrs(struct usb_serial_port *port)
{
- struct ftdi_private *priv;
- struct usb_device *udev;
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
dbg("%s",__FUNCTION__);
- priv = usb_get_serial_port_data(serial->port[0]);
- udev = serial->dev;
-
/* XXX see create_sysfs_attrs */
if (priv->chip_type != SIO) {
- device_remove_file(&udev->dev, &dev_attr_event_char);
+ device_remove_file(&port->dev, &dev_attr_event_char);
if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) {
- device_remove_file(&udev->dev, &dev_attr_latency_timer);
+ device_remove_file(&port->dev, &dev_attr_latency_timer);
}
}
@@ -1169,13 +1175,9 @@ static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id
return (0);
}
-/* attach subroutine */
-static int ftdi_sio_attach (struct usb_serial *serial)
+static int ftdi_sio_port_probe(struct usb_serial_port *port)
{
- struct usb_serial_port *port = serial->port[0];
struct ftdi_private *priv;
- struct ftdi_sio_quirk *quirk;
- int retval;
dbg("%s",__FUNCTION__);
@@ -1215,19 +1217,21 @@ static int ftdi_sio_attach (struct usb_serial *serial)
kfree(port->bulk_out_buffer);
port->bulk_out_buffer = NULL;
- usb_set_serial_port_data(serial->port[0], priv);
+ usb_set_serial_port_data(port, priv);
- ftdi_determine_type (serial->port[0]);
- retval = create_sysfs_attrs(serial);
- if (retval)
- dev_err(&serial->dev->dev, "Error creating sysfs files, "
- "continuing\n");
+ ftdi_determine_type (port);
+ create_sysfs_attrs(port);
+ return 0;
+}
+/* attach subroutine */
+static int ftdi_sio_attach (struct usb_serial *serial)
+{
/* Check for device requiring special set up. */
- quirk = (struct ftdi_sio_quirk *)usb_get_serial_data(serial);
- if (quirk && quirk->setup) {
+ struct ftdi_sio_quirk *quirk = usb_get_serial_data(serial);
+
+ if (quirk && quirk->setup)
quirk->setup(serial);
- }
return 0;
} /* ftdi_sio_attach */
@@ -1271,17 +1275,18 @@ static void ftdi_HE_TIRA1_setup (struct usb_serial *serial)
* calls __serial_close for each open of the port
* shutdown is called then (ie ftdi_shutdown)
*/
-
-
static void ftdi_shutdown (struct usb_serial *serial)
-{ /* ftdi_shutdown */
+{
+ dbg("%s", __FUNCTION__);
+}
- struct usb_serial_port *port = serial->port[0];
+static int ftdi_sio_port_remove(struct usb_serial_port *port)
+{
struct ftdi_private *priv = usb_get_serial_port_data(port);
dbg("%s", __FUNCTION__);
- remove_sysfs_attrs(serial);
+ remove_sysfs_attrs(port);
/* all open ports are closed at this point
* (by usbserial.c:__serial_close, which calls ftdi_close)
@@ -1291,8 +1296,9 @@ static void ftdi_shutdown (struct usb_serial *serial)
usb_set_serial_port_data(port, NULL);
kfree(priv);
}
-} /* ftdi_shutdown */
+ return 0;
+}
static int ftdi_open (struct usb_serial_port *port, struct file *filp)
{ /* ftdi_open */
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 1bdda935f7d9..513cfe1b768b 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -27,6 +27,7 @@
#define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */
#define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
#define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
+#define FTDI_232RL_PID 0xFBFA /* Product ID for FT232RL */
#define FTDI_RELAIS_PID 0xFA10 /* Relais device from Rudolf Gugler */
#define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */
#define FTDI_NF_RIC_PID 0x0001 /* Product Id */
@@ -339,6 +340,12 @@
#define FTDI_SUUNTO_SPORTS_PID 0xF680 /* Suunto Sports instrument */
/*
+ * TTi (Thurlby Thandar Instruments)
+ */
+#define TTI_VID 0x103E /* Vendor Id */
+#define TTI_QL355P_PID 0x03E8 /* TTi QL355P power supply */
+
+/*
* Definitions for B&B Electronics products.
*/
#define BANDB_VID 0x0856 /* B&B Electronics Vendor ID */
@@ -497,6 +504,19 @@
#define TELLDUS_VID 0x1781 /* Vendor ID */
#define TELLDUS_TELLSTICK_PID 0x0C30 /* RF control dongle 433 MHz using FT232RL */
+/*
+ * IBS elektronik product ids
+ * Submitted by Thomas Schleusener
+ */
+#define FTDI_IBS_US485_PID 0xff38 /* IBS US485 (USB<-->RS422/485 interface) */
+#define FTDI_IBS_PICPRO_PID 0xff39 /* IBS PIC-Programmer */
+#define FTDI_IBS_PCMCIA_PID 0xff3a /* IBS Card reader for PCMCIA SRAM-cards */
+#define FTDI_IBS_PK1_PID 0xff3b /* IBS PK1 - Particel counter */
+#define FTDI_IBS_RS232MON_PID 0xff3c /* IBS RS232 - Monitor */
+#define FTDI_IBS_APP70_PID 0xff3d /* APP 70 (dust monitoring system) */
+#define FTDI_IBS_PEDO_PID 0xff3e /* IBS PEDO-Modem (RF modem 868.35 MHz) */
+#define FTDI_IBS_PROD_PID 0xff3f /* future device */
+
/* Commands */
#define FTDI_SIO_RESET 0 /* Reset the port */
#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */
@@ -620,6 +640,7 @@ typedef enum {
FT8U232AM = 2,
FT232BM = 3,
FT2232C = 4,
+ FT232RL = 5,
} ftdi_chip_type_t;
typedef enum {
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 53baeec8f265..4f8282ad7720 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -20,13 +20,14 @@
#include <linux/usb/serial.h>
#include <asm/uaccess.h>
-static int generic_probe(struct usb_interface *interface,
- const struct usb_device_id *id);
-
static int debug;
#ifdef CONFIG_USB_SERIAL_GENERIC
+
+static int generic_probe(struct usb_interface *interface,
+ const struct usb_device_id *id);
+
static __u16 vendor = 0x05f9;
static __u16 product = 0xffff;
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index a408184334ea..d16e2e1764ad 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -247,6 +247,8 @@ static struct usb_device_id ipaq_id_table [] = {
{ USB_DEVICE(0x04AD, 0x0301) }, /* USB Sync 0301 */
{ USB_DEVICE(0x04AD, 0x0302) }, /* USB Sync 0302 */
{ USB_DEVICE(0x04AD, 0x0303) }, /* USB Sync 0303 */
+ { USB_DEVICE(0x04AD, 0x0306) }, /* GPS Pocket PC USB Sync */
+ { USB_DEVICE(0x04B7, 0x0531) }, /* MyGuide 7000 XL USB Sync */
{ USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */
{ USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */
{ USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 2d588fb82573..19bf403f9db2 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -1628,6 +1628,7 @@ static struct usb_serial_driver moschip7720_2port_driver = {
.chars_in_buffer = mos7720_chars_in_buffer,
.break_ctl = mos7720_break,
.read_bulk_callback = mos7720_bulk_in_callback,
+ .read_int_callback = mos7720_interrupt_callback,
};
static int __init moschip7720_init(void)
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index db92a7fb1f7c..e178e6f40319 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -109,7 +109,6 @@ static int option_send_setup(struct usb_serial_port *port);
#define HUAWEI_PRODUCT_E220 0x1003
#define NOVATELWIRELESS_VENDOR_ID 0x1410
-#define NOVATELWIRELESS_PRODUCT_U740 0x1400
#define ANYDATA_VENDOR_ID 0x16d5
#define ANYDATA_PRODUCT_ID 0x6501
@@ -152,7 +151,19 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_NETWORK) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) },
- { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1100) }, /* Novatel Merlin XS620/S640 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1110) }, /* Novatel Merlin S620 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1120) }, /* Novatel Merlin EX720 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1130) }, /* Novatel Merlin S720 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1400) }, /* Novatel U730 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1410) }, /* Novatel U740 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1420) }, /* Novatel EU870 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1430) }, /* Novatel Merlin XU870 HSDPA/3G */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1430) }, /* Novatel XU870 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2100) }, /* Novatel EV620 CDMA/EV-DO */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2110) }, /* Novatel Merlin ES620 / Merlin ES720 / Ovation U720 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2130) }, /* Novatel Merlin ES620 SM Bus */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2410) }, /* Novatel EU740 */
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
{ } /* Terminating entry */
};
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 6bf22a28adb8..7639022cdf84 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -99,9 +99,12 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po
continue;
*minor = i;
+ j = 0;
dbg("%s - minor base = %d", __FUNCTION__, *minor);
- for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i)
+ for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) {
serial_table[i] = serial;
+ serial->port[j++]->number = i;
+ }
spin_unlock(&table_lock);
return serial;
}
@@ -826,7 +829,6 @@ int usb_serial_probe(struct usb_interface *interface,
num_ports = type->num_ports;
}
- serial->minor = minor;
serial->num_ports = num_ports;
serial->num_bulk_in = num_bulk_in;
serial->num_bulk_out = num_bulk_out;
@@ -847,7 +849,6 @@ int usb_serial_probe(struct usb_interface *interface,
port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
if (!port)
goto probe_error;
- port->number = i + serial->minor;
port->serial = serial;
spin_lock_init(&port->lock);
mutex_init(&port->mutex);
@@ -980,6 +981,7 @@ int usb_serial_probe(struct usb_interface *interface,
dev_err(&interface->dev, "No more free serial devices\n");
goto probe_error;
}
+ serial->minor = minor;
/* register all of the individual ports with the driver core */
for (i = 0; i < num_ports; ++i) {
@@ -1034,9 +1036,6 @@ probe_error:
kfree(port->interrupt_out_buffer);
}
- /* return the minor range that this device had */
- return_serial (serial);
-
/* free up any memory that we allocated */
for (i = 0; i < serial->num_port_pointers; ++i)
kfree(serial->port[i]);
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 9644a8ea4aa7..4a9d0d5c7282 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -146,6 +146,13 @@ UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* Reported by Andrew Nayenko <relan@bk.ru> */
+UNUSUAL_DEV( 0x0421, 0x0019, 0x0592, 0x0592,
+ "Nokia",
+ "Nokia 6288",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_MAX_SECTORS_64 ),
+
/* Reported by Mario Rettig <mariorettig@web.de> */
UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100,
"Nokia",
@@ -320,6 +327,13 @@ UNUSUAL_DEV( 0x04b0, 0x040d, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY),
+/* Reported by Emil Larsson <emil@swip.net> */
+UNUSUAL_DEV( 0x04b0, 0x0411, 0x0100, 0x0100,
+ "NIKON",
+ "NIKON DSC D80",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY),
+
/* BENQ DC5330
* Reported by Manuel Fombuena <mfombuena@ya.com> and
* Frank Copeland <fjc@thingy.apana.org.au> */
@@ -1395,16 +1409,6 @@ UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
-/* Reported by Thomas Baechler <thomas@archlinux.org>
- * Fixes I/O errors with Teac HD-35PU devices
- */
-
-UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201,
- "Super Top",
- "USB 2.0 IDE DEVICE",
- US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_IGNORE_RESIDUE),
-
/* patch submitted by Davide Perini <perini.davide@dpsoftware.org>
* and Renato Perini <rperini@email.it>
*/
@@ -1414,6 +1418,16 @@ UNUSUAL_DEV( 0x22b8, 0x3010, 0x0001, 0x0001,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ),
+/*
+ * Patch by Pete Zaitcev <zaitcev@redhat.com>
+ * Report by Mark Patton. Red Hat bz#208928.
+ */
+UNUSUAL_DEV( 0x22b8, 0x4810, 0x0001, 0x0001,
+ "Motorola",
+ "RAZR V3i",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY),
+
/* Reported by Radovan Garabik <garabik@kassiopeia.juls.savba.sk> */
UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999,
"MPIO",
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 35d2abd1ed50..5af684b40496 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1320,7 +1320,7 @@ config FB_AU1100
config FB_AU1200
bool "Au1200 LCD Driver"
- depends on FB && MIPS && SOC_AU1200
+ depends on (FB = y) && MIPS && SOC_AU1200
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -1470,7 +1470,7 @@ config FB_G364
config FB_68328
bool "Motorola 68328 native frame buffer support"
- depends on FB && (M68328 || M68EZ328 || M68VZ328)
+ depends on (FB = y) && (M68328 || M68EZ328 || M68VZ328)
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -1616,7 +1616,7 @@ config FB_IBM_GXT4500
config FB_PS3
bool "PS3 GPU framebuffer driver"
- depends on FB && PS3_PS3AV
+ depends on (FB = y) && PS3_PS3AV
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
index d1312477813e..6b488b8a7eee 100644
--- a/drivers/video/backlight/locomolcd.c
+++ b/drivers/video/backlight/locomolcd.c
@@ -199,8 +199,8 @@ static int locomolcd_remove(struct locomo_dev *dev)
{
unsigned long flags;
- locomobl_data.brightness = 0;
- locomobl_data.power = 0;
+ locomolcd_bl_device->props.brightness = 0;
+ locomolcd_bl_device->props.power = 0;
locomolcd_set_intensity(locomolcd_bl_device);
backlight_device_unregister(locomolcd_bl_device);
diff --git a/drivers/video/backlight/progear_bl.c b/drivers/video/backlight/progear_bl.c
index 702269357861..836ab4df0ef2 100644
--- a/drivers/video/backlight/progear_bl.c
+++ b/drivers/video/backlight/progear_bl.c
@@ -65,13 +65,13 @@ static int progearbl_probe(struct platform_device *pdev)
u8 temp;
struct backlight_device *progear_backlight_device;
- pmu_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, 0);
+ pmu_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL);
if (!pmu_dev) {
printk("ALI M7101 PMU not found.\n");
return -ENODEV;
}
- sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, 0);
+ sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
if (!sb_dev) {
printk("ALI 1533 SB not found.\n");
pci_dev_put(pmu_dev);
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index 9bb6257d6918..b0b2e40bbd9f 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -186,8 +186,7 @@ static int bw2_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
* Initialisation
*/
-static void
-bw2_init_fix(struct fb_info *info, int linebytes)
+static void __devinit bw2_init_fix(struct fb_info *info, int linebytes)
{
strlcpy(info->fix.id, "bwtwo", sizeof(info->fix.id));
@@ -199,43 +198,44 @@ bw2_init_fix(struct fb_info *info, int linebytes)
info->fix.accel = FB_ACCEL_SUN_BWTWO;
}
-static u8 bw2regs_1600[] __initdata = {
+static u8 bw2regs_1600[] __devinitdata = {
0x14, 0x8b, 0x15, 0x28, 0x16, 0x03, 0x17, 0x13,
0x18, 0x7b, 0x19, 0x05, 0x1a, 0x34, 0x1b, 0x2e,
0x1c, 0x00, 0x1d, 0x0a, 0x1e, 0xff, 0x1f, 0x01,
0x10, 0x21, 0
};
-static u8 bw2regs_ecl[] __initdata = {
+static u8 bw2regs_ecl[] __devinitdata = {
0x14, 0x65, 0x15, 0x1e, 0x16, 0x04, 0x17, 0x0c,
0x18, 0x5e, 0x19, 0x03, 0x1a, 0xa7, 0x1b, 0x23,
0x1c, 0x00, 0x1d, 0x08, 0x1e, 0xff, 0x1f, 0x01,
0x10, 0x20, 0
};
-static u8 bw2regs_analog[] __initdata = {
+static u8 bw2regs_analog[] __devinitdata = {
0x14, 0xbb, 0x15, 0x2b, 0x16, 0x03, 0x17, 0x13,
0x18, 0xb0, 0x19, 0x03, 0x1a, 0xa6, 0x1b, 0x22,
0x1c, 0x01, 0x1d, 0x05, 0x1e, 0xff, 0x1f, 0x01,
0x10, 0x20, 0
};
-static u8 bw2regs_76hz[] __initdata = {
+static u8 bw2regs_76hz[] __devinitdata = {
0x14, 0xb7, 0x15, 0x27, 0x16, 0x03, 0x17, 0x0f,
0x18, 0xae, 0x19, 0x03, 0x1a, 0xae, 0x1b, 0x2a,
0x1c, 0x01, 0x1d, 0x09, 0x1e, 0xff, 0x1f, 0x01,
0x10, 0x24, 0
};
-static u8 bw2regs_66hz[] __initdata = {
+static u8 bw2regs_66hz[] __devinitdata = {
0x14, 0xbb, 0x15, 0x2b, 0x16, 0x04, 0x17, 0x14,
0x18, 0xae, 0x19, 0x03, 0x1a, 0xa8, 0x1b, 0x24,
0x1c, 0x01, 0x1d, 0x05, 0x1e, 0xff, 0x1f, 0x01,
0x10, 0x20, 0
};
-static void bw2_do_default_mode(struct bw2_par *par, struct fb_info *info,
- int *linebytes)
+static void __devinit bw2_do_default_mode(struct bw2_par *par,
+ struct fb_info *info,
+ int *linebytes)
{
u8 status, mon;
u8 *p;
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
index ec6a51a5822d..b071bb632b97 100644
--- a/drivers/video/cg14.c
+++ b/drivers/video/cg14.c
@@ -354,7 +354,8 @@ static int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
* Initialisation
*/
-static void cg14_init_fix(struct fb_info *info, int linebytes, struct device_node *dp)
+static void __devinit cg14_init_fix(struct fb_info *info, int linebytes,
+ struct device_node *dp)
{
const char *name = dp->name;
@@ -368,7 +369,7 @@ static void cg14_init_fix(struct fb_info *info, int linebytes, struct device_nod
info->fix.accel = FB_ACCEL_SUN_CG14;
}
-static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] __initdata = {
+static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] __devinitdata = {
{
.voff = CG14_REGS,
.poff = 0x80000000,
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index ada6f7e3a891..767c850f8eb7 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -186,8 +186,7 @@ static int cg3_setcolreg(unsigned regno,
* @blank_mode: the blank mode we want.
* @info: frame buffer structure that represents a single frame buffer
*/
-static int
-cg3_blank(int blank, struct fb_info *info)
+static int cg3_blank(int blank, struct fb_info *info)
{
struct cg3_par *par = (struct cg3_par *) info->par;
struct cg3_regs __iomem *regs = par->regs;
@@ -251,8 +250,8 @@ static int cg3_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
* Initialisation
*/
-static void
-cg3_init_fix(struct fb_info *info, int linebytes, struct device_node *dp)
+static void __devinit cg3_init_fix(struct fb_info *info, int linebytes,
+ struct device_node *dp)
{
strlcpy(info->fix.id, dp->name, sizeof(info->fix.id));
@@ -264,8 +263,8 @@ cg3_init_fix(struct fb_info *info, int linebytes, struct device_node *dp)
info->fix.accel = FB_ACCEL_SUN_CGTHREE;
}
-static void cg3_rdi_maybe_fixup_var(struct fb_var_screeninfo *var,
- struct device_node *dp)
+static void __devinit cg3_rdi_maybe_fixup_var(struct fb_var_screeninfo *var,
+ struct device_node *dp)
{
char *params;
char *p;
@@ -287,36 +286,36 @@ static void cg3_rdi_maybe_fixup_var(struct fb_var_screeninfo *var,
}
}
-static u8 cg3regvals_66hz[] __initdata = { /* 1152 x 900, 66 Hz */
+static u8 cg3regvals_66hz[] __devinitdata = { /* 1152 x 900, 66 Hz */
0x14, 0xbb, 0x15, 0x2b, 0x16, 0x04, 0x17, 0x14,
0x18, 0xae, 0x19, 0x03, 0x1a, 0xa8, 0x1b, 0x24,
0x1c, 0x01, 0x1d, 0x05, 0x1e, 0xff, 0x1f, 0x01,
0x10, 0x20, 0
};
-static u8 cg3regvals_76hz[] __initdata = { /* 1152 x 900, 76 Hz */
+static u8 cg3regvals_76hz[] __devinitdata = { /* 1152 x 900, 76 Hz */
0x14, 0xb7, 0x15, 0x27, 0x16, 0x03, 0x17, 0x0f,
0x18, 0xae, 0x19, 0x03, 0x1a, 0xae, 0x1b, 0x2a,
0x1c, 0x01, 0x1d, 0x09, 0x1e, 0xff, 0x1f, 0x01,
0x10, 0x24, 0
};
-static u8 cg3regvals_rdi[] __initdata = { /* 640 x 480, cgRDI */
+static u8 cg3regvals_rdi[] __devinitdata = { /* 640 x 480, cgRDI */
0x14, 0x70, 0x15, 0x20, 0x16, 0x08, 0x17, 0x10,
0x18, 0x06, 0x19, 0x02, 0x1a, 0x31, 0x1b, 0x51,
0x1c, 0x06, 0x1d, 0x0c, 0x1e, 0xff, 0x1f, 0x01,
0x10, 0x22, 0
};
-static u8 *cg3_regvals[] __initdata = {
+static u8 *cg3_regvals[] __devinitdata = {
cg3regvals_66hz, cg3regvals_76hz, cg3regvals_rdi
};
-static u_char cg3_dacvals[] __initdata = {
+static u_char cg3_dacvals[] __devinitdata = {
4, 0xff, 5, 0x00, 6, 0x70, 7, 0x00, 0
};
-static void cg3_do_default_mode(struct cg3_par *par)
+static void __devinit cg3_do_default_mode(struct cg3_par *par)
{
enum cg3_type type;
u8 *p;
@@ -433,7 +432,8 @@ static int __devinit cg3_init_one(struct of_device *op)
return 0;
}
-static int __devinit cg3_probe(struct of_device *dev, const struct of_device_id *match)
+static int __devinit cg3_probe(struct of_device *dev,
+ const struct of_device_id *match)
{
struct of_device *op = to_of_device(&dev->dev);
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
index 15854aec3180..1d4e8354b561 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/ffb.c
@@ -336,14 +336,30 @@ struct ffb_dac {
u32 value2;
};
+#define FFB_DAC_UCTRL 0x1001 /* User Control */
+#define FFB_DAC_UCTRL_MANREV 0x00000f00 /* 4-bit Manufacturing Revision */
+#define FFB_DAC_UCTRL_MANREV_SHIFT 8
+#define FFB_DAC_TGEN 0x6000 /* Timing Generator */
+#define FFB_DAC_TGEN_VIDE 0x00000001 /* Video Enable */
+#define FFB_DAC_DID 0x8000 /* Device Identification */
+#define FFB_DAC_DID_PNUM 0x0ffff000 /* Device Part Number */
+#define FFB_DAC_DID_PNUM_SHIFT 12
+#define FFB_DAC_DID_REV 0xf0000000 /* Device Revision */
+#define FFB_DAC_DID_REV_SHIFT 28
+
+#define FFB_DAC_CUR_CTRL 0x100
+#define FFB_DAC_CUR_CTRL_P0 0x00000001
+#define FFB_DAC_CUR_CTRL_P1 0x00000002
+
struct ffb_par {
spinlock_t lock;
struct ffb_fbc __iomem *fbc;
struct ffb_dac __iomem *dac;
u32 flags;
-#define FFB_FLAG_AFB 0x00000001
-#define FFB_FLAG_BLANKED 0x00000002
+#define FFB_FLAG_AFB 0x00000001 /* AFB m3 or m6 */
+#define FFB_FLAG_BLANKED 0x00000002 /* screen is blanked */
+#define FFB_FLAG_INVCURSOR 0x00000004 /* DAC has inverted cursor logic */
u32 fg_cache __attribute__((aligned (8)));
u32 bg_cache;
@@ -354,7 +370,6 @@ struct ffb_par {
unsigned long physbase;
unsigned long fbsize;
- int dac_rev;
int board_type;
};
@@ -426,11 +441,12 @@ static void ffb_switch_from_graph(struct ffb_par *par)
FFBWait(par);
/* Disable cursor. */
- upa_writel(0x100, &dac->type2);
- if (par->dac_rev <= 2)
+ upa_writel(FFB_DAC_CUR_CTRL, &dac->type2);
+ if (par->flags & FFB_FLAG_INVCURSOR)
upa_writel(0, &dac->value2);
else
- upa_writel(3, &dac->value2);
+ upa_writel((FFB_DAC_CUR_CTRL_P0 |
+ FFB_DAC_CUR_CTRL_P1), &dac->value2);
spin_unlock_irqrestore(&par->lock, flags);
}
@@ -664,18 +680,18 @@ ffb_blank(int blank, struct fb_info *info)
struct ffb_par *par = (struct ffb_par *) info->par;
struct ffb_dac __iomem *dac = par->dac;
unsigned long flags;
- u32 tmp;
+ u32 val;
+ int i;
spin_lock_irqsave(&par->lock, flags);
FFBWait(par);
+ upa_writel(FFB_DAC_TGEN, &dac->type);
+ val = upa_readl(&dac->value);
switch (blank) {
case FB_BLANK_UNBLANK: /* Unblanking */
- upa_writel(0x6000, &dac->type);
- tmp = (upa_readl(&dac->value) | 0x1);
- upa_writel(0x6000, &dac->type);
- upa_writel(tmp, &dac->value);
+ val |= FFB_DAC_TGEN_VIDE;
par->flags &= ~FFB_FLAG_BLANKED;
break;
@@ -683,13 +699,16 @@ ffb_blank(int blank, struct fb_info *info)
case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
case FB_BLANK_POWERDOWN: /* Poweroff */
- upa_writel(0x6000, &dac->type);
- tmp = (upa_readl(&dac->value) & ~0x1);
- upa_writel(0x6000, &dac->type);
- upa_writel(tmp, &dac->value);
+ val &= ~FFB_DAC_TGEN_VIDE;
par->flags |= FFB_FLAG_BLANKED;
break;
}
+ upa_writel(FFB_DAC_TGEN, &dac->type);
+ upa_writel(val, &dac->value);
+ for (i = 0; i < 10; i++) {
+ upa_writel(FFB_DAC_TGEN, &dac->type);
+ upa_readl(&dac->value);
+ }
spin_unlock_irqrestore(&par->lock, flags);
@@ -894,6 +913,7 @@ static int ffb_init_one(struct of_device *op)
struct ffb_dac __iomem *dac;
struct all_info *all;
int err;
+ u32 dac_pnum, dac_rev, dac_mrev;
all = kzalloc(sizeof(*all), GFP_KERNEL);
if (!all)
@@ -948,17 +968,31 @@ static int ffb_init_one(struct of_device *op)
if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0)
upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
- ffb_switch_from_graph(&all->par);
-
dac = all->par.dac;
- upa_writel(0x8000, &dac->type);
- all->par.dac_rev = upa_readl(&dac->value) >> 0x1c;
+ upa_writel(FFB_DAC_DID, &dac->type);
+ dac_pnum = upa_readl(&dac->value);
+ dac_rev = (dac_pnum & FFB_DAC_DID_REV) >> FFB_DAC_DID_REV_SHIFT;
+ dac_pnum = (dac_pnum & FFB_DAC_DID_PNUM) >> FFB_DAC_DID_PNUM_SHIFT;
+
+ upa_writel(FFB_DAC_UCTRL, &dac->type);
+ dac_mrev = upa_readl(&dac->value);
+ dac_mrev = (dac_mrev & FFB_DAC_UCTRL_MANREV) >>
+ FFB_DAC_UCTRL_MANREV_SHIFT;
/* Elite3D has different DAC revision numbering, and no DAC revisions
- * have the reversed meaning of cursor enable.
+ * have the reversed meaning of cursor enable. Otherwise, Pacifica 1
+ * ramdacs with manufacturing revision less than 3 have inverted
+ * cursor logic. We identify Pacifica 1 as not Pacifica 2, the
+ * latter having a part number value of 0x236e.
*/
- if (all->par.flags & FFB_FLAG_AFB)
- all->par.dac_rev = 10;
+ if ((all->par.flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) {
+ all->par.flags &= ~FFB_FLAG_INVCURSOR;
+ } else {
+ if (dac_mrev < 3)
+ all->par.flags |= FFB_FLAG_INVCURSOR;
+ }
+
+ ffb_switch_from_graph(&all->par);
/* Unblank it just to be sure. When there are multiple
* FFB/AFB cards in the system, or it is not the OBP
@@ -993,10 +1027,12 @@ static int ffb_init_one(struct of_device *op)
dev_set_drvdata(&op->dev, all);
- printk("%s: %s at %016lx, type %d, DAC revision %d\n",
+ printk("%s: %s at %016lx, type %d, "
+ "DAC pnum[%x] rev[%d] manuf_rev[%d]\n",
dp->full_name,
((all->par.flags & FFB_FLAG_AFB) ? "AFB" : "FFB"),
- all->par.physbase, all->par.board_type, all->par.dac_rev);
+ all->par.physbase, all->par.board_type,
+ dac_pnum, dac_rev, dac_mrev);
return 0;
}
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 1d1c7c624d7f..d7ece8d17a2c 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -285,8 +285,6 @@ static const struct riva_regs reg_template = {
#define MAX_LEVEL 0x534
#define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX)
-static struct backlight_properties riva_bl_data;
-
static int riva_bl_get_level_brightness(struct riva_par *par,
int level)
{
@@ -372,7 +370,7 @@ static void riva_bl_init(struct riva_par *par)
FB_BACKLIGHT_MAX);
bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
- bd->props.brightness = riva_bl_data.max_brightness;
+ bd->props.brightness = bd->props.max_brightness;
bd->props.power = FB_BLANK_UNBLANK;
backlight_update_status(bd);
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c
index 98919a6975f0..3091b20124b4 100644
--- a/drivers/video/s3fb.c
+++ b/drivers/video/s3fb.c
@@ -1000,11 +1000,12 @@ err_enable_device:
static void __devexit s3_pci_remove(struct pci_dev *dev)
{
struct fb_info *info = pci_get_drvdata(dev);
- struct s3fb_info *par = info->par;
if (info) {
#ifdef CONFIG_MTRR
+ struct s3fb_info *par = info->par;
+
if (par->mtrr_reg >= 0) {
mtrr_del(par->mtrr_reg, 0, 0);
par->mtrr_reg = -1;
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 4afa30522fdb..0166ec2ccf32 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -384,6 +384,19 @@ SavageSetup2DEngine(struct savagefb_par *par)
BCI_SEND(0);
BCI_SEND(BCI_CMD_SETREG | (1 << 16) | BCI_GBD2);
BCI_SEND(GlobalBitmapDescriptor);
+
+ /*
+ * I don't know why, sending this twice fixes the intial black screen,
+ * prevents X from crashing at least in Toshiba laptops with SavageIX.
+ * --Tony
+ */
+ par->bci_ptr = 0;
+ par->SavageWaitFifo(par, 4);
+
+ BCI_SEND(BCI_CMD_SETREG | (1 << 16) | BCI_GBD1);
+ BCI_SEND(0);
+ BCI_SEND(BCI_CMD_SETREG | (1 << 16) | BCI_GBD2);
+ BCI_SEND(GlobalBitmapDescriptor);
}
static void savagefb_set_clip(struct fb_info *info)
@@ -496,7 +509,7 @@ static int common_calc_clock(long freq, int min_m, int min_n1, int max_n1,
#ifdef SAVAGEFB_DEBUG
/* This function is used to debug, it prints out the contents of s3 regs */
-static void SavagePrintRegs(void)
+static void SavagePrintRegs(struct savagefb_par *par)
{
unsigned char i;
int vgaCRIndex = 0x3d4;
@@ -1525,7 +1538,7 @@ static int savagefb_set_par(struct fb_info *info)
savagefb_set_fix(info);
savagefb_set_clip(info);
- SavagePrintRegs();
+ SavagePrintRegs(par);
return 0;
}
@@ -2155,7 +2168,6 @@ static int __devinit savagefb_probe(struct pci_dev* dev,
int video_len;
DBG("savagefb_probe");
- SavagePrintRegs();
info = framebuffer_alloc(sizeof(struct savagefb_par), &dev->dev);
if (!info)
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index 59cd1e750f30..62fa5500361d 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -257,6 +257,7 @@ static void __sst_dac_write(u8 __iomem *vbase, u8 reg, u8 val)
r_dprintk("sst_dac_write(%#x, %#x)\n", reg, val);
reg &= 0x07;
__sst_write(vbase, DAC_DATA,(((u32)reg << 8)) | (u32)val);
+ __sst_wait_idle(vbase);
}
/* indexed access to ti/att dacs */