summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-01-16 09:09:10 (GMT)
committerIngo Molnar <mingo@elte.hu>2009-01-16 09:09:10 (GMT)
commitaf2519fb2298cdf7540082c36f4d8c66bbff103f (patch)
tree1d290d28d42d42f9e693457762c4008988628060 /drivers
parent961d7d0ee5150e0197cc81c2a8884ecb230276e2 (diff)
parent7cb36b6ccdca03bd87e8faca7fd920643dd1aec7 (diff)
downloadlinux-fsl-qoriq-af2519fb2298cdf7540082c36f4d8c66bbff103f.tar.xz
Merge branch 'linus' into core/iommu
Conflicts: arch/ia64/include/asm/dma-mapping.h arch/ia64/include/asm/machvec.h arch/ia64/include/asm/machvec_sn2.h
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/ahci.c3
-rw-r--r--drivers/ata/libata-core.c11
-rw-r--r--drivers/ata/libata-sff.c9
-rw-r--r--drivers/ata/pata_it821x.c17
-rw-r--r--drivers/block/amiflop.c40
-rw-r--r--drivers/block/nbd.c4
-rw-r--r--drivers/block/xsysace.c1
-rw-r--r--drivers/char/amiserial.c36
-rw-r--r--drivers/char/bsr.c2
-rw-r--r--drivers/char/hvc_console.c14
-rw-r--r--drivers/char/hvc_irq.c2
-rw-r--r--drivers/char/pty.c4
-rw-r--r--drivers/char/ser_a2232.c12
-rw-r--r--drivers/char/synclink_gt.c16
-rw-r--r--drivers/char/sysrq.c6
-rw-r--r--drivers/char/tty_ioctl.c2
-rw-r--r--drivers/char/vme_scc.c166
-rw-r--r--drivers/dio/dio-sysfs.c19
-rw-r--r--drivers/dio/dio.c18
-rw-r--r--drivers/gpio/max7301.c6
-rw-r--r--drivers/gpio/max732x.c6
-rw-r--r--drivers/gpio/mcp23s08.c6
-rw-r--r--drivers/gpio/pca953x.c6
-rw-r--r--drivers/gpio/pcf857x.c12
-rw-r--r--drivers/hwmon/Kconfig24
-rw-r--r--drivers/hwmon/Makefile2
-rw-r--r--drivers/hwmon/abituguru3.c24
-rw-r--r--drivers/hwmon/adt7475.c1221
-rw-r--r--drivers/hwmon/applesmc.c5
-rw-r--r--drivers/hwmon/hp_accel.c75
-rw-r--r--drivers/hwmon/k8temp.c55
-rw-r--r--drivers/i2c/chips/Kconfig11
-rw-r--r--drivers/i2c/chips/Makefile1
-rw-r--r--drivers/i2c/chips/mcu_mpc8349emitx.c209
-rw-r--r--drivers/ide/Kconfig5
-rw-r--r--drivers/ide/ide-disk.c2
-rw-r--r--drivers/ide/ide-iops.c2
-rw-r--r--drivers/ide/ide-pm.c12
-rw-r--r--drivers/ide/ide-probe.c2
-rw-r--r--drivers/ide/it821x.c15
-rw-r--r--drivers/ide/sl82c105.c4
-rw-r--r--drivers/ide/tx4938ide.c1
-rw-r--r--drivers/ide/via82cxxx.c2
-rw-r--r--drivers/infiniband/hw/ehca/ehca_main.c2
-rw-r--r--drivers/infiniband/hw/mlx4/main.c13
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.c12
-rw-r--r--drivers/infiniband/hw/nes/nes_utils.c4
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c38
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c3
-rw-r--r--drivers/infiniband/ulp/iser/Kconfig2
-rw-r--r--drivers/input/misc/Kconfig7
-rw-r--r--drivers/input/misc/Makefile1
-rw-r--r--drivers/input/misc/pcf50633-input.c132
-rw-r--r--drivers/isdn/hardware/mISDN/hfcmulti.c3
-rw-r--r--drivers/isdn/hardware/mISDN/hfcpci.c2
-rw-r--r--drivers/isdn/i4l/isdn_net.c9
-rw-r--r--drivers/isdn/mISDN/dsp_cmx.c5
-rw-r--r--drivers/isdn/mISDN/dsp_pipeline.c4
-rw-r--r--drivers/leds/Kconfig7
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-hp-disk.c137
-rw-r--r--drivers/mfd/Kconfig23
-rw-r--r--drivers/mfd/Makefile4
-rw-r--r--drivers/mfd/dm355evm_msp.c10
-rw-r--r--drivers/mfd/pcf50633-adc.c277
-rw-r--r--drivers/mfd/pcf50633-core.c710
-rw-r--r--drivers/mfd/pcf50633-gpio.c118
-rw-r--r--drivers/mfd/sm501.c30
-rw-r--r--drivers/mfd/twl4030-core.c11
-rw-r--r--drivers/misc/sgi-xp/xpc_sn2.c2
-rw-r--r--drivers/net/3c503.c1
-rw-r--r--drivers/net/3c59x.c2
-rw-r--r--drivers/net/8139cp.c2
-rw-r--r--drivers/net/8139too.c2
-rw-r--r--drivers/net/8390.c1
-rw-r--r--drivers/net/8390p.c1
-rw-r--r--drivers/net/Kconfig2
-rw-r--r--drivers/net/acenic.c1
-rw-r--r--drivers/net/arm/etherh.c1
-rw-r--r--drivers/net/arm/ks8695net.c1
-rw-r--r--drivers/net/ax88796.c27
-rw-r--r--drivers/net/b44.c17
-rw-r--r--drivers/net/b44.h2
-rw-r--r--drivers/net/bnx2x.h19
-rw-r--r--drivers/net/bnx2x_main.c178
-rw-r--r--drivers/net/cxgb3/adapter.h7
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c22
-rw-r--r--drivers/net/cxgb3/sge.c2
-rw-r--r--drivers/net/e1000e/ich8lan.c19
-rw-r--r--drivers/net/e2100.c1
-rw-r--r--drivers/net/ehea/ehea_main.c8
-rw-r--r--drivers/net/ehea/ehea_qmr.c18
-rw-r--r--drivers/net/enic/enic_main.c1
-rw-r--r--drivers/net/forcedeth.c22
-rw-r--r--drivers/net/fs_enet/fs_enet-main.c1
-rw-r--r--drivers/net/gianfar.c23
-rw-r--r--drivers/net/hamachi.c1
-rw-r--r--drivers/net/hamradio/6pack.c3
-rw-r--r--drivers/net/hp-plus.c1
-rw-r--r--drivers/net/hydra.c1
-rw-r--r--drivers/net/ibm_newemac/mal.c4
-rw-r--r--drivers/net/ibm_newemac/mal.h2
-rw-r--r--drivers/net/ibmveth.c16
-rw-r--r--drivers/net/irda/au1k_ir.c2
-rw-r--r--drivers/net/irda/donauboe.c8
-rw-r--r--drivers/net/irda/irda-usb.c2
-rw-r--r--drivers/net/iseries_veth.c2
-rw-r--r--drivers/net/korina.c158
-rw-r--r--drivers/net/mac8390.c1
-rw-r--r--drivers/net/mlx4/en_netdev.c1
-rw-r--r--drivers/net/mlx4/main.c4
-rw-r--r--drivers/net/ne-h8300.c1
-rw-r--r--drivers/net/ne2k-pci.c1
-rw-r--r--drivers/net/netxen/netxen_nic.h146
-rw-r--r--drivers/net/netxen/netxen_nic_ctx.c50
-rw-r--r--drivers/net/netxen/netxen_nic_ethtool.c31
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c97
-rw-r--r--drivers/net/netxen/netxen_nic_init.c105
-rw-r--r--drivers/net/netxen/netxen_nic_main.c203
-rw-r--r--drivers/net/ns83820.c1
-rw-r--r--drivers/net/pasemi_mac.c6
-rw-r--r--drivers/net/phy/phy_device.c9
-rw-r--r--drivers/net/ppp_generic.c43
-rw-r--r--drivers/net/qlge/qlge.h61
-rw-r--r--drivers/net/qlge/qlge_dbg.c62
-rw-r--r--drivers/net/qlge/qlge_main.c80
-rw-r--r--drivers/net/r6040.c43
-rw-r--r--drivers/net/sc92031.c1
-rw-r--r--drivers/net/sfc/tenxpress.c5
-rw-r--r--drivers/net/sis900.c9
-rw-r--r--drivers/net/smc-mca.c1
-rw-r--r--drivers/net/smc-ultra.c1
-rw-r--r--drivers/net/smsc911x.c4
-rw-r--r--drivers/net/smsc9420.c1
-rw-r--r--drivers/net/ucc_geth.c128
-rw-r--r--drivers/net/ucc_geth.h114
-rw-r--r--drivers/net/usb/hso.c12
-rw-r--r--drivers/net/via-rhine.c1
-rw-r--r--drivers/net/via-velocity.c1
-rw-r--r--drivers/net/wan/ixp4xx_hss.c6
-rw-r--r--drivers/net/wd.c1
-rw-r--r--drivers/net/wireless/Kconfig2
-rw-r--r--drivers/net/wireless/ath5k/base.c8
-rw-r--r--drivers/net/wireless/ath5k/pcu.c4
-rw-r--r--drivers/net/wireless/ath5k/reg.h2
-rw-r--r--drivers/net/wireless/ath9k/Kconfig1
-rw-r--r--drivers/net/wireless/ath9k/main.c4
-rw-r--r--drivers/net/wireless/ath9k/xmit.c48
-rw-r--r--drivers/net/wireless/b43/main.c2
-rw-r--r--drivers/net/wireless/b43legacy/main.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c1
-rw-r--r--drivers/net/wireless/libertas/main.c7
-rw-r--r--drivers/net/wireless/libertas_tf/main.c2
-rw-r--r--drivers/net/wireless/orinoco/orinoco.c28
-rw-r--r--drivers/net/wireless/orinoco/orinoco_cs.c1
-rw-r--r--drivers/net/wireless/p54/p54common.c34
-rw-r--r--drivers/net/wireless/p54/p54usb.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c23
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c8
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00leds.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h11
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c1
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_dev.c1
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_dev.c5
-rw-r--r--drivers/net/yellowfin.c1
-rw-r--r--drivers/net/zorro8390.c1
-rw-r--r--drivers/of/of_i2c.c19
-rw-r--r--drivers/parisc/superio.c1
-rw-r--r--drivers/pci/intel-iommu.c3
-rw-r--r--drivers/pci/syscall.c12
-rw-r--r--drivers/pcmcia/electra_cf.c2
-rw-r--r--drivers/power/Kconfig6
-rw-r--r--drivers/power/Makefile1
-rw-r--r--drivers/power/pcf50633-charger.c358
-rw-r--r--drivers/regulator/Kconfig7
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/pcf50633-regulator.c329
-rw-r--r--drivers/rtc/Kconfig7
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-pcf50633.c344
-rw-r--r--drivers/rtc/rtc-pxa.c2
-rw-r--r--drivers/rtc/rtc-twl4030.c49
-rw-r--r--drivers/s390/net/qeth_l2_main.c2
-rw-r--r--drivers/s390/net/qeth_l3_main.c24
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c12
-rw-r--r--drivers/serial/8250.c2
-rw-r--r--drivers/serial/8250_pci.c8
-rw-r--r--drivers/serial/8250_pnp.c2
-rw-r--r--drivers/serial/atmel_serial.c2
-rw-r--r--drivers/serial/jsm/jsm_neo.c3
-rw-r--r--drivers/serial/pnx8xxx_uart.c23
-rw-r--r--drivers/spi/atmel_spi.c3
-rw-r--r--drivers/spi/xilinx_spi.c137
-rw-r--r--drivers/usb/core/hub.c2
-rw-r--r--drivers/usb/serial/ftdi_sio.c2
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c73
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.h8
-rw-r--r--drivers/usb/serial/usb-serial.c3
-rw-r--r--drivers/video/Makefile4
-rw-r--r--drivers/video/amifb.c6
-rw-r--r--drivers/video/atafb.c112
-rw-r--r--drivers/video/bf54x-lq043fb.c15
-rw-r--r--drivers/video/bfin-t350mcqb-fb.c15
-rw-r--r--drivers/video/c2p.c232
-rw-r--r--drivers/video/c2p.h11
-rw-r--r--drivers/video/c2p_core.h153
-rw-r--r--drivers/video/c2p_iplan2.c153
-rw-r--r--drivers/video/c2p_planar.c156
-rw-r--r--drivers/video/console/fbcon.c38
-rw-r--r--drivers/watchdog/Kconfig14
-rw-r--r--drivers/watchdog/Makefile2
-rw-r--r--drivers/watchdog/gef_wdt.c330
-rw-r--r--drivers/watchdog/pika_wdt.c301
-rw-r--r--drivers/watchdog/wm8350_wdt.c6
-rw-r--r--drivers/zorro/.gitignore2
-rw-r--r--drivers/zorro/zorro-sysfs.c20
-rw-r--r--drivers/zorro/zorro.c23
-rw-r--r--drivers/zorro/zorro.h2
222 files changed, 6703 insertions, 2021 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 7f701cb..9603967 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -2660,6 +2660,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
host->iomap = pcim_iomap_table(pdev);
host->private_data = hpriv;
+ if (!(hpriv->cap & HOST_CAP_SSS))
+ host->flags |= ATA_HOST_PARALLEL_SCAN;
+
if (pi.flags & ATA_FLAG_EM)
ahci_reset_em(host);
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index c507a9a..71218d7 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5920,6 +5920,17 @@ static void async_port_probe(void *data, async_cookie_t cookie)
{
int rc;
struct ata_port *ap = data;
+
+ /*
+ * If we're not allowed to scan this host in parallel,
+ * we need to wait until all previous scans have completed
+ * before going further.
+ * Jeff Garzik says this is only within a controller, so we
+ * don't need to wait for port 0, only for later ports.
+ */
+ if (!(ap->host->flags & ATA_HOST_PARALLEL_SCAN) && ap->port_no != 0)
+ async_synchronize_cookie(cookie);
+
/* probe */
if (ap->ops->error_handler) {
struct ata_eh_info *ehi = &ap->link.eh_info;
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 0eae9b4..5a4aad1 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -1013,9 +1013,12 @@ next_sg:
qc->cursg_ofs = 0;
}
- /* consumed can be larger than count only for the last transfer */
- WARN_ON_ONCE(qc->cursg && count != consumed);
-
+ /*
+ * There used to be a WARN_ON_ONCE(qc->cursg && count != consumed);
+ * Unfortunately __atapi_pio_bytes doesn't know enough to do the WARN
+ * check correctly as it doesn't know if it is the last request being
+ * made. Somebody should implement a proper sanity check.
+ */
if (bytes)
goto next_sg;
return 0;
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index f828a29..f1bb2f9 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -80,7 +80,7 @@
#define DRV_NAME "pata_it821x"
-#define DRV_VERSION "0.4.0"
+#define DRV_VERSION "0.4.2"
struct it821x_dev
{
@@ -494,8 +494,6 @@ static int it821x_smart_set_mode(struct ata_link *link, struct ata_device **unus
* special. In our case we need to lock the sector count to avoid
* blowing the brains out of the firmware with large LBA48 requests
*
- * FIXME: When FUA appears we need to block FUA too. And SMART and
- * basically we need to filter commands for this chip.
*/
static void it821x_dev_config(struct ata_device *adev)
@@ -890,6 +888,13 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &it821x_rdc_port_ops
+ };
+ static const struct ata_port_info info_rdc_11 = {
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
/* No UDMA */
.port_ops = &it821x_rdc_port_ops
};
@@ -903,7 +908,11 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
return rc;
if (pdev->vendor == PCI_VENDOR_ID_RDC) {
- ppi[0] = &info_rdc;
+ /* Deal with Vortex86SX */
+ if (pdev->revision == 0x11)
+ ppi[0] = &info_rdc_11;
+ else
+ ppi[0] = &info_rdc;
} else {
/* Force the card into bypass mode if so requested */
if (it8212_noraid) {
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 4b1d4ac..8df436f 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -156,7 +156,7 @@ static volatile int fdc_busy = -1;
static volatile int fdc_nested;
static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
-static DECLARE_WAIT_QUEUE_HEAD(motor_wait);
+static DECLARE_COMPLETION(motor_on_completion);
static volatile int selected = -1; /* currently selected drive */
@@ -184,8 +184,7 @@ static unsigned char mfmencode[16]={
static unsigned char mfmdecode[128];
/* floppy internal millisecond timer stuff */
-static volatile int ms_busy = -1;
-static DECLARE_WAIT_QUEUE_HEAD(ms_wait);
+static DECLARE_COMPLETION(ms_wait_completion);
#define MS_TICKS ((amiga_eclock+50)/1000)
/*
@@ -211,8 +210,7 @@ static int fd_device[4] = { 0, 0, 0, 0 };
static irqreturn_t ms_isr(int irq, void *dummy)
{
- ms_busy = -1;
- wake_up(&ms_wait);
+ complete(&ms_wait_completion);
return IRQ_HANDLED;
}
@@ -220,19 +218,17 @@ static irqreturn_t ms_isr(int irq, void *dummy)
A more generic routine would do a schedule a la timer.device */
static void ms_delay(int ms)
{
- unsigned long flags;
int ticks;
+ static DEFINE_MUTEX(mutex);
+
if (ms > 0) {
- local_irq_save(flags);
- while (ms_busy == 0)
- sleep_on(&ms_wait);
- ms_busy = 0;
- local_irq_restore(flags);
+ mutex_lock(&mutex);
ticks = MS_TICKS*ms-1;
ciaa.tblo=ticks%256;
ciaa.tbhi=ticks/256;
ciaa.crb=0x19; /*count eclock, force load, one-shoot, start */
- sleep_on(&ms_wait);
+ wait_for_completion(&ms_wait_completion);
+ mutex_unlock(&mutex);
}
}
@@ -254,8 +250,7 @@ static void get_fdc(int drive)
printk("get_fdc: drive %d fdc_busy %d fdc_nested %d\n",drive,fdc_busy,fdc_nested);
#endif
local_irq_save(flags);
- while (!try_fdc(drive))
- sleep_on(&fdc_wait);
+ wait_event(fdc_wait, try_fdc(drive));
fdc_busy = drive;
fdc_nested++;
local_irq_restore(flags);
@@ -330,7 +325,7 @@ static void fd_deselect (int drive)
static void motor_on_callback(unsigned long nr)
{
if (!(ciaa.pra & DSKRDY) || --on_attempts == 0) {
- wake_up (&motor_wait);
+ complete_all(&motor_on_completion);
} else {
motor_on_timer.expires = jiffies + HZ/10;
add_timer(&motor_on_timer);
@@ -347,11 +342,12 @@ static int fd_motor_on(int nr)
unit[nr].motor = 1;
fd_select(nr);
+ INIT_COMPLETION(motor_on_completion);
motor_on_timer.data = nr;
mod_timer(&motor_on_timer, jiffies + HZ/2);
on_attempts = 10;
- sleep_on (&motor_wait);
+ wait_for_completion(&motor_on_completion);
fd_deselect(nr);
}
@@ -582,8 +578,7 @@ static void raw_read(int drive)
{
drive&=3;
get_fdc(drive);
- while (block_flag)
- sleep_on(&wait_fd_block);
+ wait_event(wait_fd_block, !block_flag);
fd_select(drive);
/* setup adkcon bits correctly */
custom.adkcon = ADK_MSBSYNC;
@@ -598,8 +593,7 @@ static void raw_read(int drive)
block_flag = 1;
- while (block_flag)
- sleep_on (&wait_fd_block);
+ wait_event(wait_fd_block, !block_flag);
custom.dsklen = 0;
fd_deselect(drive);
@@ -616,8 +610,7 @@ static int raw_write(int drive)
rel_fdc();
return 0;
}
- while (block_flag)
- sleep_on(&wait_fd_block);
+ wait_event(wait_fd_block, !block_flag);
fd_select(drive);
/* clear adkcon bits */
custom.adkcon = ADK_PRECOMP1|ADK_PRECOMP0|ADK_WORDSYNC|ADK_MSBSYNC;
@@ -1294,8 +1287,7 @@ static int non_int_flush_track (unsigned long nr)
writepending = 0;
return 0;
}
- while (block_flag == 2)
- sleep_on (&wait_fd_block);
+ wait_event(wait_fd_block, block_flag != 2);
}
else {
local_irq_restore(flags);
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 7bcc1d8..34f80fa 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -406,6 +406,7 @@ static int nbd_do_it(struct nbd_device *lo)
ret = sysfs_create_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr);
if (ret) {
printk(KERN_ERR "nbd: sysfs_create_file failed!");
+ lo->pid = 0;
return ret;
}
@@ -413,6 +414,7 @@ static int nbd_do_it(struct nbd_device *lo)
nbd_end_request(req);
sysfs_remove_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr);
+ lo->pid = 0;
return 0;
}
@@ -648,6 +650,8 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
set_capacity(lo->disk, lo->bytesize >> 9);
return 0;
case NBD_DO_IT:
+ if (lo->pid)
+ return -EBUSY;
if (!lo->file)
return -EINVAL;
thread = kthread_create(nbd_thread, lo, lo->disk->disk_name);
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
index 29e1dfa..381d686 100644
--- a/drivers/block/xsysace.c
+++ b/drivers/block/xsysace.c
@@ -1206,6 +1206,7 @@ static struct of_device_id ace_of_match[] __devinitdata = {
{ .compatible = "xlnx,opb-sysace-1.00.b", },
{ .compatible = "xlnx,opb-sysace-1.00.c", },
{ .compatible = "xlnx,xps-sysace-1.00.a", },
+ { .compatible = "xlnx,sysace", },
{},
};
MODULE_DEVICE_TABLE(of, ace_of_match);
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 4e0cfde..a58869e 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -1963,6 +1963,7 @@ static int __init rs_init(void)
{
unsigned long flags;
struct serial_state * state;
+ int error;
if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_SERIAL))
return -ENODEV;
@@ -1975,8 +1976,11 @@ static int __init rs_init(void)
* We request SERDAT and SERPER only, because the serial registers are
* too spreaded over the custom register space
*/
- if (!request_mem_region(CUSTOM_PHYSADDR+0x30, 4, "amiserial [Paula]"))
- return -EBUSY;
+ if (!request_mem_region(CUSTOM_PHYSADDR+0x30, 4,
+ "amiserial [Paula]")) {
+ error = -EBUSY;
+ goto fail_put_tty_driver;
+ }
IRQ_ports = NULL;
@@ -1997,8 +2001,9 @@ static int __init rs_init(void)
serial_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(serial_driver, &serial_ops);
- if (tty_register_driver(serial_driver))
- panic("Couldn't register serial driver\n");
+ error = tty_register_driver(serial_driver);
+ if (error)
+ goto fail_release_mem_region;
state = rs_table;
state->magic = SSTATE_MAGIC;
@@ -2024,8 +2029,14 @@ static int __init rs_init(void)
local_irq_save(flags);
/* set ISRs, and then disable the rx interrupts */
- request_irq(IRQ_AMIGA_TBE, ser_tx_int, 0, "serial TX", state);
- request_irq(IRQ_AMIGA_RBF, ser_rx_int, IRQF_DISABLED, "serial RX", state);
+ error = request_irq(IRQ_AMIGA_TBE, ser_tx_int, 0, "serial TX", state);
+ if (error)
+ goto fail_unregister;
+
+ error = request_irq(IRQ_AMIGA_RBF, ser_rx_int, IRQF_DISABLED,
+ "serial RX", state);
+ if (error)
+ goto fail_free_irq;
/* turn off Rx and Tx interrupts */
custom.intena = IF_RBF | IF_TBE;
@@ -2045,6 +2056,16 @@ static int __init rs_init(void)
ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR); /* inputs */
return 0;
+
+fail_free_irq:
+ free_irq(IRQ_AMIGA_TBE, state);
+fail_unregister:
+ tty_unregister_driver(serial_driver);
+fail_release_mem_region:
+ release_mem_region(CUSTOM_PHYSADDR+0x30, 4);
+fail_put_tty_driver:
+ put_tty_driver(serial_driver);
+ return error;
}
static __exit void rs_exit(void)
@@ -2064,6 +2085,9 @@ static __exit void rs_exit(void)
kfree(info);
}
+ free_irq(IRQ_AMIGA_TBE, rs_table);
+ free_irq(IRQ_AMIGA_RBF, rs_table);
+
release_mem_region(CUSTOM_PHYSADDR+0x30, 4);
}
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c
index 977dfb1..f6094ae 100644
--- a/drivers/char/bsr.c
+++ b/drivers/char/bsr.c
@@ -103,7 +103,7 @@ static ssize_t
bsr_len_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
- return sprintf(buf, "%lu\n", bsr_dev->bsr_len);
+ return sprintf(buf, "%llu\n", bsr_dev->bsr_len);
}
static struct device_attribute bsr_dev_attrs[] = {
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index 5a8a4c2..09676b4e 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -318,7 +318,8 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
} /* else count == 0 */
tty->driver_data = hp;
- tty->low_latency = 1; /* Makes flushes to ldisc synchronous. */
+ if (!hp->irq_requested)
+ tty->low_latency = 1; /* Makes flushes to ldisc synchronous. */
hp->tty = tty;
@@ -764,13 +765,11 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int data,
return ERR_PTR(err);
}
- hp = kmalloc(ALIGN(sizeof(*hp), sizeof(long)) + outbuf_size,
+ hp = kzalloc(ALIGN(sizeof(*hp), sizeof(long)) + outbuf_size,
GFP_KERNEL);
if (!hp)
return ERR_PTR(-ENOMEM);
- memset(hp, 0x00, sizeof(*hp));
-
hp->vtermno = vtermno;
hp->data = data;
hp->ops = ops;
@@ -876,8 +875,11 @@ static int hvc_init(void)
goto stop_thread;
}
- /* FIXME: This mb() seems completely random. Remove it. */
- mb();
+ /*
+ * Make sure tty is fully registered before allowing it to be
+ * found by hvc_console_device.
+ */
+ smp_mb();
hvc_driver = drv;
return 0;
diff --git a/drivers/char/hvc_irq.c b/drivers/char/hvc_irq.c
index d09e568..2623e17 100644
--- a/drivers/char/hvc_irq.c
+++ b/drivers/char/hvc_irq.c
@@ -37,7 +37,7 @@ int notifier_add_irq(struct hvc_struct *hp, int irq)
void notifier_del_irq(struct hvc_struct *hp, int irq)
{
- if (!irq)
+ if (!hp->irq_requested)
return;
free_irq(irq, hp);
hp->irq_requested = 0;
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 146c976..31038a0 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -230,9 +230,7 @@ static void pty_set_termios(struct tty_struct *tty,
/**
* pty_do_resize - resize event
* @tty: tty being resized
- * @real_tty: real tty (not the same as tty if using a pty/tty pair)
- * @rows: rows (character)
- * @cols: cols (character)
+ * @ws: window size being set.
*
* Update the termios variables and send the neccessary signals to
* peform a terminal resize correctly
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c
index 33872a2..33a2b53 100644
--- a/drivers/char/ser_a2232.c
+++ b/drivers/char/ser_a2232.c
@@ -718,6 +718,7 @@ static int __init a2232board_init(void)
u_char *from;
volatile u_char *to;
volatile struct a2232memory *mem;
+ int error, i;
#ifdef CONFIG_SMP
return -ENODEV; /* This driver is not SMP aware. Is there an SMP ZorroII-bus-machine? */
@@ -797,8 +798,15 @@ static int __init a2232board_init(void)
*/
if (a2232_init_drivers()) return -ENODEV; // maybe we should use a different -Exxx?
- request_irq(IRQ_AMIGA_VERTB, a2232_vbl_inter, 0, "A2232 serial VBL", a2232_driver_ID);
- return 0;
+ error = request_irq(IRQ_AMIGA_VERTB, a2232_vbl_inter, 0,
+ "A2232 serial VBL", a2232_driver_ID);
+ if (error) {
+ for (i = 0; i < nr_a2232; i++)
+ zorro_release_device(zd_a2232[i]);
+ tty_unregister_driver(a2232_driver);
+ put_tty_driver(a2232_driver);
+ }
+ return error;
}
static void __exit a2232board_exit(void)
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 53544e2..f329f45 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -1,6 +1,4 @@
/*
- * $Id: synclink_gt.c,v 4.50 2007/07/25 19:29:25 paulkf Exp $
- *
* Device driver for Microgate SyncLink GT serial adapters.
*
* written by Paul Fulghum for Microgate Corporation
@@ -91,7 +89,6 @@
* module identification
*/
static char *driver_name = "SyncLink GT";
-static char *driver_version = "$Revision: 4.50 $";
static char *tty_driver_name = "synclink_gt";
static char *tty_dev_prefix = "ttySLG";
MODULE_LICENSE("GPL");
@@ -1309,7 +1306,7 @@ static int read_proc(char *page, char **start, off_t off, int count,
off_t begin = 0;
struct slgt_info *info;
- len += sprintf(page, "synclink_gt driver:%s\n", driver_version);
+ len += sprintf(page, "synclink_gt driver\n");
info = slgt_device_list;
while( info ) {
@@ -2441,7 +2438,7 @@ static void program_hw(struct slgt_info *info)
info->ri_chkcount = 0;
info->dsr_chkcount = 0;
- slgt_irq_on(info, IRQ_DCD | IRQ_CTS | IRQ_DSR);
+ slgt_irq_on(info, IRQ_DCD | IRQ_CTS | IRQ_DSR | IRQ_RI);
get_signals(info);
if (info->netcount ||
@@ -3576,7 +3573,7 @@ static void slgt_cleanup(void)
struct slgt_info *info;
struct slgt_info *tmp;
- printk("unload %s %s\n", driver_name, driver_version);
+ printk(KERN_INFO "unload %s\n", driver_name);
if (serial_driver) {
for (info=slgt_device_list ; info != NULL ; info=info->next_device)
@@ -3619,7 +3616,7 @@ static int __init slgt_init(void)
{
int rc;
- printk("%s %s\n", driver_name, driver_version);
+ printk(KERN_INFO "%s\n", driver_name);
serial_driver = alloc_tty_driver(MAX_DEVICES);
if (!serial_driver) {
@@ -3650,9 +3647,8 @@ static int __init slgt_init(void)
goto error;
}
- printk("%s %s, tty major#%d\n",
- driver_name, driver_version,
- serial_driver->major);
+ printk(KERN_INFO "%s, tty major#%d\n",
+ driver_name, serial_driver->major);
slgt_device_count = 0;
if ((rc = pci_register_driver(&pci_driver)) < 0) {
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index d41b9f6..33a9351 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -473,6 +473,12 @@ void __handle_sysrq(int key, struct tty_struct *tty, int check_mask)
unsigned long flags;
spin_lock_irqsave(&sysrq_key_table_lock, flags);
+ /*
+ * Raise the apparent loglevel to maximum so that the sysrq header
+ * is shown to provide the user with positive feedback. We do not
+ * simply emit this at KERN_EMERG as that would change message
+ * routing in the consumers of /proc/kmsg.
+ */
orig_log_level = console_loglevel;
console_loglevel = 7;
printk(KERN_INFO "SysRq : ");
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index a408c8e..6f4c7d0 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -1057,7 +1057,7 @@ int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
if (retval)
return retval;
- ld = tty_ldisc_ref(tty);
+ ld = tty_ldisc_ref_wait(tty);
switch (arg) {
case TCIFLUSH:
if (ld && ld->ops->flush_buffer)
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
index 0e8234b..994e1a5 100644
--- a/drivers/char/vme_scc.c
+++ b/drivers/char/vme_scc.c
@@ -198,6 +198,7 @@ static void scc_init_portstructs(void)
static int mvme147_scc_init(void)
{
struct scc_port *port;
+ int error;
printk(KERN_INFO "SCC: MVME147 Serial Driver\n");
/* Init channel A */
@@ -207,14 +208,23 @@ static int mvme147_scc_init(void)
port->datap = port->ctrlp + 1;
port->port_a = &scc_ports[0];
port->port_b = &scc_ports[1];
- request_irq(MVME147_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
+ error = request_irq(MVME147_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
"SCC-A TX", port);
- request_irq(MVME147_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
+ if (error)
+ goto fail;
+ error = request_irq(MVME147_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
"SCC-A status", port);
- request_irq(MVME147_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
+ if (error)
+ goto fail_free_a_tx;
+ error = request_irq(MVME147_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
"SCC-A RX", port);
- request_irq(MVME147_IRQ_SCCA_SPCOND, scc_spcond_int, IRQF_DISABLED,
- "SCC-A special cond", port);
+ if (error)
+ goto fail_free_a_stat;
+ error = request_irq(MVME147_IRQ_SCCA_SPCOND, scc_spcond_int,
+ IRQF_DISABLED, "SCC-A special cond", port);
+ if (error)
+ goto fail_free_a_rx;
+
{
SCC_ACCESS_INIT(port);
@@ -234,14 +244,23 @@ static int mvme147_scc_init(void)
port->datap = port->ctrlp + 1;
port->port_a = &scc_ports[0];
port->port_b = &scc_ports[1];
- request_irq(MVME147_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
+ error = request_irq(MVME147_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
"SCC-B TX", port);
- request_irq(MVME147_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
+ if (error)
+ goto fail_free_a_spcond;
+ error = request_irq(MVME147_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
"SCC-B status", port);
- request_irq(MVME147_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
+ if (error)
+ goto fail_free_b_tx;
+ error = request_irq(MVME147_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
"SCC-B RX", port);
- request_irq(MVME147_IRQ_SCCB_SPCOND, scc_spcond_int, IRQF_DISABLED,
- "SCC-B special cond", port);
+ if (error)
+ goto fail_free_b_stat;
+ error = request_irq(MVME147_IRQ_SCCB_SPCOND, scc_spcond_int,
+ IRQF_DISABLED, "SCC-B special cond", port);
+ if (error)
+ goto fail_free_b_rx;
+
{
SCC_ACCESS_INIT(port);
@@ -257,6 +276,23 @@ static int mvme147_scc_init(void)
scc_init_drivers();
return 0;
+
+fail_free_b_rx:
+ free_irq(MVME147_IRQ_SCCB_RX, port);
+fail_free_b_stat:
+ free_irq(MVME147_IRQ_SCCB_STAT, port);
+fail_free_b_tx:
+ free_irq(MVME147_IRQ_SCCB_TX, port);
+fail_free_a_spcond:
+ free_irq(MVME147_IRQ_SCCA_SPCOND, port);
+fail_free_a_rx:
+ free_irq(MVME147_IRQ_SCCA_RX, port);
+fail_free_a_stat:
+ free_irq(MVME147_IRQ_SCCA_STAT, port);
+fail_free_a_tx:
+ free_irq(MVME147_IRQ_SCCA_TX, port);
+fail:
+ return error;
}
#endif
@@ -265,6 +301,7 @@ static int mvme147_scc_init(void)
static int mvme162_scc_init(void)
{
struct scc_port *port;
+ int error;
if (!(mvme16x_config & MVME16x_CONFIG_GOT_SCCA))
return (-ENODEV);
@@ -277,14 +314,23 @@ static int mvme162_scc_init(void)
port->datap = port->ctrlp + 2;
port->port_a = &scc_ports[0];
port->port_b = &scc_ports[1];
- request_irq(MVME162_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
+ error = request_irq(MVME162_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
"SCC-A TX", port);
- request_irq(MVME162_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
+ if (error)
+ goto fail;
+ error = request_irq(MVME162_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
"SCC-A status", port);
- request_irq(MVME162_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
+ if (error)
+ goto fail_free_a_tx;
+ error = request_irq(MVME162_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
"SCC-A RX", port);
- request_irq(MVME162_IRQ_SCCA_SPCOND, scc_spcond_int, IRQF_DISABLED,
- "SCC-A special cond", port);
+ if (error)
+ goto fail_free_a_stat;
+ error = request_irq(MVME162_IRQ_SCCA_SPCOND, scc_spcond_int,
+ IRQF_DISABLED, "SCC-A special cond", port);
+ if (error)
+ goto fail_free_a_rx;
+
{
SCC_ACCESS_INIT(port);
@@ -304,14 +350,22 @@ static int mvme162_scc_init(void)
port->datap = port->ctrlp + 2;
port->port_a = &scc_ports[0];
port->port_b = &scc_ports[1];
- request_irq(MVME162_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
+ error = request_irq(MVME162_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
"SCC-B TX", port);
- request_irq(MVME162_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
+ if (error)
+ goto fail_free_a_spcond;
+ error = request_irq(MVME162_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
"SCC-B status", port);
- request_irq(MVME162_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
+ if (error)
+ goto fail_free_b_tx;
+ error = request_irq(MVME162_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
"SCC-B RX", port);
- request_irq(MVME162_IRQ_SCCB_SPCOND, scc_spcond_int, IRQF_DISABLED,
- "SCC-B special cond", port);
+ if (error)
+ goto fail_free_b_stat;
+ error = request_irq(MVME162_IRQ_SCCB_SPCOND, scc_spcond_int,
+ IRQF_DISABLED, "SCC-B special cond", port);
+ if (error)
+ goto fail_free_b_rx;
{
SCC_ACCESS_INIT(port); /* Either channel will do */
@@ -328,6 +382,23 @@ static int mvme162_scc_init(void)
scc_init_drivers();
return 0;
+
+fail_free_b_rx:
+ free_irq(MVME162_IRQ_SCCB_RX, port);
+fail_free_b_stat:
+ free_irq(MVME162_IRQ_SCCB_STAT, port);
+fail_free_b_tx:
+ free_irq(MVME162_IRQ_SCCB_TX, port);
+fail_free_a_spcond:
+ free_irq(MVME162_IRQ_SCCA_SPCOND, port);
+fail_free_a_rx:
+ free_irq(MVME162_IRQ_SCCA_RX, port);
+fail_free_a_stat:
+ free_irq(MVME162_IRQ_SCCA_STAT, port);
+fail_free_a_tx:
+ free_irq(MVME162_IRQ_SCCA_TX, port);
+fail:
+ return error;
}
#endif
@@ -336,6 +407,7 @@ static int mvme162_scc_init(void)
static int bvme6000_scc_init(void)
{
struct scc_port *port;
+ int error;
printk(KERN_INFO "SCC: BVME6000 Serial Driver\n");
/* Init channel A */
@@ -345,14 +417,23 @@ static int bvme6000_scc_init(void)
port->datap = port->ctrlp + 4;
port->port_a = &scc_ports[0];
port->port_b = &scc_ports[1];
- request_irq(BVME_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
+ error = request_irq(BVME_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
"SCC-A TX", port);
- request_irq(BVME_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
+ if (error)
+ goto fail;
+ error = request_irq(BVME_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
"SCC-A status", port);
- request_irq(BVME_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
+ if (error)
+ goto fail_free_a_tx;
+ error = request_irq(BVME_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
"SCC-A RX", port);
- request_irq(BVME_IRQ_SCCA_SPCOND, scc_spcond_int, IRQF_DISABLED,
- "SCC-A special cond", port);
+ if (error)
+ goto fail_free_a_stat;
+ error = request_irq(BVME_IRQ_SCCA_SPCOND, scc_spcond_int,
+ IRQF_DISABLED, "SCC-A special cond", port);
+ if (error)
+ goto fail_free_a_rx;
+
{
SCC_ACCESS_INIT(port);
@@ -372,14 +453,22 @@ static int bvme6000_scc_init(void)
port->datap = port->ctrlp + 4;
port->port_a = &scc_ports[0];
port->port_b = &scc_ports[1];
- request_irq(BVME_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
+ error = request_irq(BVME_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
"SCC-B TX", port);
- request_irq(BVME_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
+ if (error)
+ goto fail_free_a_spcond;
+ error = request_irq(BVME_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
"SCC-B status", port);
- request_irq(BVME_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
+ if (error)
+ goto fail_free_b_tx;
+ error = request_irq(BVME_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
"SCC-B RX", port);
- request_irq(BVME_IRQ_SCCB_SPCOND, scc_spcond_int, IRQF_DISABLED,
- "SCC-B special cond", port);
+ if (error)
+ goto fail_free_b_stat;
+ error = request_irq(BVME_IRQ_SCCB_SPCOND, scc_spcond_int,
+ IRQF_DISABLED, "SCC-B special cond", port);
+ if (error)
+ goto fail_free_b_rx;
{
SCC_ACCESS_INIT(port); /* Either channel will do */
@@ -393,6 +482,23 @@ static int bvme6000_scc_init(void)
scc_init_drivers();
return 0;
+
+fail:
+ free_irq(BVME_IRQ_SCCA_STAT, port);
+fail_free_a_tx:
+ free_irq(BVME_IRQ_SCCA_RX, port);
+fail_free_a_stat:
+ free_irq(BVME_IRQ_SCCA_SPCOND, port);
+fail_free_a_rx:
+ free_irq(BVME_IRQ_SCCB_TX, port);
+fail_free_a_spcond:
+ free_irq(BVME_IRQ_SCCB_STAT, port);
+fail_free_b_tx:
+ free_irq(BVME_IRQ_SCCB_RX, port);
+fail_free_b_stat:
+ free_irq(BVME_IRQ_SCCB_SPCOND, port);
+fail_free_b_rx:
+ return error;
}
#endif
diff --git a/drivers/dio/dio-sysfs.c b/drivers/dio/dio-sysfs.c
index f464630..ee1a3b5 100644
--- a/drivers/dio/dio-sysfs.c
+++ b/drivers/dio/dio-sysfs.c
@@ -58,20 +58,25 @@ static ssize_t dio_show_resource(struct device *dev, struct device_attribute *at
struct dio_dev *d = to_dio_dev(dev);
return sprintf(buf, "0x%08lx 0x%08lx 0x%08lx\n",
- dio_resource_start(d), dio_resource_end(d),
+ (unsigned long)dio_resource_start(d),
+ (unsigned long)dio_resource_end(d),
dio_resource_flags(d));
}
static DEVICE_ATTR(resource, S_IRUGO, dio_show_resource, NULL);
-void dio_create_sysfs_dev_files(struct dio_dev *d)
+int dio_create_sysfs_dev_files(struct dio_dev *d)
{
struct device *dev = &d->dev;
+ int error;
/* current configuration's attributes */
- device_create_file(dev, &dev_attr_id);
- device_create_file(dev, &dev_attr_ipl);
- device_create_file(dev, &dev_attr_secid);
- device_create_file(dev, &dev_attr_name);
- device_create_file(dev, &dev_attr_resource);
+ if ((error = device_create_file(dev, &dev_attr_id)) ||
+ (error = device_create_file(dev, &dev_attr_ipl)) ||
+ (error = device_create_file(dev, &dev_attr_secid)) ||
+ (error = device_create_file(dev, &dev_attr_name)) ||
+ (error = device_create_file(dev, &dev_attr_resource)))
+ return error;
+
+ return 0;
}
diff --git a/drivers/dio/dio.c b/drivers/dio/dio.c
index 07f274f..10c3c49 100644
--- a/drivers/dio/dio.c
+++ b/drivers/dio/dio.c
@@ -173,6 +173,7 @@ static int __init dio_init(void)
mm_segment_t fs;
int i;
struct dio_dev *dev;
+ int error;
if (!MACH_IS_HP300)
return 0;
@@ -182,7 +183,11 @@ static int __init dio_init(void)
/* Initialize the DIO bus */
INIT_LIST_HEAD(&dio_bus.devices);
strcpy(dio_bus.dev.bus_id, "dio");
- device_register(&dio_bus.dev);
+ error = device_register(&dio_bus.dev);
+ if (error) {
+ pr_err("DIO: Error registering dio_bus\n");
+ return error;
+ }
/* Request all resources */
dio_bus.num_resources = (hp300_model == HP_320 ? 1 : 2);
@@ -252,8 +257,15 @@ static int __init dio_init(void)
if (scode >= DIOII_SCBASE)
iounmap(va);
- device_register(&dev->dev);
- dio_create_sysfs_dev_files(dev);
+ error = device_register(&dev->dev);
+ if (error) {
+ pr_err("DIO: Error registering device %s\n",
+ dev->name);
+ continue;
+ }
+ error = dio_create_sysfs_dev_files(dev);
+ if (error)
+ dev_err(&dev->dev, "Error creating sysfs files\n");
}
return 0;
}
diff --git a/drivers/gpio/max7301.c b/drivers/gpio/max7301.c
index 8b24d78..3e7f4e0 100644
--- a/drivers/gpio/max7301.c
+++ b/drivers/gpio/max7301.c
@@ -217,8 +217,10 @@ static int __devinit max7301_probe(struct spi_device *spi)
int i, ret;
pdata = spi->dev.platform_data;
- if (!pdata || !pdata->base)
- return -ENODEV;
+ if (!pdata || !pdata->base) {
+ dev_dbg(&spi->dev, "incorrect or missing platform data\n");
+ return -EINVAL;
+ }
/*
* bits_per_word cannot be configured in platform data
diff --git a/drivers/gpio/max732x.c b/drivers/gpio/max732x.c
index 55ae9a4..f786824 100644
--- a/drivers/gpio/max732x.c
+++ b/drivers/gpio/max732x.c
@@ -267,8 +267,10 @@ static int __devinit max732x_probe(struct i2c_client *client,
int ret, nr_port;
pdata = client->dev.platform_data;
- if (pdata == NULL)
- return -ENODEV;
+ if (pdata == NULL) {
+ dev_dbg(&client->dev, "no platform data\n");
+ return -EINVAL;
+ }
chip = kzalloc(sizeof(struct max732x_chip), GFP_KERNEL);
if (chip == NULL)
diff --git a/drivers/gpio/mcp23s08.c b/drivers/gpio/mcp23s08.c
index 89c1d22..f6fae0e 100644
--- a/drivers/gpio/mcp23s08.c
+++ b/drivers/gpio/mcp23s08.c
@@ -310,8 +310,10 @@ static int mcp23s08_probe(struct spi_device *spi)
unsigned base;
pdata = spi->dev.platform_data;
- if (!pdata || !gpio_is_valid(pdata->base))
- return -ENODEV;
+ if (!pdata || !gpio_is_valid(pdata->base)) {
+ dev_dbg(&spi->dev, "invalid or missing platform data\n");
+ return -EINVAL;
+ }
for (addr = 0; addr < 4; addr++) {
if (!pdata->chip[addr].is_present)
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
index 37f3538..8dc0164 100644
--- a/drivers/gpio/pca953x.c
+++ b/drivers/gpio/pca953x.c
@@ -202,8 +202,10 @@ static int __devinit pca953x_probe(struct i2c_client *client,
int ret;
pdata = client->dev.platform_data;
- if (pdata == NULL)
- return -ENODEV;
+ if (pdata == NULL) {
+ dev_dbg(&client->dev, "no platform data\n");
+ return -EINVAL;
+ }
chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
if (chip == NULL)
diff --git a/drivers/gpio/pcf857x.c b/drivers/gpio/pcf857x.c
index 4bc2070..9525724 100644
--- a/drivers/gpio/pcf857x.c
+++ b/drivers/gpio/pcf857x.c
@@ -188,8 +188,10 @@ static int pcf857x_probe(struct i2c_client *client,
int status;
pdata = client->dev.platform_data;
- if (!pdata)
- return -ENODEV;
+ if (!pdata) {
+ dev_dbg(&client->dev, "no platform data\n");
+ return -EINVAL;
+ }
/* Allocate, initialize, and register this gpio_chip. */
gpio = kzalloc(sizeof *gpio, GFP_KERNEL);
@@ -248,8 +250,10 @@ static int pcf857x_probe(struct i2c_client *client,
else
status = i2c_read_le16(client);
- } else
- status = -ENODEV;
+ } else {
+ dev_dbg(&client->dev, "unsupported number of gpios\n");
+ status = -EINVAL;
+ }
if (status < 0)
goto fail;
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 4b33bc8..b84bf06 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -189,6 +189,16 @@ config SENSORS_ADT7473
This driver can also be built as a module. If so, the module
will be called adt7473.
+config SENSORS_ADT7475
+ tristate "Analog Devices ADT7475"
+ depends on I2C && EXPERIMENTAL
+ help
+ If you say yes here you get support for the Analog Devices
+ ADT7475 hardware monitoring chips.
+
+ This driver can also be build as a module. If so, the module
+ will be called adt7475.
+
config SENSORS_K8TEMP
tristate "AMD Athlon64/FX or Opteron temperature sensor"
depends on X86 && PCI && EXPERIMENTAL
@@ -861,6 +871,8 @@ config SENSORS_HDAPS
config SENSORS_LIS3LV02D
tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer"
depends on ACPI && INPUT
+ select NEW_LEDS
+ select LEDS_CLASS
default n
help
This driver provides support for the LIS3LV02Dx accelerometer. In
@@ -872,10 +884,16 @@ config SENSORS_LIS3LV02D
/sys/devices/platform/lis3lv02d.
This driver also provides an absolute input class device, allowing
- the laptop to act as a pinball machine-esque joystick.
+ the laptop to act as a pinball machine-esque joystick. On HP laptops,
+ if the led infrastructure is activated, support for a led indicating
+ disk protection will be provided as hp:red:hddprotection.
- This driver can also be built as a module. If so, the module
- will be called lis3lv02d.
+ This driver can also be built as modules. If so, the core module
+ will be called lis3lv02d and a specific module for HP laptops will be
+ called hp_accel.
+
+ Say Y here if you have an applicable laptop and want to experience
+ the awesome power of lis3lv02d.
config SENSORS_APPLESMC
tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)"
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 19cb1ac..2e80f37 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -28,6 +28,8 @@ obj-$(CONFIG_SENSORS_ADS7828) += ads7828.o
obj-$(CONFIG_SENSORS_ADT7462) += adt7462.o
obj-$(CONFIG_SENSORS_ADT7470) += adt7470.o
obj-$(CONFIG_SENSORS_ADT7473) += adt7473.o
+obj-$(CONFIG_SENSORS_ADT7475) += adt7475.o
+
obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o
obj-$(CONFIG_SENSORS_AMS) += ams/
obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
index 70bb854..e52b388 100644
--- a/drivers/hwmon/abituguru3.c
+++ b/drivers/hwmon/abituguru3.c
@@ -279,7 +279,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "OTES1 Fan", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x0011, "AT8 32X(ATI RD580-ULI M1575)", {
+ { 0x0011, "AT8 32X", {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR", 1, 0, 20, 1, 0 },
{ "DDR VTT", 2, 0, 10, 1, 0 },
@@ -402,7 +402,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX3 Fan", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x0016, "AW9D-MAX (Intel i975-ICH7)", {
+ { 0x0016, "AW9D-MAX", {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR2", 1, 0, 20, 1, 0 },
{ "DDR2 VTT", 2, 0, 10, 1, 0 },
@@ -482,7 +482,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX3 Fan", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x0019, NULL /* Unknown, need DMI string */, {
+ { 0x0019, "IN9 32X MAX", {
{ "CPU Core", 7, 0, 10, 1, 0 },
{ "DDR2", 13, 0, 20, 1, 0 },
{ "DDR2 VTT", 14, 0, 10, 1, 0 },
@@ -509,7 +509,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX3 FAN", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x001A, "IP35 Pro(Intel P35-ICH9R)", {
+ { 0x001A, "IP35 Pro", {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR2", 1, 0, 20, 1, 0 },
{ "DDR2 VTT", 2, 0, 10, 1, 0 },
@@ -1128,6 +1128,7 @@ static int __init abituguru3_dmi_detect(void)
{
const char *board_vendor, *board_name;
int i, err = (force) ? 1 : -ENODEV;
+ size_t sublen;
board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
if (!board_vendor || strcmp(board_vendor, "http://www.abit.com.tw/"))
@@ -1137,9 +1138,20 @@ static int __init abituguru3_dmi_detect(void)
if (!board_name)
return err;
+ /* At the moment, we don't care about the part of the vendor
+ * DMI string contained in brackets. Truncate the string at
+ * the first occurrence of a bracket. Trim any trailing space
+ * from the substring.
+ */
+ sublen = strcspn(board_name, "(");
+ while (sublen > 0 && board_name[sublen - 1] == ' ')
+ sublen--;
+
for (i = 0; abituguru3_motherboards[i].id; i++) {
const char *dmi_name = abituguru3_motherboards[i].dmi_name;
- if (dmi_name && !strcmp(dmi_name, board_name))
+ if (!dmi_name || strlen(dmi_name) != sublen)
+ continue;
+ if (!strncasecmp(board_name, dmi_name, sublen))
break;
}
@@ -1153,7 +1165,7 @@ static int __init abituguru3_dmi_detect(void)
static inline int abituguru3_dmi_detect(void)
{
- return -ENODEV;
+ return 1;
}
#endif /* CONFIG_DMI */
diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c
new file mode 100644
index 0000000..d39877a
--- /dev/null
+++ b/drivers/hwmon/adt7475.c
@@ -0,0 +1,1221 @@
+/*
+ * adt7475 - Thermal sensor driver for the ADT7475 chip and derivatives
+ * Copyright (C) 2007-2008, Advanced Micro Devices, Inc.
+ * Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net>
+ * Copyright (C) 2008 Hans de Goede <hdegoede@redhat.com>
+
+ * Derived from the lm83 driver by Jean Delvare
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+
+/* Indexes for the sysfs hooks */
+
+#define INPUT 0
+#define MIN 1
+#define MAX 2
+#define CONTROL 3
+#define OFFSET 3
+#define AUTOMIN 4
+#define THERM 5
+#define HYSTERSIS 6
+
+/* These are unique identifiers for the sysfs functions - unlike the
+ numbers above, these are not also indexes into an array
+*/
+
+#define ALARM 9
+#define FAULT 10
+
+/* 7475 Common Registers */
+
+#define REG_VOLTAGE_BASE 0x21
+#define REG_TEMP_BASE 0x25
+#define REG_TACH_BASE 0x28
+#define REG_PWM_BASE 0x30
+#define REG_PWM_MAX_BASE 0x38
+
+#define REG_DEVID 0x3D
+#define REG_VENDID 0x3E
+
+#define REG_STATUS1 0x41
+#define REG_STATUS2 0x42
+
+#define REG_VOLTAGE_MIN_BASE 0x46
+#define REG_VOLTAGE_MAX_BASE 0x47
+
+#define REG_TEMP_MIN_BASE 0x4E
+#define REG_TEMP_MAX_BASE 0x4F
+
+#define REG_TACH_MIN_BASE 0x54
+
+#define REG_PWM_CONFIG_BASE 0x5C
+
+#define REG_TEMP_TRANGE_BASE 0x5F
+
+#define REG_PWM_MIN_BASE 0x64
+
+#define REG_TEMP_TMIN_BASE 0x67
+#define REG_TEMP_THERM_BASE 0x6A
+
+#define REG_REMOTE1_HYSTERSIS 0x6D
+#define REG_REMOTE2_HYSTERSIS 0x6E
+
+#define REG_TEMP_OFFSET_BASE 0x70
+
+#define REG_EXTEND1 0x76
+#define REG_EXTEND2 0x77
+#define REG_CONFIG5 0x7C
+
+#define CONFIG5_TWOSCOMP 0x01
+#define CONFIG5_TEMPOFFSET 0x02
+
+/* ADT7475 Settings */
+
+#define ADT7475_VOLTAGE_COUNT 2
+#define ADT7475_TEMP_COUNT 3
+#define ADT7475_TACH_COUNT 4
+#define ADT7475_PWM_COUNT 3
+
+/* Macro to read the registers */
+
+#define adt7475_read(reg) i2c_smbus_read_byte_data(client, (reg))
+
+/* Macros to easily index the registers */
+
+#define TACH_REG(idx) (REG_TACH_BASE + ((idx) * 2))
+#define TACH_MIN_REG(idx) (REG_TACH_MIN_BASE + ((idx) * 2))
+
+#define PWM_REG(idx) (REG_PWM_BASE + (idx))
+#define PWM_MAX_REG(idx) (REG_PWM_MAX_BASE + (idx))
+#define PWM_MIN_REG(idx) (REG_PWM_MIN_BASE + (idx))
+#define PWM_CONFIG_REG(idx) (REG_PWM_CONFIG_BASE + (idx))
+
+#define VOLTAGE_REG(idx) (REG_VOLTAGE_BASE + (idx))
+#define VOLTAGE_MIN_REG(idx) (REG_VOLTAGE_MIN_BASE + ((idx) * 2))
+#define VOLTAGE_MAX_REG(idx) (REG_VOLTAGE_MAX_BASE + ((idx) * 2))
+
+#define TEMP_REG(idx) (REG_TEMP_BASE + (idx))
+#define TEMP_MIN_REG(idx) (REG_TEMP_MIN_BASE + ((idx) * 2))
+#define TEMP_MAX_REG(idx) (REG_TEMP_MAX_BASE + ((idx) * 2))
+#define TEMP_TMIN_REG(idx) (REG_TEMP_TMIN_BASE + (idx))
+#define TEMP_THERM_REG(idx) (REG_TEMP_THERM_BASE + (idx))
+#define TEMP_OFFSET_REG(idx) (REG_TEMP_OFFSET_BASE + (idx))
+#define TEMP_TRANGE_REG(idx) (REG_TEMP_TRANGE_BASE + (idx))
+
+static unsigned short normal_i2c[] = { 0x2e, I2C_CLIENT_END };
+
+I2C_CLIENT_INSMOD_1(adt7475);
+
+static const struct i2c_device_id adt7475_id[] = {
+ { "adt7475", adt7475 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adt7475_id);
+
+struct adt7475_data {
+ struct device *hwmon_dev;
+ struct mutex lock;
+
+ unsigned long measure_updated;
+ unsigned long limits_updated;
+ char valid;
+
+ u8 config5;
+ u16 alarms;
+ u16 voltage[3][3];
+ u16 temp[7][3];
+ u16 tach[2][4];
+ u8 pwm[4][3];
+ u8 range[3];
+ u8 pwmctl[3];
+ u8 pwmchan[3];
+};
+
+static struct i2c_driver adt7475_driver;
+static struct adt7475_data *adt7475_update_device(struct device *dev);
+static void adt7475_read_hystersis(struct i2c_client *client);
+static void adt7475_read_pwm(struct i2c_client *client, int index);
+
+/* Given a temp value, convert it to register value */
+
+static inline u16 temp2reg(struct adt7475_data *data, long val)
+{
+ u16 ret;
+
+ if (!(data->config5 & CONFIG5_TWOSCOMP)) {
+ val = SENSORS_LIMIT(val, -64000, 191000);
+ ret = (val + 64500) / 1000;
+ } else {
+ val = SENSORS_LIMIT(val, -128000, 127000);
+ if (val < -500)
+ ret = (256500 + val) / 1000;
+ else
+ ret = (val + 500) / 1000;
+ }
+
+ return ret << 2;
+}
+
+/* Given a register value, convert it to a real temp value */
+
+static inline int reg2temp(struct adt7475_data *data, u16 reg)
+{
+ if (data->config5 & CONFIG5_TWOSCOMP) {
+ if (reg >= 512)
+ return (reg - 1024) * 250;
+ else
+ return reg * 250;
+ } else
+ return (reg - 256) * 250;
+}
+
+static inline int tach2rpm(u16 tach)
+{
+ if (tach == 0 || tach == 0xFFFF)
+ return 0;
+
+ return (90000 * 60) / tach;
+}
+
+static inline u16 rpm2tach(unsigned long rpm)
+{
+ if (rpm == 0)
+ return 0;
+
+ return SENSORS_LIMIT((90000 * 60) / rpm, 1, 0xFFFF);
+}
+
+static inline int reg2vcc(u16 reg)
+{
+ return (4296 * reg) / 1000;
+}
+
+static inline int reg2vccp(u16 reg)
+{
+ return (2929 * reg) / 1000;
+}
+
+static inline u16 vcc2reg(long vcc)
+{
+ vcc = SENSORS_LIMIT(vcc, 0, 4396);
+ return (vcc * 1000) / 4296;
+}
+
+static inline u16 vccp2reg(long vcc)
+{
+ vcc = SENSORS_LIMIT(vcc, 0, 2998);
+ return (vcc * 1000) / 2929;
+}
+
+static u16 adt7475_read_word(struct i2c_client *client, int reg)
+{
+ u16 val;
+
+ val = i2c_smbus_read_byte_data(client, reg);
+ val |= (i2c_smbus_read_byte_data(client, reg + 1) << 8);
+
+ return val;
+}
+
+static void adt7475_write_word(struct i2c_client *client, int reg, u16 val)
+{
+ i2c_smbus_write_byte_data(client, reg + 1, val >> 8);
+ i2c_smbus_write_byte_data(client, reg, val & 0xFF);
+}
+
+/* Find the nearest value in a table - used for pwm frequency and
+ auto temp range */
+static int find_nearest(long val, const int *array, int size)
+{
+ int i;
+
+ if (val < array[0])
+ return 0;
+
+ if (val > array[size - 1])
+ return size - 1;
+
+ for (i = 0; i < size - 1; i++) {
+ int a, b;
+
+ if (val > array[i + 1])
+ continue;
+
+ a = val - array[i];
+ b = array[i + 1] - val;
+
+ return (a <= b) ? i : i + 1;
+ }
+
+ return 0;
+}
+
+static ssize_t show_voltage(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adt7475_data *data = adt7475_update_device(dev);
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ unsigned short val;
+
+ switch (sattr->nr) {
+ case ALARM:
+ return sprintf(buf, "%d\n",
+ (data->alarms >> (sattr->index + 1)) & 1);
+ default:
+ val = data->voltage[sattr->nr][sattr->index];
+ return sprintf(buf, "%d\n",
+ sattr->index ==
+ 0 ? reg2vccp(val) : reg2vcc(val));
+ }
+}
+
+static ssize_t set_voltage(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ unsigned char reg;
+ long val;
+
+ if (strict_strtol(buf, 10, &val))
+ return -EINVAL;
+
+ mutex_lock(&data->lock);
+
+ data->voltage[sattr->nr][sattr->index] =
+ sattr->index ? vcc2reg(val) : vccp2reg(val);
+
+ if (sattr->nr == MIN)
+ reg = VOLTAGE_MIN_REG(sattr->index);
+ else
+ reg = VOLTAGE_MAX_REG(sattr->index);
+
+ i2c_smbus_write_byte_data(client, reg,
+ data->voltage[sattr->nr][sattr->index] >> 2);
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adt7475_data *data = adt7475_update_device(dev);
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ int out;
+
+ switch (sattr->nr) {
+ case HYSTERSIS:
+ mutex_lock(&data->lock);
+ out = data->temp[sattr->nr][sattr->index];
+ if (sattr->index != 1)
+ out = (out >> 4) & 0xF;
+ else
+ out = (out & 0xF);
+ /* Show the value as an absolute number tied to
+ * THERM */
+ out = reg2temp(data, data->temp[THERM][sattr->index]) -
+ out * 1000;
+ mutex_unlock(&data->lock);
+ break;
+
+ case OFFSET:
+ /* Offset is always 2's complement, regardless of the
+ * setting in CONFIG5 */
+ mutex_lock(&data->lock);
+ out = (s8)data->temp[sattr->nr][sattr->index];
+ if (data->config5 & CONFIG5_TEMPOFFSET)
+ out *= 1000;
+ else
+ out *= 500;
+ mutex_unlock(&data->lock);
+ break;
+
+ case ALARM:
+ out = (data->alarms >> (sattr->index + 4)) & 1;
+ break;
+
+ case FAULT:
+ /* Note - only for remote1 and remote2 */
+ out = data->alarms & (sattr->index ? 0x8000 : 0x4000);
+ out = out ? 0 : 1;
+ break;
+
+ default:
+ /* All other temp values are in the configured format */
+ out = reg2temp(data, data->temp[sattr->nr][sattr->index]);
+ }
+
+ return sprintf(buf, "%d\n", out);
+}
+
+static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ unsigned char reg = 0;
+ u8 out;
+ int temp;
+ long val;
+
+ if (strict_strtol(buf, 10, &val))
+ return -EINVAL;
+
+ mutex_lock(&data->lock);
+
+ /* We need the config register in all cases for temp <-> reg conv. */
+ data->config5 = adt7475_read(REG_CONFIG5);
+
+ switch (sattr->nr) {
+ case OFFSET:
+ if (data->config5 & CONFIG5_TEMPOFFSET) {
+ val = SENSORS_LIMIT(val, -63000, 127000);
+ out = data->temp[OFFSET][sattr->index] = val / 1000;
+ } else {
+ val = SENSORS_LIMIT(val, -63000, 64000);
+ out = data->temp[OFFSET][sattr->index] = val / 500;
+ }
+ break;
+
+ case HYSTERSIS:
+ /* The value will be given as an absolute value, turn it
+ into an offset based on THERM */
+
+ /* Read fresh THERM and HYSTERSIS values from the chip */
+ data->temp[THERM][sattr->index] =
+ adt7475_read(TEMP_THERM_REG(sattr->index)) << 2;
+ adt7475_read_hystersis(client);
+
+ temp = reg2temp(data, data->temp[THERM][sattr->index]);
+ val = SENSORS_LIMIT(val, temp - 15000, temp);
+ val = (temp - val) / 1000;
+
+ if (sattr->index != 1) {
+ data->temp[HYSTERSIS][sattr->index] &= 0xF0;
+ data->temp[HYSTERSIS][sattr->index] |= (val & 0xF) << 4;
+ } else {
+ data->temp[HYSTERSIS][sattr->index] &= 0x0F;
+ data->temp[HYSTERSIS][sattr->index] |= (val & 0xF);
+ }
+
+ out = data->temp[HYSTERSIS][sattr->index];
+ break;
+
+ default:
+ data->temp[sattr->nr][sattr->index] = temp2reg(data, val);
+
+ /* We maintain an extra 2 digits of precision for simplicity
+ * - shift those back off before writing the value */
+ out = (u8) (data->temp[sattr->nr][sattr->index] >> 2);
+ }
+
+ switch (sattr->nr) {
+ case MIN:
+ reg = TEMP_MIN_REG(sattr->index);
+ break;
+ case MAX:
+ reg = TEMP_MAX_REG(sattr->index);
+ break;
+ case OFFSET:
+ reg = TEMP_OFFSET_REG(sattr->index);
+ break;
+ case AUTOMIN:
+ reg = TEMP_TMIN_REG(sattr->index);
+ break;
+ case THERM:
+ reg = TEMP_THERM_REG(sattr->index);
+ break;
+ case HYSTERSIS:
+ if (sattr->index != 2)
+ reg = REG_REMOTE1_HYSTERSIS;
+ else
+ reg = REG_REMOTE2_HYSTERSIS;
+
+ break;
+ }
+
+ i2c_smbus_write_byte_data(client, reg, out);
+
+ mutex_unlock(&data->lock);
+ return count;
+}
+
+/* Table of autorange values - the user will write the value in millidegrees,
+ and we'll convert it */
+static const int autorange_table[] = {
+ 2000, 2500, 3330, 4000, 5000, 6670, 8000,
+ 10000, 13330, 16000, 20000, 26670, 32000, 40000,
+ 53330, 80000
+};
+
+static ssize_t show_point2(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adt7475_data *data = adt7475_update_device(dev);
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ int out, val;
+
+ mutex_lock(&data->lock);
+ out = (data->range[sattr->index] >> 4) & 0x0F;
+ val = reg2temp(data, data->temp[AUTOMIN][sattr->index]);
+ mutex_unlock(&data->lock);
+
+ return sprintf(buf, "%d\n", val + autorange_table[out]);
+}
+
+static ssize_t set_point2(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ int temp;
+ long val;
+
+ if (strict_strtol(buf, 10, &val))
+ return -EINVAL;
+
+ mutex_lock(&data->lock);
+
+ /* Get a fresh copy of the needed registers */
+ data->config5 = adt7475_read(REG_CONFIG5);
+ data->temp[AUTOMIN][sattr->index] =
+ adt7475_read(TEMP_TMIN_REG(sattr->index)) << 2;
+ data->range[sattr->index] =
+ adt7475_read(TEMP_TRANGE_REG(sattr->index));
+
+ /* The user will write an absolute value, so subtract the start point
+ to figure the range */
+ temp = reg2temp(data, data->temp[AUTOMIN][sattr->index]);
+ val = SENSORS_LIMIT(val, temp + autorange_table[0],
+ temp + autorange_table[ARRAY_SIZE(autorange_table) - 1]);
+ val -= temp;
+
+ /* Find the nearest table entry to what the user wrote */
+ val = find_nearest(val, autorange_table, ARRAY_SIZE(autorange_table));
+
+ data->range[sattr->index] &= ~0xF0;
+ data->range[sattr->index] |= val << 4;
+
+ i2c_smbus_write_byte_data(client, TEMP_TRANGE_REG(sattr->index),
+ data->range[sattr->index]);
+
+ mutex_unlock(&data->lock);
+ return count;
+}
+
+static ssize_t show_tach(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adt7475_data *data = adt7475_update_device(dev);
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ int out;
+
+ if (sattr->nr == ALARM)
+ out = (data->alarms >> (sattr->index + 10)) & 1;
+ else
+ out = tach2rpm(data->tach[sattr->nr][sattr->index]);
+
+ return sprintf(buf, "%d\n", out);
+}
+
+static ssize_t set_tach(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ unsigned long val;
+
+ if (strict_strtoul(buf, 10, &val))
+ return -EINVAL;
+
+ mutex_lock(&data->lock);
+
+ data->tach[MIN][sattr->index] = rpm2tach(val);
+
+ adt7475_write_word(client, TACH_MIN_REG(sattr->index),
+ data->tach[MIN][sattr->index]);
+
+ mutex_unlock(&data->lock);
+ return count;
+}
+
+static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adt7475_data *data = adt7475_update_device(dev);
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+ return sprintf(buf, "%d\n", data->pwm[sattr->nr][sattr->index]);
+}
+
+static ssize_t show_pwmchan(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adt7475_data *data = adt7475_update_device(dev);
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+ return sprintf(buf, "%d\n", data->pwmchan[sattr->index]);
+}
+
+static ssize_t show_pwmctrl(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adt7475_data *data = adt7475_update_device(dev);
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+ return sprintf(buf, "%d\n", data->pwmctl[sattr->index]);
+}
+
+static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ unsigned char reg = 0;
+ long val;
+
+ if (strict_strtol(buf, 10, &val))
+ return -EINVAL;
+
+ mutex_lock(&data->lock);
+
+ switch (sattr->nr) {
+ case INPUT:
+ /* Get a fresh value for CONTROL */
+ data->pwm[CONTROL][sattr->index] =
+ adt7475_read(PWM_CONFIG_REG(sattr->index));
+
+ /* If we are not in manual mode, then we shouldn't allow
+ * the user to set the pwm speed */
+ if (((data->pwm[CONTROL][sattr->index] >> 5) & 7) != 7) {
+ mutex_unlock(&data->lock);
+ return count;
+ }
+
+ reg = PWM_REG(sattr->index);
+ break;
+
+ case MIN:
+ reg = PWM_MIN_REG(sattr->index);
+ break;
+
+ case MAX:
+ reg = PWM_MAX_REG(sattr->index);
+ break;
+ }
+
+ data->pwm[sattr->nr][sattr->index] = SENSORS_LIMIT(val, 0, 0xFF);
+ i2c_smbus_write_byte_data(client, reg,
+ data->pwm[sattr->nr][sattr->index]);
+
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+/* Called by set_pwmctrl and set_pwmchan */
+
+static int hw_set_pwm(struct i2c_client *client, int index,
+ unsigned int pwmctl, unsigned int pwmchan)
+{
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ long val = 0;
+
+ switch (pwmctl) {
+ case 0:
+ val = 0x03; /* Run at full speed */
+ break;
+ case 1:
+ val = 0x07; /* Manual mode */
+ break;
+ case 2:
+ switch (pwmchan) {
+ case 1:
+ /* Remote1 controls PWM */
+ val = 0x00;
+ break;
+ case 2:
+ /* local controls PWM */
+ val = 0x01;
+ break;
+ case 4:
+ /* remote2 controls PWM */
+ val = 0x02;
+ break;
+ case 6:
+ /* local/remote2 control PWM */
+ val = 0x05;
+ break;
+ case 7:
+ /* All three control PWM */
+ val = 0x06;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ data->pwmctl[index] = pwmctl;
+ data->pwmchan[index] = pwmchan;
+
+ data->pwm[CONTROL][index] &= ~0xE0;
+ data->pwm[CONTROL][index] |= (val & 7) << 5;
+
+ i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index),
+ data->pwm[CONTROL][index]);
+
+ return 0;
+}
+
+static ssize_t set_pwmchan(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ int r;
+ long val;
+
+ if (strict_strtol(buf, 10, &val))
+ return -EINVAL;
+
+ mutex_lock(&data->lock);
+ /* Read Modify Write PWM values */
+ adt7475_read_pwm(client, sattr->index);
+ r = hw_set_pwm(client, sattr->index, data->pwmctl[sattr->index], val);
+ if (r)
+ count = r;
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static ssize_t set_pwmctrl(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ int r;
+ long val;
+
+ if (strict_strtol(buf, 10, &val))
+ return -EINVAL;
+
+ mutex_lock(&data->lock);
+ /* Read Modify Write PWM values */
+ adt7475_read_pwm(client, sattr->index);
+ r = hw_set_pwm(client, sattr->index, val, data->pwmchan[sattr->index]);
+ if (r)
+ count = r;
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+/* List of frequencies for the PWM */
+static const int pwmfreq_table[] = {
+ 11, 14, 22, 29, 35, 44, 58, 88
+};
+
+static ssize_t show_pwmfreq(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adt7475_data *data = adt7475_update_device(dev);
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+ return sprintf(buf, "%d\n",
+ pwmfreq_table[data->range[sattr->index] & 7]);
+}
+
+static ssize_t set_pwmfreq(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ int out;
+ long val;
+
+ if (strict_strtol(buf, 10, &val))
+ return -EINVAL;
+
+ out = find_nearest(val, pwmfreq_table, ARRAY_SIZE(pwmfreq_table));
+
+ mutex_lock(&data->lock);
+
+ data->range[sattr->index] =
+ adt7475_read(TEMP_TRANGE_REG(sattr->index));
+ data->range[sattr->index] &= ~7;
+ data->range[sattr->index] |= out;
+
+ i2c_smbus_write_byte_data(client, TEMP_TRANGE_REG(sattr->index),
+ data->range[sattr->index]);
+
+ mutex_unlock(&data->lock);
+ return count;
+}
+
+static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_voltage, NULL, INPUT, 0);
+static SENSOR_DEVICE_ATTR_2(in1_max, S_IRUGO | S_IWUSR, show_voltage,
+ set_voltage, MAX, 0);
+static SENSOR_DEVICE_ATTR_2(in1_min, S_IRUGO | S_IWUSR, show_voltage,
+ set_voltage, MIN, 0);
+static SENSOR_DEVICE_ATTR_2(in1_alarm, S_IRUGO, show_voltage, NULL, ALARM, 0);
+static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_voltage, NULL, INPUT, 1);
+static SENSOR_DEVICE_ATTR_2(in2_max, S_IRUGO | S_IWUSR, show_voltage,
+ set_voltage, MAX, 1);
+static SENSOR_DEVICE_ATTR_2(in2_min, S_IRUGO | S_IWUSR, show_voltage,
+ set_voltage, MIN, 1);
+static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, show_voltage, NULL, ALARM, 1);
+static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, INPUT, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_alarm, S_IRUGO, show_temp, NULL, ALARM, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_fault, S_IRUGO, show_temp, NULL, FAULT, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
+ MAX, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
+ MIN, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_offset, S_IRUGO | S_IWUSR, show_temp,
+ set_temp, OFFSET, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_auto_point1_temp, S_IRUGO | S_IWUSR,
+ show_temp, set_temp, AUTOMIN, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_auto_point2_temp, S_IRUGO | S_IWUSR,
+ show_point2, set_point2, 0, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
+ THERM, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_crit_hyst, S_IRUGO | S_IWUSR, show_temp,
+ set_temp, HYSTERSIS, 0);
+static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, INPUT, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_alarm, S_IRUGO, show_temp, NULL, ALARM, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
+ MAX, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
+ MIN, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_offset, S_IRUGO | S_IWUSR, show_temp,
+ set_temp, OFFSET, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_auto_point1_temp, S_IRUGO | S_IWUSR,
+ show_temp, set_temp, AUTOMIN, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_auto_point2_temp, S_IRUGO | S_IWUSR,
+ show_point2, set_point2, 0, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
+ THERM, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_crit_hyst, S_IRUGO | S_IWUSR, show_temp,
+ set_temp, HYSTERSIS, 1);
+static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, INPUT, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_alarm, S_IRUGO, show_temp, NULL, ALARM, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_fault, S_IRUGO, show_temp, NULL, FAULT, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
+ MAX, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
+ MIN, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_offset, S_IRUGO | S_IWUSR, show_temp,
+ set_temp, OFFSET, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_auto_point1_temp, S_IRUGO | S_IWUSR,
+ show_temp, set_temp, AUTOMIN, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_auto_point2_temp, S_IRUGO | S_IWUSR,
+ show_point2, set_point2, 0, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
+ THERM, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_crit_hyst, S_IRUGO | S_IWUSR, show_temp,
+ set_temp, HYSTERSIS, 2);
+static SENSOR_DEVICE_ATTR_2(fan1_input, S_IRUGO, show_tach, NULL, INPUT, 0);
+static SENSOR_DEVICE_ATTR_2(fan1_min, S_IRUGO | S_IWUSR, show_tach, set_tach,
+ MIN, 0);
+static SENSOR_DEVICE_ATTR_2(fan1_alarm, S_IRUGO, show_tach, NULL, ALARM, 0);
+static SENSOR_DEVICE_ATTR_2(fan2_input, S_IRUGO, show_tach, NULL, INPUT, 1);
+static SENSOR_DEVICE_ATTR_2(fan2_min, S_IRUGO | S_IWUSR, show_tach, set_tach,
+ MIN, 1);
+static SENSOR_DEVICE_ATTR_2(fan2_alarm, S_IRUGO, show_tach, NULL, ALARM, 1);
+static SENSOR_DEVICE_ATTR_2(fan3_input, S_IRUGO, show_tach, NULL, INPUT, 2);
+static SENSOR_DEVICE_ATTR_2(fan3_min, S_IRUGO | S_IWUSR, show_tach, set_tach,
+ MIN, 2);
+static SENSOR_DEVICE_ATTR_2(fan3_alarm, S_IRUGO, show_tach, NULL, ALARM, 2);
+static SENSOR_DEVICE_ATTR_2(fan4_input, S_IRUGO, show_tach, NULL, INPUT, 3);
+static SENSOR_DEVICE_ATTR_2(fan4_min, S_IRUGO | S_IWUSR, show_tach, set_tach,
+ MIN, 3);
+static SENSOR_DEVICE_ATTR_2(fan4_alarm, S_IRUGO, show_tach, NULL, ALARM, 3);
+static SENSOR_DEVICE_ATTR_2(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, INPUT,
+ 0);
+static SENSOR_DEVICE_ATTR_2(pwm1_freq, S_IRUGO | S_IWUSR, show_pwmfreq,
+ set_pwmfreq, INPUT, 0);
+static SENSOR_DEVICE_ATTR_2(pwm1_enable, S_IRUGO | S_IWUSR, show_pwmctrl,
+ set_pwmctrl, INPUT, 0);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_channel_temp, S_IRUGO | S_IWUSR,
+ show_pwmchan, set_pwmchan, INPUT, 0);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO | S_IWUSR, show_pwm,
+ set_pwm, MIN, 0);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm,
+ set_pwm, MAX, 0);
+static SENSOR_DEVICE_ATTR_2(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, INPUT,
+ 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_freq, S_IRUGO | S_IWUSR, show_pwmfreq,
+ set_pwmfreq, INPUT, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_enable, S_IRUGO | S_IWUSR, show_pwmctrl,
+ set_pwmctrl, INPUT, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_channel_temp, S_IRUGO | S_IWUSR,
+ show_pwmchan, set_pwmchan, INPUT, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO | S_IWUSR, show_pwm,
+ set_pwm, MIN, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm,
+ set_pwm, MAX, 1);
+static SENSOR_DEVICE_ATTR_2(pwm3, S_IRUGO | S_IWUSR, show_pwm, set_pwm, INPUT,
+ 2);
+static SENSOR_DEVICE_ATTR_2(pwm3_freq, S_IRUGO | S_IWUSR, show_pwmfreq,
+ set_pwmfreq, INPUT, 2);
+static SENSOR_DEVICE_ATTR_2(pwm3_enable, S_IRUGO | S_IWUSR, show_pwmctrl,
+ set_pwmctrl, INPUT, 2);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_channel_temp, S_IRUGO | S_IWUSR,
+ show_pwmchan, set_pwmchan, INPUT, 2);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO | S_IWUSR, show_pwm,
+ set_pwm, MIN, 2);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm,
+ set_pwm, MAX, 2);
+
+static struct attribute *adt7475_attrs[] = {
+ &sensor_dev_attr_in1_input.dev_attr.attr,
+ &sensor_dev_attr_in1_max.dev_attr.attr,
+ &sensor_dev_attr_in1_min.dev_attr.attr,
+ &sensor_dev_attr_in1_alarm.dev_attr.attr,
+ &sensor_dev_attr_in2_input.dev_attr.attr,
+ &sensor_dev_attr_in2_max.dev_attr.attr,
+ &sensor_dev_attr_in2_min.dev_attr.attr,
+ &sensor_dev_attr_in2_alarm.dev_attr.attr,
+ &sensor_dev_attr_temp1_input.dev_attr.attr,
+ &sensor_dev_attr_temp1_alarm.dev_attr.attr,
+ &sensor_dev_attr_temp1_fault.dev_attr.attr,
+ &sensor_dev_attr_temp1_max.dev_attr.attr,
+ &sensor_dev_attr_temp1_min.dev_attr.attr,
+ &sensor_dev_attr_temp1_offset.dev_attr.attr,
+ &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
+ &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr,
+ &sensor_dev_attr_temp1_crit.dev_attr.attr,
+ &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
+ &sensor_dev_attr_temp2_input.dev_attr.attr,
+ &sensor_dev_attr_temp2_alarm.dev_attr.attr,
+ &sensor_dev_attr_temp2_max.dev_attr.attr,
+ &sensor_dev_attr_temp2_min.dev_attr.attr,
+ &sensor_dev_attr_temp2_offset.dev_attr.attr,
+ &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr,
+ &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr,
+ &sensor_dev_attr_temp2_crit.dev_attr.attr,
+ &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr,
+ &sensor_dev_attr_temp3_input.dev_attr.attr,
+ &sensor_dev_attr_temp3_fault.dev_attr.attr,
+ &sensor_dev_attr_temp3_alarm.dev_attr.attr,
+ &sensor_dev_attr_temp3_max.dev_attr.attr,
+ &sensor_dev_attr_temp3_min.dev_attr.attr,
+ &sensor_dev_attr_temp3_offset.dev_attr.attr,
+ &sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr,
+ &sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr,
+ &sensor_dev_attr_temp3_crit.dev_attr.attr,
+ &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr,
+ &sensor_dev_attr_fan1_input.dev_attr.attr,
+ &sensor_dev_attr_fan1_min.dev_attr.attr,
+ &sensor_dev_attr_fan1_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan2_input.dev_attr.attr,
+ &sensor_dev_attr_fan2_min.dev_attr.attr,
+ &sensor_dev_attr_fan2_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan3_input.dev_attr.attr,
+ &sensor_dev_attr_fan3_min.dev_attr.attr,
+ &sensor_dev_attr_fan3_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan4_input.dev_attr.attr,
+ &sensor_dev_attr_fan4_min.dev_attr.attr,
+ &sensor_dev_attr_fan4_alarm.dev_attr.attr,
+ &sensor_dev_attr_pwm1.dev_attr.attr,
+ &sensor_dev_attr_pwm1_freq.dev_attr.attr,
+ &sensor_dev_attr_pwm1_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_channel_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm2.dev_attr.attr,
+ &sensor_dev_attr_pwm2_freq.dev_attr.attr,
+ &sensor_dev_attr_pwm2_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_channel_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm3.dev_attr.attr,
+ &sensor_dev_attr_pwm3_freq.dev_attr.attr,
+ &sensor_dev_attr_pwm3_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm3_auto_channel_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr,
+ NULL,
+};
+
+struct attribute_group adt7475_attr_group = { .attrs = adt7475_attrs };
+
+static int adt7475_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
+{
+ struct i2c_adapter *adapter = client->adapter;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
+
+ if (kind <= 0) {
+ if (adt7475_read(REG_VENDID) != 0x41 ||
+ adt7475_read(REG_DEVID) != 0x75) {
+ dev_err(&adapter->dev,
+ "Couldn't detect a adt7475 part at 0x%02x\n",
+ (unsigned int)client->addr);
+ return -ENODEV;
+ }
+ }
+
+ strlcpy(info->type, adt7475_id[0].name, I2C_NAME_SIZE);
+
+ return 0;
+}
+
+static int adt7475_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct adt7475_data *data;
+ int i, ret = 0;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+
+ mutex_init(&data->lock);
+ i2c_set_clientdata(client, data);
+
+ /* Call adt7475_read_pwm for all pwm's as this will reprogram any
+ pwm's which are disabled to manual mode with 0% duty cycle */
+ for (i = 0; i < ADT7475_PWM_COUNT; i++)
+ adt7475_read_pwm(client, i);
+
+ ret = sysfs_create_group(&client->dev.kobj, &adt7475_attr_group);
+ if (ret)
+ goto efree;
+
+ data->hwmon_dev = hwmon_device_register(&client->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ ret = PTR_ERR(data->hwmon_dev);
+ goto eremove;
+ }
+
+ return 0;
+
+eremove:
+ sysfs_remove_group(&client->dev.kobj, &adt7475_attr_group);
+efree:
+ kfree(data);
+ return ret;
+}
+
+static int adt7475_remove(struct i2c_client *client)
+{
+ struct adt7475_data *data = i2c_get_clientdata(client);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &adt7475_attr_group);
+ kfree(data);
+
+ return 0;
+}
+
+static struct i2c_driver adt7475_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "adt7475",
+ },
+ .probe = adt7475_probe,
+ .remove = adt7475_remove,
+ .id_table = adt7475_id,
+ .detect = adt7475_detect,
+ .address_data = &addr_data,
+};
+
+static void adt7475_read_hystersis(struct i2c_client *client)
+{
+ struct adt7475_data *data = i2c_get_clientdata(client);
+
+ data->temp[HYSTERSIS][0] = (u16) adt7475_read(REG_REMOTE1_HYSTERSIS);
+ data->temp[HYSTERSIS][1] = data->temp[HYSTERSIS][0];
+ data->temp[HYSTERSIS][2] = (u16) adt7475_read(REG_REMOTE2_HYSTERSIS);
+}
+
+static void adt7475_read_pwm(struct i2c_client *client, int index)
+{
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ unsigned int v;
+
+ data->pwm[CONTROL][index] = adt7475_read(PWM_CONFIG_REG(index));
+
+ /* Figure out the internal value for pwmctrl and pwmchan
+ based on the current settings */
+ v = (data->pwm[CONTROL][index] >> 5) & 7;
+
+ if (v == 3)
+ data->pwmctl[index] = 0;
+ else if (v == 7)
+ data->pwmctl[index] = 1;
+ else if (v == 4) {
+ /* The fan is disabled - we don't want to
+ support that, so change to manual mode and
+ set the duty cycle to 0 instead
+ */
+ data->pwm[INPUT][index] = 0;
+ data->pwm[CONTROL][index] &= ~0xE0;
+ data->pwm[CONTROL][index] |= (7 << 5);
+
+ i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index),
+ data->pwm[INPUT][index]);
+
+ i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index),
+ data->pwm[CONTROL][index]);
+
+ data->pwmctl[index] = 1;
+ } else {
+ data->pwmctl[index] = 2;
+
+ switch (v) {
+ case 0:
+ data->pwmchan[index] = 1;
+ break;
+ case 1:
+ data->pwmchan[index] = 2;
+ break;
+ case 2:
+ data->pwmchan[index] = 4;
+ break;
+ case 5:
+ data->pwmchan[index] = 6;
+ break;
+ case 6:
+ data->pwmchan[index] = 7;
+ break;
+ }
+ }
+}
+
+static struct adt7475_data *adt7475_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ u8 ext;
+ int i;
+
+ mutex_lock(&data->lock);
+
+ /* Measurement values update every 2 seconds */
+ if (time_after(jiffies, data->measure_updated + HZ * 2) ||
+ !data->valid) {
+ data->alarms = adt7475_read(REG_STATUS2) << 8;
+ data->alarms |= adt7475_read(REG_STATUS1);
+
+ ext = adt7475_read(REG_EXTEND1);
+ for (i = 0; i < ADT7475_VOLTAGE_COUNT; i++)
+ data->voltage[INPUT][i] =
+ (adt7475_read(VOLTAGE_REG(i)) << 2) |
+ ((ext >> ((i + 1) * 2)) & 3);
+
+ ext = adt7475_read(REG_EXTEND2);
+ for (i = 0; i < ADT7475_TEMP_COUNT; i++)
+ data->temp[INPUT][i] =
+ (adt7475_read(TEMP_REG(i)) << 2) |
+ ((ext >> ((i + 1) * 2)) & 3);
+
+ for (i = 0; i < ADT7475_TACH_COUNT; i++)
+ data->tach[INPUT][i] =
+ adt7475_read_word(client, TACH_REG(i));
+
+ /* Updated by hw when in auto mode */
+ for (i = 0; i < ADT7475_PWM_COUNT; i++)
+ data->pwm[INPUT][i] = adt7475_read(PWM_REG(i));
+
+ data->measure_updated = jiffies;
+ }
+
+ /* Limits and settings, should never change update every 60 seconds */
+ if (time_after(jiffies, data->limits_updated + HZ * 2) ||
+ !data->valid) {
+ data->config5 = adt7475_read(REG_CONFIG5);
+
+ for (i = 0; i < ADT7475_VOLTAGE_COUNT; i++) {
+ /* Adjust values so they match the input precision */
+ data->voltage[MIN][i] =
+ adt7475_read(VOLTAGE_MIN_REG(i)) << 2;
+ data->voltage[MAX][i] =
+ adt7475_read(VOLTAGE_MAX_REG(i)) << 2;
+ }
+
+ for (i = 0; i < ADT7475_TEMP_COUNT; i++) {
+ /* Adjust values so they match the input precision */
+ data->temp[MIN][i] =
+ adt7475_read(TEMP_MIN_REG(i)) << 2;
+ data->temp[MAX][i] =
+ adt7475_read(TEMP_MAX_REG(i)) << 2;
+ data->temp[AUTOMIN][i] =
+ adt7475_read(TEMP_TMIN_REG(i)) << 2;
+ data->temp[THERM][i] =
+ adt7475_read(TEMP_THERM_REG(i)) << 2;
+ data->temp[OFFSET][i] =
+ adt7475_read(TEMP_OFFSET_REG(i));
+ }
+ adt7475_read_hystersis(client);
+
+ for (i = 0; i < ADT7475_TACH_COUNT; i++)
+ data->tach[MIN][i] =
+ adt7475_read_word(client, TACH_MIN_REG(i));
+
+ for (i = 0; i < ADT7475_PWM_COUNT; i++) {
+ data->pwm[MAX][i] = adt7475_read(PWM_MAX_REG(i));
+ data->pwm[MIN][i] = adt7475_read(PWM_MIN_REG(i));
+ /* Set the channel and control information */
+ adt7475_read_pwm(client, i);
+ }
+
+ data->range[0] = adt7475_read(TEMP_TRANGE_REG(0));
+ data->range[1] = adt7475_read(TEMP_TRANGE_REG(1));
+ data->range[2] = adt7475_read(TEMP_TRANGE_REG(2));
+
+ data->limits_updated = jiffies;
+ data->valid = 1;
+ }
+
+ mutex_unlock(&data->lock);
+
+ return data;
+}
+
+static int __init sensors_adt7475_init(void)
+{
+ return i2c_add_driver(&adt7475_driver);
+}
+
+static void __exit sensors_adt7475_exit(void)
+{
+ i2c_del_driver(&adt7475_driver);
+}
+
+MODULE_AUTHOR("Advanced Micro Devices, Inc");
+MODULE_DESCRIPTION("adt7475 driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_adt7475_init);
+module_exit(sensors_adt7475_exit);
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index dca47a5..e301862 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -590,6 +590,11 @@ static ssize_t applesmc_light_show(struct device *dev,
}
ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, data_length);
+ /* newer macbooks report a single 10-bit bigendian value */
+ if (data_length == 10) {
+ left = be16_to_cpu(*(__be16 *)(buffer + 6)) >> 2;
+ goto out;
+ }
left = buffer[2];
if (ret)
goto out;
diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c
index bf8d405..0370524 100644
--- a/drivers/hwmon/hp_accel.c
+++ b/drivers/hwmon/hp_accel.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2007-2008 Yan Burman
* Copyright (C) 2008 Eric Piel
- * Copyright (C) 2008 Pavel Machek
+ * Copyright (C) 2008-2009 Pavel Machek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -36,6 +36,7 @@
#include <linux/freezer.h>
#include <linux/version.h>
#include <linux/uaccess.h>
+#include <linux/leds.h>
#include <acpi/acpi_drivers.h>
#include <asm/atomic.h>
#include "lis3lv02d.h"
@@ -43,6 +44,36 @@
#define DRIVER_NAME "lis3lv02d"
#define ACPI_MDPS_CLASS "accelerometer"
+/* Delayed LEDs infrastructure ------------------------------------ */
+
+/* Special LED class that can defer work */
+struct delayed_led_classdev {
+ struct led_classdev led_classdev;
+ struct work_struct work;
+ enum led_brightness new_brightness;
+
+ unsigned int led; /* For driver */
+ void (*set_brightness)(struct delayed_led_classdev *data, enum led_brightness value);
+};
+
+static inline void delayed_set_status_worker(struct work_struct *work)
+{
+ struct delayed_led_classdev *data =
+ container_of(work, struct delayed_led_classdev, work);
+
+ data->set_brightness(data, data->new_brightness);
+}
+
+static inline void delayed_sysfs_set(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ struct delayed_led_classdev *data = container_of(led_cdev,
+ struct delayed_led_classdev, led_classdev);
+ data->new_brightness = brightness;
+ schedule_work(&data->work);
+}
+
+/* HP-specific accelerometer driver ------------------------------------ */
/* For automatic insertion of the module */
static struct acpi_device_id lis3lv02d_device_ids[] = {
@@ -154,10 +185,33 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
*/
};
+static void hpled_set(struct delayed_led_classdev *led_cdev, enum led_brightness value)
+{
+ acpi_handle handle = adev.device->handle;
+ unsigned long long ret; /* Not used when writing */
+ union acpi_object in_obj[1];
+ struct acpi_object_list args = { 1, in_obj };
+
+ in_obj[0].type = ACPI_TYPE_INTEGER;
+ in_obj[0].integer.value = !!value;
+
+ acpi_evaluate_integer(handle, "ALED", &args, &ret);
+}
+
+static struct delayed_led_classdev hpled_led = {
+ .led_classdev = {
+ .name = "hp::hddprotect",
+ .default_trigger = "none",
+ .brightness_set = delayed_sysfs_set,
+ .flags = LED_CORE_SUSPENDRESUME,
+ },
+ .set_brightness = hpled_set,
+};
static int lis3lv02d_add(struct acpi_device *device)
{
u8 val;
+ int ret;
if (!device)
return -EINVAL;
@@ -183,7 +237,19 @@ static int lis3lv02d_add(struct acpi_device *device)
adev.ac = lis3lv02d_axis_normal;
}
- return lis3lv02d_init_device(&adev);
+ INIT_WORK(&hpled_led.work, delayed_set_status_worker);
+ ret = led_classdev_register(NULL, &hpled_led.led_classdev);
+ if (ret)
+ return ret;
+
+ ret = lis3lv02d_init_device(&adev);
+ if (ret) {
+ flush_work(&hpled_led.work);
+ led_classdev_unregister(&hpled_led.led_classdev);
+ return ret;
+ }
+
+ return ret;
}
static int lis3lv02d_remove(struct acpi_device *device, int type)
@@ -194,6 +260,9 @@ static int lis3lv02d_remove(struct acpi_device *device, int type)
lis3lv02d_joystick_disable();
lis3lv02d_poweroff(device->handle);
+ flush_work(&hpled_led.work);
+ led_classdev_unregister(&hpled_led.led_classdev);
+
return lis3lv02d_remove_fs();
}
@@ -256,7 +325,7 @@ static void __exit lis3lv02d_exit_module(void)
acpi_bus_unregister_driver(&lis3lv02d_driver);
}
-MODULE_DESCRIPTION("Glue between LIS3LV02Dx and HP ACPI BIOS");
+MODULE_DESCRIPTION("Glue between LIS3LV02Dx and HP ACPI BIOS and support for disk protection LED.");
MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
index bd2bde0..1fe9951 100644
--- a/drivers/hwmon/k8temp.c
+++ b/drivers/hwmon/k8temp.c
@@ -31,6 +31,7 @@
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
+#include <asm/processor.h>
#define TEMP_FROM_REG(val) (((((val) >> 16) & 0xff) - 49) * 1000)
#define REG_TEMP 0xe4
@@ -47,6 +48,8 @@ struct k8temp_data {
/* registers values */
u8 sensorsp; /* sensor presence bits - SEL_CORE & SEL_PLACE */
u32 temp[2][2]; /* core, place */
+ u8 swap_core_select; /* meaning of SEL_CORE is inverted */
+ u32 temp_offset;
};
static struct k8temp_data *k8temp_update_device(struct device *dev)
@@ -114,10 +117,15 @@ static ssize_t show_temp(struct device *dev,
to_sensor_dev_attr_2(devattr);
int core = attr->nr;
int place = attr->index;
+ int temp;
struct k8temp_data *data = k8temp_update_device(dev);
- return sprintf(buf, "%d\n",
- TEMP_FROM_REG(data->temp[core][place]));
+ if (data->swap_core_select)
+ core = core ? 0 : 1;
+
+ temp = TEMP_FROM_REG(data->temp[core][place]) + data->temp_offset;
+
+ return sprintf(buf, "%d\n", temp);
}
/* core, place */
@@ -141,20 +149,49 @@ static int __devinit k8temp_probe(struct pci_dev *pdev,
int err;
u8 scfg;
u32 temp;
+ u8 model, stepping;
struct k8temp_data *data;
- u32 cpuid = cpuid_eax(1);
-
- /* this feature should be available since SH-C0 core */
- if ((cpuid == 0xf40) || (cpuid == 0xf50) || (cpuid == 0xf51)) {
- err = -ENODEV;
- goto exit;
- }
if (!(data = kzalloc(sizeof(struct k8temp_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
+ model = boot_cpu_data.x86_model;
+ stepping = boot_cpu_data.x86_mask;
+
+ switch (boot_cpu_data.x86) {
+ case 0xf:
+ /* feature available since SH-C0, exclude older revisions */
+ if (((model == 4) && (stepping == 0)) ||
+ ((model == 5) && (stepping <= 1))) {
+ err = -ENODEV;
+ goto exit_free;
+ }
+
+ /*
+ * AMD NPT family 0fh, i.e. RevF and RevG:
+ * meaning of SEL_CORE bit is inverted
+ */
+ if (model >= 0x40) {
+ data->swap_core_select = 1;
+ dev_warn(&pdev->dev, "Temperature readouts might be "
+ "wrong - check erratum #141\n");
+ }
+
+ if ((model >= 0x69) &&
+ !(model == 0xc1 || model == 0x6c || model == 0x7c)) {
+ /*
+ * RevG desktop CPUs (i.e. no socket S1G1 parts)
+ * need additional offset, otherwise reported
+ * temperature is below ambient temperature
+ */
+ data->temp_offset = 21000;
+ }
+
+ break;
+ }
+
pci_read_config_byte(pdev, REG_TEMP, &scfg);
scfg &= ~(SEL_PLACE | SEL_CORE); /* Select sensor 0, core0 */
pci_write_config_byte(pdev, REG_TEMP, scfg);
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 59c3d23..b9bef04 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -139,15 +139,4 @@ config SENSORS_TSL2550
This driver can also be built as a module. If so, the module
will be called tsl2550.
-config MCU_MPC8349EMITX
- tristate "MPC8349E-mITX MCU driver"
- depends on I2C && PPC_83xx
- select GENERIC_GPIO
- select ARCH_REQUIRE_GPIOLIB
- help
- Say Y here to enable soft power-off functionality on the Freescale
- boards with the MPC8349E-mITX-compatible MCU chips. This driver will
- also register MCU GPIOs with the generic GPIO API, so you'll able
- to use MCU pins as GPIOs.
-
endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 83accaa..00fcb51 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -19,7 +19,6 @@ obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
obj-$(CONFIG_PCF8575) += pcf8575.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
-obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o
ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/chips/mcu_mpc8349emitx.c b/drivers/i2c/chips/mcu_mpc8349emitx.c
deleted file mode 100644
index 82a9bcb..0000000
--- a/drivers/i2c/chips/mcu_mpc8349emitx.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Power Management and GPIO expander driver for MPC8349E-mITX-compatible MCU
- *
- * Copyright (c) 2008 MontaVista Software, Inc.
- *
- * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/mutex.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/of.h>
-#include <linux/of_gpio.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
-
-/*
- * I don't have specifications for the MCU firmware, I found this register
- * and bits positions by the trial&error method.
- */
-#define MCU_REG_CTRL 0x20
-#define MCU_CTRL_POFF 0x40
-
-#define MCU_NUM_GPIO 2
-
-struct mcu {
- struct mutex lock;
- struct device_node *np;
- struct i2c_client *client;
- struct of_gpio_chip of_gc;
- u8 reg_ctrl;
-};
-
-static struct mcu *glob_mcu;
-
-static void mcu_power_off(void)
-{
- struct mcu *mcu = glob_mcu;
-
- pr_info("Sending power-off request to the MCU...\n");
- mutex_lock(&mcu->lock);
- i2c_smbus_write_byte_data(glob_mcu->client, MCU_REG_CTRL,
- mcu->reg_ctrl | MCU_CTRL_POFF);
- mutex_unlock(&mcu->lock);
-}
-
-static void mcu_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
- struct of_gpio_chip *of_gc = to_of_gpio_chip(gc);
- struct mcu *mcu = container_of(of_gc, struct mcu, of_gc);
- u8 bit = 1 << (4 + gpio);
-
- mutex_lock(&mcu->lock);
- if (val)
- mcu->reg_ctrl &= ~bit;
- else
- mcu->reg_ctrl |= bit;
-
- i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL, mcu->reg_ctrl);
- mutex_unlock(&mcu->lock);
-}
-
-static int mcu_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
-{
- mcu_gpio_set(gc, gpio, val);
- return 0;
-}
-
-static int mcu_gpiochip_add(struct mcu *mcu)
-{
- struct device_node *np;
- struct of_gpio_chip *of_gc = &mcu->of_gc;
- struct gpio_chip *gc = &of_gc->gc;
- int ret;
-
- np = of_find_compatible_node(NULL, NULL, "fsl,mcu-mpc8349emitx");
- if (!np)
- return -ENODEV;
-
- gc->owner = THIS_MODULE;
- gc->label = np->full_name;
- gc->can_sleep = 1;
- gc->ngpio = MCU_NUM_GPIO;
- gc->base = -1;
- gc->set = mcu_gpio_set;
- gc->direction_output = mcu_gpio_dir_out;
- of_gc->gpio_cells = 2;
- of_gc->xlate = of_gpio_simple_xlate;
-
- np->data = of_gc;
- mcu->np = np;
-
- /*
- * We don't want to lose the node, its ->data and ->full_name...
- * So, if succeeded, we don't put the node here.
- */
- ret = gpiochip_add(gc);
- if (ret)
- of_node_put(np);
- return ret;
-}
-
-static int mcu_gpiochip_remove(struct mcu *mcu)
-{
- int ret;
-
- ret = gpiochip_remove(&mcu->of_gc.gc);
- if (ret)
- return ret;
- of_node_put(mcu->np);
-
- return 0;
-}
-
-static int __devinit mcu_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct mcu *mcu;
- int ret;
-
- mcu = kzalloc(sizeof(*mcu), GFP_KERNEL);
- if (!mcu)
- return -ENOMEM;
-
- mutex_init(&mcu->lock);
- mcu->client = client;
- i2c_set_clientdata(client, mcu);
-
- ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL);
- if (ret < 0)
- goto err;
- mcu->reg_ctrl = ret;
-
- ret = mcu_gpiochip_add(mcu);
- if (ret)
- goto err;
-
- /* XXX: this is potentially racy, but there is no lock for ppc_md */
- if (!ppc_md.power_off) {
- glob_mcu = mcu;
- ppc_md.power_off = mcu_power_off;
- dev_info(&client->dev, "will provide power-off service\n");
- }
-
- return 0;
-err:
- kfree(mcu);
- return ret;
-}
-
-static int __devexit mcu_remove(struct i2c_client *client)
-{
- struct mcu *mcu = i2c_get_clientdata(client);
- int ret;
-
- if (glob_mcu == mcu) {
- ppc_md.power_off = NULL;
- glob_mcu = NULL;
- }
-
- ret = mcu_gpiochip_remove(mcu);
- if (ret)
- return ret;
- i2c_set_clientdata(client, NULL);
- kfree(mcu);
- return 0;
-}
-
-static const struct i2c_device_id mcu_ids[] = {
- { "mcu-mpc8349emitx", },
- {},
-};
-MODULE_DEVICE_TABLE(i2c, mcu_ids);
-
-static struct i2c_driver mcu_driver = {
- .driver = {
- .name = "mcu-mpc8349emitx",
- .owner = THIS_MODULE,
- },
- .probe = mcu_probe,
- .remove = __devexit_p(mcu_remove),
- .id_table = mcu_ids,
-};
-
-static int __init mcu_init(void)
-{
- return i2c_add_driver(&mcu_driver);
-}
-module_init(mcu_init);
-
-static void __exit mcu_exit(void)
-{
- i2c_del_driver(&mcu_driver);
-}
-module_exit(mcu_exit);
-
-MODULE_DESCRIPTION("Power Management and GPIO expander driver for "
- "MPC8349E-mITX-compatible MCU");
-MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 3f95038..b1c6f68 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -701,11 +701,6 @@ config BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
depends on SOC_AU1200 && BLK_DEV_IDE_AU1XXX
endchoice
-config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ
- int "Maximum transfer size (KB) per request (up to 128)"
- default "128"
- depends on BLK_DEV_IDE_AU1XXX
-
config BLK_DEV_IDE_TX4938
tristate "TX4938 internal IDE support"
depends on SOC_TX4938
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 4088a62..806760d 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -633,7 +633,7 @@ static void ide_disk_setup(ide_drive_t *drive)
printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name,
q->max_sectors / 2);
- if (ata_id_is_ssd(id) || ata_id_is_cfa(id))
+ if (ata_id_is_ssd(id))
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
/* calculate drive capacity, and select LBA if possible */
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index e728cfe..753b92e 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -493,7 +493,7 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti
stat = tp_ops->read_status(hwif);
if (stat & ATA_BUSY) {
- local_irq_save(flags);
+ local_save_flags(flags);
local_irq_enable_in_hardirq();
timeout += jiffies;
while ((stat = tp_ops->read_status(hwif)) & ATA_BUSY) {
diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c
index 4b3bf6a..60538d9 100644
--- a/drivers/ide/ide-pm.c
+++ b/drivers/ide/ide-pm.c
@@ -186,12 +186,10 @@ void ide_complete_pm_request(ide_drive_t *drive, struct request *rq)
blk_pm_suspend_request(rq) ? "suspend" : "resume");
#endif
spin_lock_irqsave(q->queue_lock, flags);
- if (blk_pm_suspend_request(rq)) {
+ if (blk_pm_suspend_request(rq))
blk_stop_queue(q);
- } else {
+ else
drive->dev_flags &= ~IDE_DFLAG_BLOCKED;
- blk_start_queue(q);
- }
spin_unlock_irqrestore(q->queue_lock, flags);
drive->hwif->rq = NULL;
@@ -219,6 +217,8 @@ void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
* point.
*/
ide_hwif_t *hwif = drive->hwif;
+ struct request_queue *q = drive->queue;
+ unsigned long flags;
int rc;
#ifdef DEBUG_PM
printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name);
@@ -231,5 +231,9 @@ void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
rc = ide_wait_not_busy(hwif, 100000);
if (rc)
printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ blk_start_queue(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
}
}
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 0ccbb44..312127e 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -796,7 +796,7 @@ static int ide_probe_port(ide_hwif_t *hwif)
if (irqd)
disable_irq(hwif->irq);
- local_irq_save(flags);
+ local_save_flags(flags);
local_irq_enable_in_hardirq();
if (ide_port_wait_ready(hwif) == -EBUSY)
diff --git a/drivers/ide/it821x.c b/drivers/ide/it821x.c
index 0be27ac..e1c4f54 100644
--- a/drivers/ide/it821x.c
+++ b/drivers/ide/it821x.c
@@ -68,6 +68,8 @@
#define DRV_NAME "it821x"
+#define QUIRK_VORTEX86 1
+
struct it821x_dev
{
unsigned int smart:1, /* Are we in smart raid mode */
@@ -79,6 +81,7 @@ struct it821x_dev
u16 pio[2]; /* Cached PIO values */
u16 mwdma[2]; /* Cached MWDMA values */
u16 udma[2]; /* Cached UDMA values (per drive) */
+ u16 quirks;
};
#define ATA_66 0
@@ -557,8 +560,7 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
* this is necessary.
*/
- pci_read_config_byte(dev, 0x08, &conf);
- if (conf == 0x10) {
+ if (dev->revision == 0x10) {
idev->timing10 = 1;
hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
if (idev->smart == 0)
@@ -577,6 +579,12 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
hwif->ultra_mask = ATA_UDMA6;
hwif->mwdma_mask = ATA_MWDMA2;
+
+ /* Vortex86SX quirk: prevent Ultra-DMA mode to fix BadCRC issue */
+ if (idev->quirks & QUIRK_VORTEX86) {
+ if (dev->revision == 0x11)
+ hwif->ultra_mask = 0;
+ }
}
static void it8212_disable_raid(struct pci_dev *dev)
@@ -649,6 +657,8 @@ static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_devic
return -ENOMEM;
}
+ itdevs->quirks = id->driver_data;
+
rc = ide_pci_init_one(dev, &it821x_chipset, itdevs);
if (rc)
kfree(itdevs);
@@ -668,6 +678,7 @@ static void __devexit it821x_remove(struct pci_dev *dev)
static const struct pci_device_id it821x_pci_tbl[] = {
{ PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8211), 0 },
{ PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8212), 0 },
+ { PCI_VDEVICE(RDC, PCI_DEVICE_ID_RDC_D1010), QUIRK_VORTEX86 },
{ 0, },
};
diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c
index 48cc748..6297956 100644
--- a/drivers/ide/sl82c105.c
+++ b/drivers/ide/sl82c105.c
@@ -310,10 +310,6 @@ static const struct ide_port_info sl82c105_chipset __devinitdata = {
.dma_ops = &sl82c105_dma_ops,
.host_flags = IDE_HFLAG_IO_32BIT |
IDE_HFLAG_UNMASK_IRQS |
-/* FIXME: check for Compatibility mode in generic IDE PCI code */
-#if defined(CONFIG_LOPEC) || defined(CONFIG_SANDPOINT)
- IDE_HFLAG_FORCE_LEGACY_IRQS |
-#endif
IDE_HFLAG_SERIALIZE_DMA |
IDE_HFLAG_NO_AUTODMA,
.pio_mask = ATA_PIO5,
diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c
index b4ef218..d909534 100644
--- a/drivers/ide/tx4938ide.c
+++ b/drivers/ide/tx4938ide.c
@@ -202,7 +202,6 @@ static const struct ide_tp_ops tx4938ide_tp_ops = {
.exec_command = ide_exec_command,
.read_status = ide_read_status,
.read_altstatus = ide_read_altstatus,
- .read_sff_dma_status = ide_read_sff_dma_status,
.set_irq = ide_set_irq,
diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c
index fecc0e0..703c3ee 100644
--- a/drivers/ide/via82cxxx.c
+++ b/drivers/ide/via82cxxx.c
@@ -432,8 +432,6 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i
if (via_clock < 20000 || via_clock > 50000) {
printk(KERN_WARNING DRV_NAME ": User given PCI clock speed "
"impossible (%d), using 33 MHz instead.\n", via_clock);
- printk(KERN_WARNING DRV_NAME ": Use ide0=ata66 if you want "
- "to assume 80-wire cable.\n");
via_clock = 33333;
}
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index 3b77b67..c7b8a50 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -955,7 +955,7 @@ void ehca_poll_eqs(unsigned long data)
struct ehca_eq *eq = &shca->eq;
int max = 3;
volatile u64 q_ofs, q_ofs2;
- u64 flags;
+ unsigned long flags;
spin_lock_irqsave(&eq->spinlock, flags);
q_ofs = eq->ipz_queue.current_q_offset;
spin_unlock_irqrestore(&eq->spinlock, flags);
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index dcefe1f..61588bd 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -543,14 +543,21 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
{
static int mlx4_ib_version_printed;
struct mlx4_ib_dev *ibdev;
+ int num_ports = 0;
int i;
-
if (!mlx4_ib_version_printed) {
printk(KERN_INFO "%s", mlx4_ib_version);
++mlx4_ib_version_printed;
}
+ mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB)
+ num_ports++;
+
+ /* No point in registering a device with no ports... */
+ if (num_ports == 0)
+ return NULL;
+
ibdev = (struct mlx4_ib_dev *) ib_alloc_device(sizeof *ibdev);
if (!ibdev) {
dev_err(&dev->pdev->dev, "Device struct alloc failed\n");
@@ -574,9 +581,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
ibdev->ib_dev.owner = THIS_MODULE;
ibdev->ib_dev.node_type = RDMA_NODE_IB_CA;
ibdev->ib_dev.local_dma_lkey = dev->caps.reserved_lkey;
- ibdev->num_ports = 0;
- mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB)
- ibdev->num_ports++;
+ ibdev->num_ports = num_ports;
ibdev->ib_dev.phys_port_cnt = ibdev->num_ports;
ibdev->ib_dev.num_comp_vectors = dev->caps.num_comp_vectors;
ibdev->ib_dev.dma_device = &dev->pdev->dev;
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index 6ba57e9..a01b448 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -778,12 +778,13 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
unsigned long flags;
struct list_head *hte;
struct nes_cm_node *cm_node;
+ __be32 tmp_addr = cpu_to_be32(loc_addr);
/* get a handle on the hte */
hte = &cm_core->connected_nodes;
nes_debug(NES_DBG_CM, "Searching for an owner node: %pI4:%x from core %p->%p\n",
- &loc_addr, loc_port, cm_core, hte);
+ &tmp_addr, loc_port, cm_core, hte);
/* walk list and find cm_node associated with this session ID */
spin_lock_irqsave(&cm_core->ht_lock, flags);
@@ -816,6 +817,7 @@ static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core,
{
unsigned long flags;
struct nes_cm_listener *listen_node;
+ __be32 tmp_addr = cpu_to_be32(dst_addr);
/* walk list and find cm_node associated with this session ID */
spin_lock_irqsave(&cm_core->listen_list_lock, flags);
@@ -833,7 +835,7 @@ static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core,
spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
nes_debug(NES_DBG_CM, "Unable to find listener for %pI4:%x\n",
- &dst_addr, dst_port);
+ &tmp_addr, dst_port);
/* no listener */
return NULL;
@@ -2059,6 +2061,7 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
struct tcphdr *tcph;
struct nes_cm_info nfo;
int skb_handled = 1;
+ __be32 tmp_daddr, tmp_saddr;
if (!skb)
return 0;
@@ -2074,8 +2077,11 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
nfo.rem_addr = ntohl(iph->saddr);
nfo.rem_port = ntohs(tcph->source);
+ tmp_daddr = cpu_to_be32(iph->daddr);
+ tmp_saddr = cpu_to_be32(iph->saddr);
+
nes_debug(NES_DBG_CM, "Received packet: dest=%pI4:0x%04X src=%pI4:0x%04X\n",
- &iph->daddr, tcph->dest, &iph->saddr, tcph->source);
+ &tmp_daddr, tcph->dest, &tmp_saddr, tcph->source);
do {
cm_node = find_node(cm_core,
diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c
index aa9b734..6f3bc1b 100644
--- a/drivers/infiniband/hw/nes/nes_utils.c
+++ b/drivers/infiniband/hw/nes/nes_utils.c
@@ -655,6 +655,7 @@ int nes_arp_table(struct nes_device *nesdev, u32 ip_addr, u8 *mac_addr, u32 acti
struct nes_adapter *nesadapter = nesdev->nesadapter;
int arp_index;
int err = 0;
+ __be32 tmp_addr;
for (arp_index = 0; (u32) arp_index < nesadapter->arp_table_size; arp_index++) {
if (nesadapter->arp_table[arp_index].ip_addr == ip_addr)
@@ -682,8 +683,9 @@ int nes_arp_table(struct nes_device *nesdev, u32 ip_addr, u8 *mac_addr, u32 acti
/* DELETE or RESOLVE */
if (arp_index == nesadapter->arp_table_size) {
+ tmp_addr = cpu_to_be32(ip_addr);
nes_debug(NES_DBG_NETDEV, "MAC for %pI4 not in ARP table - cannot %s\n",
- &ip_addr, action == NES_ARP_RESOLVE ? "resolve" : "delete");
+ &tmp_addr, action == NES_ARP_RESOLVE ? "resolve" : "delete");
return -1;
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 19e06bc..dce0443 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -711,26 +711,26 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
neigh = *to_ipoib_neigh(skb->dst->neighbour);
- if (neigh->ah)
- if (unlikely((memcmp(&neigh->dgid.raw,
- skb->dst->neighbour->ha + 4,
- sizeof(union ib_gid))) ||
- (neigh->dev != dev))) {
- spin_lock_irqsave(&priv->lock, flags);
- /*
- * It's safe to call ipoib_put_ah() inside
- * priv->lock here, because we know that
- * path->ah will always hold one more reference,
- * so ipoib_put_ah() will never do more than
- * decrement the ref count.
- */
+ if (unlikely((memcmp(&neigh->dgid.raw,
+ skb->dst->neighbour->ha + 4,
+ sizeof(union ib_gid))) ||
+ (neigh->dev != dev))) {
+ spin_lock_irqsave(&priv->lock, flags);
+ /*
+ * It's safe to call ipoib_put_ah() inside
+ * priv->lock here, because we know that
+ * path->ah will always hold one more reference,
+ * so ipoib_put_ah() will never do more than
+ * decrement the ref count.
+ */
+ if (neigh->ah)
ipoib_put_ah(neigh->ah);
- list_del(&neigh->list);
- ipoib_neigh_free(dev, neigh);
- spin_unlock_irqrestore(&priv->lock, flags);
- ipoib_path_lookup(skb, dev);
- return NETDEV_TX_OK;
- }
+ list_del(&neigh->list);
+ ipoib_neigh_free(dev, neigh);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ ipoib_path_lookup(skb, dev);
+ return NETDEV_TX_OK;
+ }
if (ipoib_cm_get(neigh)) {
if (ipoib_cm_up(neigh)) {
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index a2eb3b9..59d02e0b 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -529,6 +529,9 @@ void ipoib_mcast_join_task(struct work_struct *work)
if (!priv->broadcast) {
struct ipoib_mcast *broadcast;
+ if (!test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
+ return;
+
broadcast = ipoib_mcast_alloc(dev, 1);
if (!broadcast) {
ipoib_warn(priv, "failed to allocate broadcast group\n");
diff --git a/drivers/infiniband/ulp/iser/Kconfig b/drivers/infiniband/ulp/iser/Kconfig
index 77dedba..b411c51 100644
--- a/drivers/infiniband/ulp/iser/Kconfig
+++ b/drivers/infiniband/ulp/iser/Kconfig
@@ -1,6 +1,6 @@
config INFINIBAND_ISER
tristate "iSCSI Extensions for RDMA (iSER)"
- depends on SCSI && INET
+ depends on SCSI && INET && INFINIBAND_ADDR_TRANS
select SCSI_ISCSI_ATTRS
---help---
Support for the iSCSI Extensions for RDMA (iSER) Protocol
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 199055d..67e5553 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -220,4 +220,11 @@ config HP_SDC_RTC
Say Y here if you want to support the built-in real time clock
of the HP SDC controller.
+config INPUT_PCF50633_PMU
+ tristate "PCF50633 PMU events"
+ depends on MFD_PCF50633
+ help
+ Say Y to include support for delivering PMU events via input
+ layer on NXP PCF50633.
+
endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index d7db2ae..bb62e6e 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -21,3 +21,4 @@ obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
obj-$(CONFIG_INPUT_APANEL) += apanel.o
obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
+obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o
diff --git a/drivers/input/misc/pcf50633-input.c b/drivers/input/misc/pcf50633-input.c
new file mode 100644
index 0000000..039dcb0
--- /dev/null
+++ b/drivers/input/misc/pcf50633-input.c
@@ -0,0 +1,132 @@
+/* NXP PCF50633 Input Driver
+ *
+ * (C) 2006-2008 by Openmoko, Inc.
+ * Author: Balaji Rao <balajirrao@openmoko.org>
+ * All rights reserved.
+ *
+ * Broken down from monstrous PCF50633 driver mainly by
+ * Harald Welte, Andy Green and Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+
+#include <linux/mfd/pcf50633/core.h>
+
+#define PCF50633_OOCSTAT_ONKEY 0x01
+#define PCF50633_REG_OOCSTAT 0x12
+#define PCF50633_REG_OOCMODE 0x10
+
+struct pcf50633_input {
+ struct pcf50633 *pcf;
+ struct input_dev *input_dev;
+};
+
+static void
+pcf50633_input_irq(int irq, void *data)
+{
+ struct pcf50633_input *input;
+ int onkey_released;
+
+ input = data;
+
+ /* We report only one event depending on the key press status */
+ onkey_released = pcf50633_reg_read(input->pcf, PCF50633_REG_OOCSTAT)
+ & PCF50633_OOCSTAT_ONKEY;
+
+ if (irq == PCF50633_IRQ_ONKEYF && !onkey_released)
+ input_report_key(input->input_dev, KEY_POWER, 1);
+ else if (irq == PCF50633_IRQ_ONKEYR && onkey_released)
+ input_report_key(input->input_dev, KEY_POWER, 0);
+
+ input_sync(input->input_dev);
+}
+
+static int __devinit pcf50633_input_probe(struct platform_device *pdev)
+{
+ struct pcf50633_input *input;
+ struct pcf50633_subdev_pdata *pdata = pdev->dev.platform_data;
+ struct input_dev *input_dev;
+ int ret;
+
+
+ input = kzalloc(sizeof(*input), GFP_KERNEL);
+ if (!input)
+ return -ENOMEM;
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ kfree(input);
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(pdev, input);
+ input->pcf = pdata->pcf;
+ input->input_dev = input_dev;
+
+ input_dev->name = "PCF50633 PMU events";
+ input_dev->id.bustype = BUS_I2C;
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_PWR);
+ set_bit(KEY_POWER, input_dev->keybit);
+
+ ret = input_register_device(input_dev);
+ if (ret) {
+ input_free_device(input_dev);
+ kfree(input);
+ return ret;
+ }
+ pcf50633_register_irq(pdata->pcf, PCF50633_IRQ_ONKEYR,
+ pcf50633_input_irq, input);
+ pcf50633_register_irq(pdata->pcf, PCF50633_IRQ_ONKEYF,
+ pcf50633_input_irq, input);
+
+ return 0;
+}
+
+static int __devexit pcf50633_input_remove(struct platform_device *pdev)
+{
+ struct pcf50633_input *input = platform_get_drvdata(pdev);
+
+ pcf50633_free_irq(input->pcf, PCF50633_IRQ_ONKEYR);
+ pcf50633_free_irq(input->pcf, PCF50633_IRQ_ONKEYF);
+
+ input_unregister_device(input->input_dev);
+ kfree(input);
+
+ return 0;
+}
+
+static struct platform_driver pcf50633_input_driver = {
+ .driver = {
+ .name = "pcf50633-input",
+ },
+ .probe = pcf50633_input_probe,
+ .remove = __devexit_p(pcf50633_input_remove),
+};
+
+static int __init pcf50633_input_init(void)
+{
+ return platform_driver_register(&pcf50633_input_driver);
+}
+module_init(pcf50633_input_init);
+
+static void __exit pcf50633_input_exit(void)
+{
+ platform_driver_unregister(&pcf50633_input_driver);
+}
+module_exit(pcf50633_input_exit);
+
+MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
+MODULE_DESCRIPTION("PCF50633 input driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pcf50633-input");
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index 97f4708..595ba8e 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -3615,7 +3615,7 @@ hfcm_bctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
static void
ph_state_change(struct dchannel *dch)
{
- struct hfc_multi *hc = dch->hw;
+ struct hfc_multi *hc;
int ch, i;
if (!dch) {
@@ -3623,6 +3623,7 @@ ph_state_change(struct dchannel *dch)
__func__);
return;
}
+ hc = dch->hw;
ch = dch->slot;
if (hc->type == 1) {
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index 917bf41..f0e14df 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -61,7 +61,7 @@ u32 hfc_jiffies;
MODULE_AUTHOR("Karsten Keil");
MODULE_LICENSE("GPL");
-module_param(debug, uint, 0);
+module_param(debug, uint, S_IRUGO | S_IWUSR);
module_param(poll, uint, S_IRUGO | S_IWUSR);
enum {
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index 7c5f970..cb8943d 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -292,7 +292,9 @@ isdn_net_unbind_channel(isdn_net_local * lp)
lp->dialstate = 0;
dev->rx_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
dev->st_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
- isdn_free_channel(lp->isdn_device, lp->isdn_channel, ISDN_USAGE_NET);
+ if (lp->isdn_device != -1 && lp->isdn_channel != -1)
+ isdn_free_channel(lp->isdn_device, lp->isdn_channel,
+ ISDN_USAGE_NET);
lp->flags &= ~ISDN_NET_CONNECTED;
lp->isdn_device = -1;
lp->isdn_channel = -1;
@@ -2513,7 +2515,6 @@ static const struct net_device_ops isdn_netdev_ops = {
.ndo_stop = isdn_net_close,
.ndo_do_ioctl = isdn_net_ioctl,
- .ndo_validate_addr = NULL,
.ndo_start_xmit = isdn_net_start_xmit,
.ndo_get_stats = isdn_net_get_stats,
.ndo_tx_timeout = isdn_net_tx_timeout,
@@ -2528,12 +2529,8 @@ static void _isdn_setup(struct net_device *dev)
ether_setup(dev);
- dev->flags = IFF_NOARP | IFF_POINTOPOINT;
/* Setup the generic properties */
- dev->mtu = 1500;
dev->flags = IFF_NOARP|IFF_POINTOPOINT;
- dev->type = ARPHRD_ETHER;
- dev->addr_len = ETH_ALEN;
dev->header_ops = NULL;
dev->netdev_ops = &isdn_netdev_ops;
diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c
index 0ac67bf..58c43e4 100644
--- a/drivers/isdn/mISDN/dsp_cmx.c
+++ b/drivers/isdn/mISDN/dsp_cmx.c
@@ -1579,7 +1579,7 @@ send_packet:
schedule_work(&dsp->workq);
}
-static u32 jittercount; /* counter for jitter check */;
+static u32 jittercount; /* counter for jitter check */
struct timer_list dsp_spl_tl;
u32 dsp_spl_jiffies; /* calculate the next time to fire */
static u16 dsp_count; /* last sample count */
@@ -1893,7 +1893,7 @@ dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb)
/* in case of hardware (echo) */
if (dsp->pcm_slot_tx >= 0)
return;
- if (dsp->echo)
+ if (dsp->echo) {
nskb = skb_clone(skb, GFP_ATOMIC);
if (nskb) {
hh = mISDN_HEAD_P(nskb);
@@ -1902,6 +1902,7 @@ dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb)
skb_queue_tail(&dsp->sendq, nskb);
schedule_work(&dsp->workq);
}
+ }
return;
}
/* in case of hardware conference */
diff --git a/drivers/isdn/mISDN/dsp_pipeline.c b/drivers/isdn/mISDN/dsp_pipeline.c
index bf999bd..18cf87c 100644
--- a/drivers/isdn/mISDN/dsp_pipeline.c
+++ b/drivers/isdn/mISDN/dsp_pipeline.c
@@ -110,8 +110,7 @@ int mISDN_dsp_element_register(struct mISDN_dsp_element *elem)
}
list_add_tail(&entry->list, &dsp_elements);
- for (i = 0; i < (sizeof(element_attributes)
- / sizeof(struct device_attribute)); ++i)
+ for (i = 0; i < ARRAY_SIZE(element_attributes); ++i) {
ret = device_create_file(&entry->dev,
&element_attributes[i]);
if (ret) {
@@ -119,6 +118,7 @@ int mISDN_dsp_element_register(struct mISDN_dsp_element *elem)
__func__);
goto err2;
}
+ }
#ifdef PIPELINE_DEBUG
printk(KERN_DEBUG "%s: %s registered\n", __func__, elem->name);
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index a4a1ae2..7427136 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -119,13 +119,6 @@ config LEDS_GPIO
outputs. To be useful the particular board must have LEDs
and they must be connected to the GPIO lines.
-config LEDS_HP_DISK
- tristate "LED Support for disk protection LED on HP notebooks"
- depends on LEDS_CLASS && ACPI
- help
- This option enable support for disk protection LED, found on
- newer HP notebooks.
-
config LEDS_CLEVO_MAIL
tristate "Mail LED on Clevo notebook (EXPERIMENTAL)"
depends on LEDS_CLASS && X86 && SERIO_I8042 && DMI && EXPERIMENTAL
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index bc247cb..9d76f0f 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -23,7 +23,6 @@ obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o
obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o
-obj-$(CONFIG_LEDS_HP_DISK) += leds-hp-disk.o
obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o
# LED Triggers
diff --git a/drivers/leds/leds-hp-disk.c b/drivers/leds/leds-hp-disk.c
deleted file mode 100644
index d786adc..0000000
--- a/drivers/leds/leds-hp-disk.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * leds-hp-disk.c - driver for HP "hard disk protection" LED
- *
- * Copyright (C) 2008 Pavel Machek
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/dmi.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/input.h>
-#include <linux/kthread.h>
-#include <linux/leds.h>
-#include <acpi/acpi_drivers.h>
-
-#define DRIVER_NAME "leds-hp-disk"
-#define ACPI_MDPS_CLASS "led"
-
-/* For automatic insertion of the module */
-static struct acpi_device_id hpled_device_ids[] = {
- {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */
- {"", 0},
-};
-MODULE_DEVICE_TABLE(acpi, hpled_device_ids);
-
-struct acpi_hpled {
- struct acpi_device *device; /* The ACPI device */
-};
-
-static struct acpi_hpled adev;
-
-static acpi_status hpled_acpi_write(acpi_handle handle, int reg)
-{
- unsigned long long ret; /* Not used when writing */
- union acpi_object in_obj[1];
- struct acpi_object_list args = { 1, in_obj };
-
- in_obj[0].type = ACPI_TYPE_INTEGER;
- in_obj[0].integer.value = reg;
-
- return acpi_evaluate_integer(handle, "ALED", &args, &ret);
-}
-
-static void hpled_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- hpled_acpi_write(adev.device->handle, !!value);
-}
-
-static struct led_classdev hpled_led = {
- .name = "hp:red:hddprotection",
- .default_trigger = "heartbeat",
- .brightness_set = hpled_set,
- .flags = LED_CORE_SUSPENDRESUME,
-};
-
-static int hpled_add(struct acpi_device *device)
-{
- int ret;
-
- if (!device)
- return -EINVAL;
-
- adev.device = device;
- strcpy(acpi_device_name(device), DRIVER_NAME);
- strcpy(acpi_device_class(device), ACPI_MDPS_CLASS);
- device->driver_data = &adev;
-
- ret = led_classdev_register(NULL, &hpled_led);
- return ret;
-}
-
-static int hpled_remove(struct acpi_device *device, int type)
-{
- if (!device)
- return -EINVAL;
-
- led_classdev_unregister(&hpled_led);
- return 0;
-}
-
-
-
-static struct acpi_driver leds_hp_driver = {
- .name = DRIVER_NAME,
- .class = ACPI_MDPS_CLASS,
- .ids = hpled_device_ids,
- .ops = {
- .add = hpled_add,
- .remove = hpled_remove,
- }
-};
-
-static int __init hpled_init_module(void)
-{
- int ret;
-
- if (acpi_disabled)
- return -ENODEV;
-
- ret = acpi_bus_register_driver(&leds_hp_driver);
- if (ret < 0)
- return ret;
-
- printk(KERN_INFO DRIVER_NAME " driver loaded.\n");
-
- return 0;
-}
-
-static void __exit hpled_exit_module(void)
-{
- acpi_bus_unregister_driver(&leds_hp_driver);
-}
-
-MODULE_DESCRIPTION("Driver for HP disk protection LED");
-MODULE_AUTHOR("Pavel Machek <pavel@suse.cz>");
-MODULE_LICENSE("GPL");
-
-module_init(hpled_init_module);
-module_exit(hpled_exit_module);
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 416f9e7..06a2b0f 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -217,6 +217,29 @@ config MFD_WM8350_I2C
I2C as the control interface. Additional options must be
selected to enable support for the functionality of the chip.
+config MFD_PCF50633
+ tristate "Support for NXP PCF50633"
+ depends on I2C
+ help
+ Say yes here if you have NXP PCF50633 chip on your board.
+ This core driver provides register access and IRQ handling
+ facilities, and registers devices for the various functions
+ so that function-specific drivers can bind to them.
+
+config PCF50633_ADC
+ tristate "Support for NXP PCF50633 ADC"
+ depends on MFD_PCF50633
+ help
+ Say yes here if you want to include support for ADC in the
+ NXP PCF50633 chip.
+
+config PCF50633_GPIO
+ tristate "Support for NXP PCF50633 GPIO"
+ depends on MFD_PCF50633
+ help
+ Say yes here if you want to include support GPIO for pins on
+ the PCF50633 chip.
+
endmenu
menu "Multimedia Capabilities Port drivers"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 0c9418b..3afb519 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -37,3 +37,7 @@ endif
obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o
obj-$(CONFIG_PMIC_DA903X) += da903x.o
+
+obj-$(CONFIG_MFD_PCF50633) += pcf50633-core.o
+obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o
+obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o \ No newline at end of file
diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c
index 4214b3f..7ac12cb 100644
--- a/drivers/mfd/dm355evm_msp.c
+++ b/drivers/mfd/dm355evm_msp.c
@@ -107,6 +107,9 @@ static const u8 msp_gpios[] = {
MSP_GPIO(0, SWITCH1), MSP_GPIO(1, SWITCH1),
MSP_GPIO(2, SWITCH1), MSP_GPIO(3, SWITCH1),
MSP_GPIO(4, SWITCH1),
+ /* switches on MMC/SD sockets */
+ MSP_GPIO(1, SDMMC), MSP_GPIO(2, SDMMC), /* mmc0 WP, nCD */
+ MSP_GPIO(3, SDMMC), MSP_GPIO(4, SDMMC), /* mmc1 WP, nCD */
};
#define MSP_GPIO_REG(offset) (msp_gpios[(offset)] >> 3)
@@ -304,6 +307,13 @@ static int add_children(struct i2c_client *client)
gpio_export(gpio, false);
}
+ /* MMC/SD inputs -- right after the last config input */
+ if (client->dev.platform_data) {
+ void (*mmcsd_setup)(unsigned) = client->dev.platform_data;
+
+ mmcsd_setup(dm355evm_msp_gpio.base + 8 + 5);
+ }
+
/* RTC is a 32 bit counter, no alarm */
if (msp_has_rtc()) {
child = add_child(client, "rtc-dm355evm",
diff --git a/drivers/mfd/pcf50633-adc.c b/drivers/mfd/pcf50633-adc.c
new file mode 100644
index 0000000..c2d05be
--- /dev/null
+++ b/drivers/mfd/pcf50633-adc.c
@@ -0,0 +1,277 @@
+/* NXP PCF50633 ADC Driver
+ *
+ * (C) 2006-2008 by Openmoko, Inc.
+ * Author: Balaji Rao <balajirrao@openmoko.org>
+ * All rights reserved.
+ *
+ * Broken down from monstrous PCF50633 driver mainly by
+ * Harald Welte, Andy Green and Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * NOTE: This driver does not yet support subtractive ADC mode, which means
+ * you can do only one measurement per read request.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/completion.h>
+
+#include <linux/mfd/pcf50633/core.h>
+#include <linux/mfd/pcf50633/adc.h>
+
+struct pcf50633_adc_request {
+ int mux;
+ int avg;
+ int result;
+ void (*callback)(struct pcf50633 *, void *, int);
+ void *callback_param;
+
+ /* Used in case of sync requests */
+ struct completion completion;
+
+};
+
+#define PCF50633_MAX_ADC_FIFO_DEPTH 8
+
+struct pcf50633_adc {
+ struct pcf50633 *pcf;
+
+ /* Private stuff */
+ struct pcf50633_adc_request *queue[PCF50633_MAX_ADC_FIFO_DEPTH];
+ int queue_head;
+ int queue_tail;
+ struct mutex queue_mutex;
+};
+
+static inline struct pcf50633_adc *__to_adc(struct pcf50633 *pcf)
+{
+ return platform_get_drvdata(pcf->adc_pdev);
+}
+
+static void adc_setup(struct pcf50633 *pcf, int channel, int avg)
+{
+ channel &= PCF50633_ADCC1_ADCMUX_MASK;
+
+ /* kill ratiometric, but enable ACCSW biasing */
+ pcf50633_reg_write(pcf, PCF50633_REG_ADCC2, 0x00);
+ pcf50633_reg_write(pcf, PCF50633_REG_ADCC3, 0x01);
+
+ /* start ADC conversion on selected channel */
+ pcf50633_reg_write(pcf, PCF50633_REG_ADCC1, channel | avg |
+ PCF50633_ADCC1_ADCSTART | PCF50633_ADCC1_RES_10BIT);
+}
+
+static void trigger_next_adc_job_if_any(struct pcf50633 *pcf)
+{
+ struct pcf50633_adc *adc = __to_adc(pcf);
+ int head;
+
+ mutex_lock(&adc->queue_mutex);
+
+ head = adc->queue_head;
+
+ if (!adc->queue[head]) {
+ mutex_unlock(&adc->queue_mutex);
+ return;
+ }
+ mutex_unlock(&adc->queue_mutex);
+
+ adc_setup(pcf, adc->queue[head]->mux, adc->queue[head]->avg);
+}
+
+static int
+adc_enqueue_request(struct pcf50633 *pcf, struct pcf50633_adc_request *req)
+{
+ struct pcf50633_adc *adc = __to_adc(pcf);
+ int head, tail;
+
+ mutex_lock(&adc->queue_mutex);
+
+ head = adc->queue_head;
+ tail = adc->queue_tail;
+
+ if (adc->queue[tail]) {
+ mutex_unlock(&adc->queue_mutex);
+ return -EBUSY;
+ }
+
+ adc->queue[tail] = req;
+ adc->queue_tail = (tail + 1) & (PCF50633_MAX_ADC_FIFO_DEPTH - 1);
+
+ mutex_unlock(&adc->queue_mutex);
+
+ trigger_next_adc_job_if_any(pcf);
+
+ return 0;
+}
+
+static void
+pcf50633_adc_sync_read_callback(struct pcf50633 *pcf, void *param, int result)
+{
+ struct pcf50633_adc_request *req = param;
+
+ req->result = result;
+ complete(&req->completion);
+}
+
+int pcf50633_adc_sync_read(struct pcf50633 *pcf, int mux, int avg)
+{
+ struct pcf50633_adc_request *req;
+
+ /* req is freed when the result is ready, in interrupt handler */
+ req = kzalloc(sizeof(*req), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+
+ req->mux = mux;
+ req->avg = avg;
+ req->callback = pcf50633_adc_sync_read_callback;
+ req->callback_param = req;
+
+ init_completion(&req->completion);
+ adc_enqueue_request(pcf, req);
+ wait_for_completion(&req->completion);
+
+ return req->result;
+}
+EXPORT_SYMBOL_GPL(pcf50633_adc_sync_read);
+
+int pcf50633_adc_async_read(struct pcf50633 *pcf, int mux, int avg,
+ void (*callback)(struct pcf50633 *, void *, int),
+ void *callback_param)
+{
+ struct pcf50633_adc_request *req;
+
+ /* req is freed when the result is ready, in interrupt handler */
+ req = kmalloc(sizeof(*req), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+
+ req->mux = mux;
+ req->avg = avg;
+ req->callback = callback;
+ req->callback_param = callback_param;
+
+ adc_enqueue_request(pcf, req);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pcf50633_adc_async_read);
+
+static int adc_result(struct pcf50633 *pcf)
+{
+ u8 adcs1, adcs3;
+ u16 result;
+
+ adcs1 = pcf50633_reg_read(pcf, PCF50633_REG_ADCS1);
+ adcs3 = pcf50633_reg_read(pcf, PCF50633_REG_ADCS3);
+ result = (adcs1 << 2) | (adcs3 & PCF50633_ADCS3_ADCDAT1L_MASK);
+
+ dev_dbg(pcf->dev, "adc result = %d\n", result);
+
+ return result;
+}
+
+static void pcf50633_adc_irq(int irq, void *data)
+{
+ struct pcf50633_adc *adc = data;
+ struct pcf50633 *pcf = adc->pcf;
+ struct pcf50633_adc_request *req;
+ int head;
+
+ mutex_lock(&adc->queue_mutex);
+ head = adc->queue_head;
+
+ req = adc->queue[head];
+ if (WARN_ON(!req)) {
+ dev_err(pcf->dev, "pcf50633-adc irq: ADC queue empty!\n");
+ mutex_unlock(&adc->queue_mutex);
+ return;
+ }
+ adc->queue[head] = NULL;
+ adc->queue_head = (head + 1) &
+ (PCF50633_MAX_ADC_FIFO_DEPTH - 1);
+
+ mutex_unlock(&adc->queue_mutex);
+
+ req->callback(pcf, req->callback_param, adc_result(pcf));
+ kfree(req);
+
+ trigger_next_adc_job_if_any(pcf);
+}
+
+static int __devinit pcf50633_adc_probe(struct platform_device *pdev)
+{
+ struct pcf50633_subdev_pdata *pdata = pdev->dev.platform_data;
+ struct pcf50633_adc *adc;
+
+ adc = kzalloc(sizeof(*adc), GFP_KERNEL);
+ if (!adc)
+ return -ENOMEM;
+
+ adc->pcf = pdata->pcf;
+ platform_set_drvdata(pdev, adc);
+
+ pcf50633_register_irq(pdata->pcf, PCF50633_IRQ_ADCRDY,
+ pcf50633_adc_irq, adc);
+
+ mutex_init(&adc->queue_mutex);
+
+ return 0;
+}
+
+static int __devexit pcf50633_adc_remove(struct platform_device *pdev)
+{
+ struct pcf50633_adc *adc = platform_get_drvdata(pdev);
+ int i, head;
+
+ pcf50633_free_irq(adc->pcf, PCF50633_IRQ_ADCRDY);
+
+ mutex_lock(&adc->queue_mutex);
+ head = adc->queue_head;
+
+ if (WARN_ON(adc->queue[head]))
+ dev_err(adc->pcf->dev,
+ "adc driver removed with request pending\n");
+
+ for (i = 0; i < PCF50633_MAX_ADC_FIFO_DEPTH; i++)
+ kfree(adc->queue[i]);
+
+ mutex_unlock(&adc->queue_mutex);
+ kfree(adc);
+
+ return 0;
+}
+
+static struct platform_driver pcf50633_adc_driver = {
+ .driver = {
+ .name = "pcf50633-adc",
+ },
+ .probe = pcf50633_adc_probe,
+ .remove = __devexit_p(pcf50633_adc_remove),
+};
+
+static int __init pcf50633_adc_init(void)
+{
+ return platform_driver_register(&pcf50633_adc_driver);
+}
+module_init(pcf50633_adc_init);
+
+static void __exit pcf50633_adc_exit(void)
+{
+ platform_driver_unregister(&pcf50633_adc_driver);
+}
+module_exit(pcf50633_adc_exit);
+
+MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
+MODULE_DESCRIPTION("PCF50633 adc driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pcf50633-adc");
+
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
new file mode 100644
index 0000000..24508e2
--- /dev/null
+++ b/drivers/mfd/pcf50633-core.c
@@ -0,0 +1,710 @@
+/* NXP PCF50633 Power Management Unit (PMU) driver
+ *
+ * (C) 2006-2008 by Openmoko, Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ * Balaji Rao <balajirrao@openmoko.org>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/sysfs.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+
+#include <linux/mfd/pcf50633/core.h>
+
+/* Two MBCS registers used during cold start */
+#define PCF50633_REG_MBCS1 0x4b
+#define PCF50633_REG_MBCS2 0x4c
+#define PCF50633_MBCS1_USBPRES 0x01
+#define PCF50633_MBCS1_ADAPTPRES 0x01
+
+static int __pcf50633_read(struct pcf50633 *pcf, u8 reg, int num, u8 *data)
+{
+ int ret;
+
+ ret = i2c_smbus_read_i2c_block_data(pcf->i2c_client, reg,
+ num, data);
+ if (ret < 0)
+ dev_err(pcf->dev, "Error reading %d regs at %d\n", num, reg);
+
+ return ret;
+}
+
+static int __pcf50633_write(struct pcf50633 *pcf, u8 reg, int num, u8 *data)
+{
+ int ret;
+
+ ret = i2c_smbus_write_i2c_block_data(pcf->i2c_client, reg,
+ num, data);
+ if (ret < 0)
+ dev_err(pcf->dev, "Error writing %d regs at %d\n", num, reg);
+
+ return ret;
+
+}
+
+/* Read a block of upto 32 regs */
+int pcf50633_read_block(struct pcf50633 *pcf, u8 reg,
+ int nr_regs, u8 *data)
+{
+ int ret;
+
+ mutex_lock(&pcf->lock);
+ ret = __pcf50633_read(pcf, reg, nr_regs, data);
+ mutex_unlock(&pcf->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pcf50633_read_block);
+
+/* Write a block of upto 32 regs */
+int pcf50633_write_block(struct pcf50633 *pcf , u8 reg,
+ int nr_regs, u8 *data)
+{
+ int ret;
+
+ mutex_lock(&pcf->lock);
+ ret = __pcf50633_write(pcf, reg, nr_regs, data);
+ mutex_unlock(&pcf->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pcf50633_write_block);
+
+u8 pcf50633_reg_read(struct pcf50633 *pcf, u8 reg)
+{
+ u8 val;
+
+ mutex_lock(&pcf->lock);
+ __pcf50633_read(pcf, reg, 1, &val);
+ mutex_unlock(&pcf->lock);
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(pcf50633_reg_read);
+
+int pcf50633_reg_write(struct pcf50633 *pcf, u8 reg, u8 val)
+{
+ int ret;
+
+ mutex_lock(&pcf->lock);
+ ret = __pcf50633_write(pcf, reg, 1, &val);
+ mutex_unlock(&pcf->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pcf50633_reg_write);
+
+int pcf50633_reg_set_bit_mask(struct pcf50633 *pcf, u8 reg, u8 mask, u8 val)
+{
+ int ret;
+ u8 tmp;
+
+ val &= mask;
+
+ mutex_lock(&pcf->lock);
+ ret = __pcf50633_read(pcf, reg, 1, &tmp);
+ if (ret < 0)
+ goto out;
+
+ tmp &= ~mask;
+ tmp |= val;
+ ret = __pcf50633_write(pcf, reg, 1, &tmp);
+
+out:
+ mutex_unlock(&pcf->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pcf50633_reg_set_bit_mask);
+
+int pcf50633_reg_clear_bits(struct pcf50633 *pcf, u8 reg, u8 val)
+{
+ int ret;
+ u8 tmp;
+
+ mutex_lock(&pcf->lock);
+ ret = __pcf50633_read(pcf, reg, 1, &tmp);
+ if (ret < 0)
+ goto out;
+
+ tmp &= ~val;
+ ret = __pcf50633_write(pcf, reg, 1, &tmp);
+
+out:
+ mutex_unlock(&pcf->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pcf50633_reg_clear_bits);
+
+/* sysfs attributes */
+static ssize_t show_dump_regs(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct pcf50633 *pcf = dev_get_drvdata(dev);
+ u8 dump[16];
+ int n, n1, idx = 0;
+ char *buf1 = buf;
+ static u8 address_no_read[] = { /* must be ascending */
+ PCF50633_REG_INT1,
+ PCF50633_REG_INT2,
+ PCF50633_REG_INT3,
+ PCF50633_REG_INT4,
+ PCF50633_REG_INT5,
+ 0 /* terminator */
+ };
+
+ for (n = 0; n < 256; n += sizeof(dump)) {
+ for (n1 = 0; n1 < sizeof(dump); n1++)
+ if (n == address_no_read[idx]) {
+ idx++;
+ dump[n1] = 0x00;
+ } else
+ dump[n1] = pcf50633_reg_read(pcf, n + n1);
+
+ hex_dump_to_buffer(dump, sizeof(dump), 16, 1, buf1, 128, 0);
+ buf1 += strlen(buf1);
+ *buf1++ = '\n';
+ *buf1 = '\0';
+ }
+
+ return buf1 - buf;
+}
+static DEVICE_ATTR(dump_regs, 0400, show_dump_regs, NULL);
+
+static ssize_t show_resume_reason(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct pcf50633 *pcf = dev_get_drvdata(dev);
+ int n;
+
+ n = sprintf(buf, "%02x%02x%02x%02x%02x\n",
+ pcf->resume_reason[0],
+ pcf->resume_reason[1],
+ pcf->resume_reason[2],
+ pcf->resume_reason[3],
+ pcf->resume_reason[4]);
+
+ return n;
+}
+static DEVICE_ATTR(resume_reason, 0400, show_resume_reason, NULL);
+
+static struct attribute *pcf_sysfs_entries[] = {
+ &dev_attr_dump_regs.attr,
+ &dev_attr_resume_reason.attr,
+ NULL,
+};
+
+static struct attribute_group pcf_attr_group = {
+ .name = NULL, /* put in device directory */
+ .attrs = pcf_sysfs_entries,
+};
+
+int pcf50633_register_irq(struct pcf50633 *pcf, int irq,
+ void (*handler) (int, void *), void *data)
+{
+ if (irq < 0 || irq > PCF50633_NUM_IRQ || !handler)
+ return -EINVAL;
+
+ if (WARN_ON(pcf->irq_handler[irq].handler))
+ return -EBUSY;
+
+ mutex_lock(&pcf->lock);
+ pcf->irq_handler[irq].handler = handler;
+ pcf->irq_handler[irq].data = data;
+ mutex_unlock(&pcf->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pcf50633_register_irq);
+
+int pcf50633_free_irq(struct pcf50633 *pcf, int irq)
+{
+ if (irq < 0 || irq > PCF50633_NUM_IRQ)
+ return -EINVAL;
+
+ mutex_lock(&pcf->lock);
+ pcf->irq_handler[irq].handler = NULL;
+ mutex_unlock(&pcf->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pcf50633_free_irq);
+
+static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask)
+{
+ u8 reg, bits, tmp;
+ int ret = 0, idx;
+
+ idx = irq >> 3;
+ reg = PCF50633_REG_INT1M + idx;
+ bits = 1 << (irq & 0x07);
+
+ mutex_lock(&pcf->lock);
+
+ if (mask) {
+ ret = __pcf50633_read(pcf, reg, 1, &tmp);
+ if (ret < 0)
+ goto out;
+
+ tmp |= bits;
+
+ ret = __pcf50633_write(pcf, reg, 1, &tmp);
+ if (ret < 0)
+ goto out;
+
+ pcf->mask_regs[idx] &= ~bits;
+ pcf->mask_regs[idx] |= bits;
+ } else {
+ ret = __pcf50633_read(pcf, reg, 1, &tmp);
+ if (ret < 0)
+ goto out;
+
+ tmp &= ~bits;
+
+ ret = __pcf50633_write(pcf, reg, 1, &tmp);
+ if (ret < 0)
+ goto out;
+
+ pcf->mask_regs[idx] &= ~bits;
+ }
+out:
+ mutex_unlock(&pcf->lock);
+
+ return ret;
+}
+
+int pcf50633_irq_mask(struct pcf50633 *pcf, int irq)
+{
+ dev_info(pcf->dev, "Masking IRQ %d\n", irq);
+
+ return __pcf50633_irq_mask_set(pcf, irq, 1);
+}
+EXPORT_SYMBOL_GPL(pcf50633_irq_mask);
+
+int pcf50633_irq_unmask(struct pcf50633 *pcf, int irq)
+{
+ dev_info(pcf->dev, "Unmasking IRQ %d\n", irq);
+
+ return __pcf50633_irq_mask_set(pcf, irq, 0);
+}
+EXPORT_SYMBOL_GPL(pcf50633_irq_unmask);
+
+int pcf50633_irq_mask_get(struct pcf50633 *pcf, int irq)
+{
+ u8 reg, bits;
+
+ reg = irq >> 3;
+ bits = 1 << (irq & 0x07);
+
+ return pcf->mask_regs[reg] & bits;
+}
+EXPORT_SYMBOL_GPL(pcf50633_irq_mask_get);
+
+static void pcf50633_irq_call_handler(struct pcf50633 *pcf, int irq)
+{
+ if (pcf->irq_handler[irq].handler)
+ pcf->irq_handler[irq].handler(irq, pcf->irq_handler[irq].data);
+}
+
+/* Maximum amount of time ONKEY is held before emergency action is taken */
+#define PCF50633_ONKEY1S_TIMEOUT 8
+
+static void pcf50633_irq_worker(struct work_struct *work)
+{
+ struct pcf50633 *pcf;
+ int ret, i, j;
+ u8 pcf_int[5], chgstat;
+
+ pcf = container_of(work, struct pcf50633, irq_work);
+
+ /* Read the 5 INT regs in one transaction */
+ ret = pcf50633_read_block(pcf, PCF50633_REG_INT1,
+ ARRAY_SIZE(pcf_int), pcf_int);
+ if (ret != ARRAY_SIZE(pcf_int)) {
+ dev_err(pcf->dev, "Error reading INT registers\n");
+
+ /*
+ * If this doesn't ACK the interrupt to the chip, we'll be
+ * called once again as we're level triggered.
+ */
+ goto out;
+ }
+
+ /* We immediately read the usb and adapter status. We thus make sure
+ * only of USBINS/USBREM IRQ handlers are called */
+ if (pcf_int[0] & (PCF50633_INT1_USBINS | PCF50633_INT1_USBREM)) {
+ chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
+ if (chgstat & (0x3 << 4))
+ pcf_int[0] &= ~(1 << PCF50633_INT1_USBREM);
+ else
+ pcf_int[0] &= ~(1 << PCF50633_INT1_USBINS);
+ }
+
+ /* Make sure only one of ADPINS or ADPREM is set */
+ if (pcf_int[0] & (PCF50633_INT1_ADPINS | PCF50633_INT1_ADPREM)) {
+ chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
+ if (chgstat & (0x3 << 4))
+ pcf_int[0] &= ~(1 << PCF50633_INT1_ADPREM);
+ else
+ pcf_int[0] &= ~(1 << PCF50633_INT1_ADPINS);
+ }
+
+ dev_dbg(pcf->dev, "INT1=0x%02x INT2=0x%02x INT3=0x%02x "
+ "INT4=0x%02x INT5=0x%02x\n", pcf_int[0],
+ pcf_int[1], pcf_int[2], pcf_int[3], pcf_int[4]);
+
+ /* Some revisions of the chip don't have a 8s standby mode on
+ * ONKEY1S press. We try to manually do it in such cases. */
+ if ((pcf_int[0] & PCF50633_INT1_SECOND) && pcf->onkey1s_held) {
+ dev_info(pcf->dev, "ONKEY1S held for %d secs\n",
+ pcf->onkey1s_held);
+ if (pcf->onkey1s_held++ == PCF50633_ONKEY1S_TIMEOUT)
+ if (pcf->pdata->force_shutdown)
+ pcf->pdata->force_shutdown(pcf);
+ }
+
+ if (pcf_int[2] & PCF50633_INT3_ONKEY1S) {
+ dev_info(pcf->dev, "ONKEY1S held\n");
+ pcf->onkey1s_held = 1 ;
+
+ /* Unmask IRQ_SECOND */
+ pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT1M,
+ PCF50633_INT1_SECOND);
+
+ /* Unmask IRQ_ONKEYR */
+ pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT2M,
+ PCF50633_INT2_ONKEYR);
+ }
+
+ if ((pcf_int[1] & PCF50633_INT2_ONKEYR) && pcf->onkey1s_held) {
+ pcf->onkey1s_held = 0;
+
+ /* Mask SECOND and ONKEYR interrupts */
+ if (pcf->mask_regs[0] & PCF50633_INT1_SECOND)
+ pcf50633_reg_set_bit_mask(pcf,
+ PCF50633_REG_INT1M,
+ PCF50633_INT1_SECOND,
+ PCF50633_INT1_SECOND);
+
+ if (pcf->mask_regs[1] & PCF50633_INT2_ONKEYR)
+ pcf50633_reg_set_bit_mask(pcf,
+ PCF50633_REG_INT2M,
+ PCF50633_INT2_ONKEYR,
+ PCF50633_INT2_ONKEYR);
+ }
+
+ /* Have we just resumed ? */
+ if (pcf->is_suspended) {
+ pcf->is_suspended = 0;
+
+ /* Set the resume reason filtering out non resumers */
+ for (i = 0; i < ARRAY_SIZE(pcf_int); i++)
+ pcf->resume_reason[i] = pcf_int[i] &
+ pcf->pdata->resumers[i];
+
+ /* Make sure we don't pass on any ONKEY events to
+ * userspace now */
+ pcf_int[1] &= ~(PCF50633_INT2_ONKEYR | PCF50633_INT2_ONKEYF);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(pcf_int); i++) {
+ /* Unset masked interrupts */
+ pcf_int[i] &= ~pcf->mask_regs[i];
+
+ for (j = 0; j < 8 ; j++)
+ if (pcf_int[i] & (1 << j))
+ pcf50633_irq_call_handler(pcf, (i * 8) + j);
+ }
+
+out:
+ put_device(pcf->dev);
+ enable_irq(pcf->irq);
+}
+
+static irqreturn_t pcf50633_irq(int irq, void *data)
+{
+ struct pcf50633 *pcf = data;
+
+ dev_dbg(pcf->dev, "pcf50633_irq\n");
+
+ get_device(pcf->dev);
+ disable_irq(pcf->irq);
+ schedule_work(&pcf->irq_work);
+
+ return IRQ_HANDLED;
+}
+
+static void
+pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name,
+ struct platform_device **pdev)
+{
+ struct pcf50633_subdev_pdata *subdev_pdata;
+ int ret;
+
+ *pdev = platform_device_alloc(name, -1);
+ if (!*pdev) {
+ dev_err(pcf->dev, "Falied to allocate %s\n", name);
+ return;
+ }
+
+ subdev_pdata = kmalloc(sizeof(*subdev_pdata), GFP_KERNEL);
+ if (!subdev_pdata) {
+ dev_err(pcf->dev, "Error allocating subdev pdata\n");
+ platform_device_put(*pdev);
+ }
+
+ subdev_pdata->pcf = pcf;
+ platform_device_add_data(*pdev, subdev_pdata, sizeof(*subdev_pdata));
+
+ (*pdev)->dev.parent = pcf->dev;
+
+ ret = platform_device_add(*pdev);
+ if (ret) {
+ dev_err(pcf->dev, "Failed to register %s: %d\n", name, ret);
+ platform_device_put(*pdev);
+ *pdev = NULL;
+ }
+}
+
+#ifdef CONFIG_PM
+static int pcf50633_suspend(struct device *dev, pm_message_t state)
+{
+ struct pcf50633 *pcf;
+ int ret = 0, i;
+ u8 res[5];
+
+ pcf = dev_get_drvdata(dev);
+
+ /* Make sure our interrupt handlers are not called
+ * henceforth */
+ disable_irq(pcf->irq);
+
+ /* Make sure that any running IRQ worker has quit */
+ cancel_work_sync(&pcf->irq_work);
+
+ /* Save the masks */
+ ret = pcf50633_read_block(pcf, PCF50633_REG_INT1M,
+ ARRAY_SIZE(pcf->suspend_irq_masks),
+ pcf->suspend_irq_masks);
+ if (ret < 0) {
+ dev_err(pcf->dev, "error saving irq masks\n");
+ goto out;
+ }
+
+ /* Write wakeup irq masks */
+ for (i = 0; i < ARRAY_SIZE(res); i++)
+ res[i] = ~pcf->pdata->resumers[i];
+
+ ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,
+ ARRAY_SIZE(res), &res[0]);
+ if (ret < 0) {
+ dev_err(pcf->dev, "error writing wakeup irq masks\n");
+ goto out;
+ }
+
+ pcf->is_suspended = 1;
+
+out:
+ return ret;
+}
+
+static int pcf50633_resume(struct device *dev)
+{
+ struct pcf50633 *pcf;
+ int ret;
+
+ pcf = dev_get_drvdata(dev);
+
+ /* Write the saved mask registers */
+ ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,
+ ARRAY_SIZE(pcf->suspend_irq_masks),
+ pcf->suspend_irq_masks);
+ if (ret < 0)
+ dev_err(pcf->dev, "Error restoring saved suspend masks\n");
+
+ /* Restore regulators' state */
+
+
+ get_device(pcf->dev);
+
+ /*
+ * Clear any pending interrupts and set resume reason if any.
+ * This will leave with enable_irq()
+ */
+ pcf50633_irq_worker(&pcf->irq_work);
+
+ return 0;
+}
+#else
+#define pcf50633_suspend NULL
+#define pcf50633_resume NULL
+#endif
+
+static int __devinit pcf50633_probe(struct i2c_client *client,
+ const struct i2c_device_id *ids)
+{
+ struct pcf50633 *pcf;
+ struct pcf50633_platform_data *pdata = client->dev.platform_data;
+ int i, ret = 0;
+ int version, variant;
+
+ pcf = kzalloc(sizeof(*pcf), GFP_KERNEL);
+ if (!pcf)
+ return -ENOMEM;
+
+ pcf->pdata = pdata;
+
+ mutex_init(&pcf->lock);
+
+ i2c_set_clientdata(client, pcf);
+ pcf->dev = &client->dev;
+ pcf->i2c_client = client;
+ pcf->irq = client->irq;
+
+ INIT_WORK(&pcf->irq_work, pcf50633_irq_worker);
+
+ version = pcf50633_reg_read(pcf, 0);
+ variant = pcf50633_reg_read(pcf, 1);
+ if (version < 0 || variant < 0) {
+ dev_err(pcf->dev, "Unable to probe pcf50633\n");
+ ret = -ENODEV;
+ goto err;
+ }
+
+ dev_info(pcf->dev, "Probed device version %d variant %d\n",
+ version, variant);
+
+ /* Enable all interrupts except RTC SECOND */
+ pcf->mask_regs[0] = 0x80;
+ pcf50633_reg_write(pcf, PCF50633_REG_INT1M, pcf->mask_regs[0]);
+ pcf50633_reg_write(pcf, PCF50633_REG_INT2M, 0x00);
+ pcf50633_reg_write(pcf, PCF50633_REG_INT3M, 0x00);
+ pcf50633_reg_write(pcf, PCF50633_REG_INT4M, 0x00);
+ pcf50633_reg_write(pcf, PCF50633_REG_INT5M, 0x00);
+
+ /* Create sub devices */
+ pcf50633_client_dev_register(pcf, "pcf50633-input",
+ &pcf->input_pdev);
+ pcf50633_client_dev_register(pcf, "pcf50633-rtc",
+ &pcf->rtc_pdev);
+ pcf50633_client_dev_register(pcf, "pcf50633-mbc",
+ &pcf->mbc_pdev);
+ pcf50633_client_dev_register(pcf, "pcf50633-adc",
+ &pcf->adc_pdev);
+
+ for (i = 0; i < PCF50633_NUM_REGULATORS; i++) {
+ struct platform_device *pdev;
+
+ pdev = platform_device_alloc("pcf50633-regltr", i);
+ if (!pdev) {
+ dev_err(pcf->dev, "Cannot create regulator\n");
+ continue;
+ }
+
+ pdev->dev.parent = pcf->dev;
+ pdev->dev.platform_data = &pdata->reg_init_data[i];
+ pdev->dev.driver_data = pcf;
+ pcf->regulator_pdev[i] = pdev;
+
+ platform_device_add(pdev);
+ }
+
+ if (client->irq) {
+ set_irq_handler(client->irq, handle_level_irq);
+ ret = request_irq(client->irq, pcf50633_irq,
+ IRQF_TRIGGER_LOW, "pcf50633", pcf);
+
+ if (ret) {
+ dev_err(pcf->dev, "Failed to request IRQ %d\n", ret);
+ goto err;
+ }
+ } else {
+ dev_err(pcf->dev, "No IRQ configured\n");
+ goto err;
+ }
+
+ if (enable_irq_wake(client->irq) < 0)
+ dev_err(pcf->dev, "IRQ %u cannot be enabled as wake-up source"
+ "in this hardware revision", client->irq);
+
+ ret = sysfs_create_group(&client->dev.kobj, &pcf_attr_group);
+ if (ret)
+ dev_err(pcf->dev, "error creating sysfs entries\n");
+
+ if (pdata->probe_done)
+ pdata->probe_done(pcf);
+
+ return 0;
+
+err:
+ kfree(pcf);
+ return ret;
+}
+
+static int __devexit pcf50633_remove(struct i2c_client *client)
+{
+ struct pcf50633 *pcf = i2c_get_clientdata(client);
+ int i;
+
+ free_irq(pcf->irq, pcf);
+
+ platform_device_unregister(pcf->input_pdev);
+ platform_device_unregister(pcf->rtc_pdev);
+ platform_device_unregister(pcf->mbc_pdev);
+ platform_device_unregister(pcf->adc_pdev);
+
+ for (i = 0; i < PCF50633_NUM_REGULATORS; i++)
+ platform_device_unregister(pcf->regulator_pdev[i]);
+
+ kfree(pcf);
+
+ return 0;
+}
+
+static struct i2c_device_id pcf50633_id_table[] = {
+ {"pcf50633", 0x73},
+};
+
+static struct i2c_driver pcf50633_driver = {
+ .driver = {
+ .name = "pcf50633",
+ .suspend = pcf50633_suspend,
+ .resume = pcf50633_resume,
+ },
+ .id_table = pcf50633_id_table,
+ .probe = pcf50633_probe,
+ .remove = __devexit_p(pcf50633_remove),
+};
+
+static int __init pcf50633_init(void)
+{
+ return i2c_add_driver(&pcf50633_driver);
+}
+
+static void __exit pcf50633_exit(void)
+{
+ i2c_del_driver(&pcf50633_driver);
+}
+
+MODULE_DESCRIPTION("I2C chip driver for NXP PCF50633 PMU");
+MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
+MODULE_LICENSE("GPL");
+
+module_init(pcf50633_init);
+module_exit(pcf50633_exit);
diff --git a/drivers/mfd/pcf50633-gpio.c b/drivers/mfd/pcf50633-gpio.c
new file mode 100644
index 0000000..2fa2eca
--- /dev/null
+++ b/drivers/mfd/pcf50633-gpio.c
@@ -0,0 +1,118 @@
+/* NXP PCF50633 GPIO Driver
+ *
+ * (C) 2006-2008 by Openmoko, Inc.
+ * Author: Balaji Rao <balajirrao@openmoko.org>
+ * All rights reserved.
+ *
+ * Broken down from monstrous PCF50633 driver mainly by
+ * Harald Welte, Andy Green and Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+
+#include <linux/mfd/pcf50633/core.h>
+#include <linux/mfd/pcf50633/gpio.h>
+
+enum pcf50633_regulator_id {
+ PCF50633_REGULATOR_AUTO,
+ PCF50633_REGULATOR_DOWN1,
+ PCF50633_REGULATOR_DOWN2,
+ PCF50633_REGULATOR_LDO1,
+ PCF50633_REGULATOR_LDO2,
+ PCF50633_REGULATOR_LDO3,
+ PCF50633_REGULATOR_LDO4,
+ PCF50633_REGULATOR_LDO5,
+ PCF50633_REGULATOR_LDO6,
+ PCF50633_REGULATOR_HCLDO,
+ PCF50633_REGULATOR_MEMLDO,
+};
+
+#define PCF50633_REG_AUTOOUT 0x1a
+#define PCF50633_REG_DOWN1OUT 0x1e
+#define PCF50633_REG_DOWN2OUT 0x22
+#define PCF50633_REG_MEMLDOOUT 0x26
+#define PCF50633_REG_LDO1OUT 0x2d
+#define PCF50633_REG_LDO2OUT 0x2f
+#define PCF50633_REG_LDO3OUT 0x31
+#define PCF50633_REG_LDO4OUT 0x33
+#define PCF50633_REG_LDO5OUT 0x35
+#define PCF50633_REG_LDO6OUT 0x37
+#define PCF50633_REG_HCLDOOUT 0x39
+
+static const u8 pcf50633_regulator_registers[PCF50633_NUM_REGULATORS] = {
+ [PCF50633_REGULATOR_AUTO] = PCF50633_REG_AUTOOUT,
+ [PCF50633_REGULATOR_DOWN1] = PCF50633_REG_DOWN1OUT,
+ [PCF50633_REGULATOR_DOWN2] = PCF50633_REG_DOWN2OUT,
+ [PCF50633_REGULATOR_MEMLDO] = PCF50633_REG_MEMLDOOUT,
+ [PCF50633_REGULATOR_LDO1] = PCF50633_REG_LDO1OUT,
+ [PCF50633_REGULATOR_LDO2] = PCF50633_REG_LDO2OUT,
+ [PCF50633_REGULATOR_LDO3] = PCF50633_REG_LDO3OUT,
+ [PCF50633_REGULATOR_LDO4] = PCF50633_REG_LDO4OUT,
+ [PCF50633_REGULATOR_LDO5] = PCF50633_REG_LDO5OUT,
+ [PCF50633_REGULATOR_LDO6] = PCF50633_REG_LDO6OUT,
+ [PCF50633_REGULATOR_HCLDO] = PCF50633_REG_HCLDOOUT,
+};
+
+int pcf50633_gpio_set(struct pcf50633 *pcf, int gpio, u8 val)
+{
+ u8 reg;
+
+ reg = gpio - PCF50633_GPIO1 + PCF50633_REG_GPIO1CFG;
+
+ return pcf50633_reg_set_bit_mask(pcf, reg, 0x07, val);
+}
+EXPORT_SYMBOL_GPL(pcf50633_gpio_set);
+
+u8 pcf50633_gpio_get(struct pcf50633 *pcf, int gpio)
+{
+ u8 reg, val;
+
+ reg = gpio - PCF50633_GPIO1 + PCF50633_REG_GPIO1CFG;
+ val = pcf50633_reg_read(pcf, reg) & 0x07;
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(pcf50633_gpio_get);
+
+int pcf50633_gpio_invert_set(struct pcf50633 *pcf, int gpio, int invert)
+{
+ u8 val, reg;
+
+ reg = gpio - PCF50633_GPIO1 + PCF50633_REG_GPIO1CFG;
+ val = !!invert << 3;
+
+ return pcf50633_reg_set_bit_mask(pcf, reg, 1 << 3, val);
+}
+EXPORT_SYMBOL_GPL(pcf50633_gpio_invert_set);
+
+int pcf50633_gpio_invert_get(struct pcf50633 *pcf, int gpio)
+{
+ u8 reg, val;
+
+ reg = gpio - PCF50633_GPIO1 + PCF50633_REG_GPIO1CFG;
+ val = pcf50633_reg_read(pcf, reg);
+
+ return val & (1 << 3);
+}
+EXPORT_SYMBOL_GPL(pcf50633_gpio_invert_get);
+
+int pcf50633_gpio_power_supply_set(struct pcf50633 *pcf,
+ int gpio, int regulator, int on)
+{
+ u8 reg, val, mask;
+
+ /* the *ENA register is always one after the *OUT register */
+ reg = pcf50633_regulator_registers[regulator] + 1;
+
+ val = !!on << (gpio - PCF50633_GPIO1);
+ mask = 1 << (gpio - PCF50633_GPIO1);
+
+ return pcf50633_reg_set_bit_mask(pcf, reg, mask, val);
+}
+EXPORT_SYMBOL_GPL(pcf50633_gpio_power_supply_set);
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 170f9d4..0e5761f 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -41,6 +41,7 @@ struct sm501_gpio_chip {
struct gpio_chip gpio;
struct sm501_gpio *ourgpio; /* to get back to parent. */
void __iomem *regbase;
+ void __iomem *control; /* address of control reg. */
};
struct sm501_gpio {
@@ -908,6 +909,25 @@ static int sm501_gpio_get(struct gpio_chip *chip, unsigned offset)
return result & 1UL;
}
+static void sm501_gpio_ensure_gpio(struct sm501_gpio_chip *smchip,
+ unsigned long bit)
+{
+ unsigned long ctrl;
+
+ /* check and modify if this pin is not set as gpio. */
+
+ if (readl(smchip->control) & bit) {
+ dev_info(sm501_gpio_to_dev(smchip->ourgpio)->dev,
+ "changing mode of gpio, bit %08lx\n", bit);
+
+ ctrl = readl(smchip->control);
+ ctrl &= ~bit;
+ writel(ctrl, smchip->control);
+
+ sm501_sync_regs(sm501_gpio_to_dev(smchip->ourgpio));
+ }
+}
+
static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
@@ -929,6 +949,8 @@ static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
writel(val, regs);
sm501_sync_regs(sm501_gpio_to_dev(smgpio));
+ sm501_gpio_ensure_gpio(smchip, bit);
+
spin_unlock_irqrestore(&smgpio->lock, save);
}
@@ -941,8 +963,8 @@ static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset)
unsigned long save;
unsigned long ddr;
- dev_info(sm501_gpio_to_dev(smgpio)->dev, "%s(%p,%d)\n",
- __func__, chip, offset);
+ dev_dbg(sm501_gpio_to_dev(smgpio)->dev, "%s(%p,%d)\n",
+ __func__, chip, offset);
spin_lock_irqsave(&smgpio->lock, save);
@@ -950,6 +972,8 @@ static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset)
writel(ddr & ~bit, regs + SM501_GPIO_DDR_LOW);
sm501_sync_regs(sm501_gpio_to_dev(smgpio));
+ sm501_gpio_ensure_gpio(smchip, bit);
+
spin_unlock_irqrestore(&smgpio->lock, save);
return 0;
@@ -1012,9 +1036,11 @@ static int __devinit sm501_gpio_register_chip(struct sm501_devdata *sm,
if (base > 0)
base += 32;
chip->regbase = gpio->regs + SM501_GPIO_DATA_HIGH;
+ chip->control = sm->regs + SM501_GPIO63_32_CONTROL;
gchip->label = "SM501-HIGH";
} else {
chip->regbase = gpio->regs + SM501_GPIO_DATA_LOW;
+ chip->control = sm->regs + SM501_GPIO31_0_CONTROL;
gchip->label = "SM501-LOW";
}
diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl4030-core.c
index b59c385..e7ab003 100644
--- a/drivers/mfd/twl4030-core.c
+++ b/drivers/mfd/twl4030-core.c
@@ -38,6 +38,9 @@
#include <linux/i2c.h>
#include <linux/i2c/twl4030.h>
+#ifdef CONFIG_ARM
+#include <mach/cpu.h>
+#endif
/*
* The TWL4030 "Triton 2" is one of a family of a multi-function "Power
@@ -646,7 +649,7 @@ static inline int __init unprotect_pm_master(void)
return e;
}
-static void __init clocks_init(void)
+static void __init clocks_init(struct device *dev)
{
int e = 0;
struct clk *osc;
@@ -655,9 +658,9 @@ static void __init clocks_init(void)
#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
if (cpu_is_omap2430())
- osc = clk_get(NULL, "osc_ck");
+ osc = clk_get(dev, "osc_ck");
else
- osc = clk_get(NULL, "osc_sys_ck");
+ osc = clk_get(dev, "osc_sys_ck");
if (IS_ERR(osc)) {
printk(KERN_WARNING "Skipping twl4030 internal clock init and "
@@ -773,7 +776,7 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id)
inuse = true;
/* setup clock framework */
- clocks_init();
+ clocks_init(&client->dev);
/* Maybe init the T2 Interrupt subsystem */
if (client->irq
diff --git a/drivers/misc/sgi-xp/xpc_sn2.c b/drivers/misc/sgi-xp/xpc_sn2.c
index 73b7fb8..82fb995 100644
--- a/drivers/misc/sgi-xp/xpc_sn2.c
+++ b/drivers/misc/sgi-xp/xpc_sn2.c
@@ -899,7 +899,7 @@ xpc_update_partition_info_sn2(struct xpc_partition *part, u8 remote_rp_version,
dev_dbg(xpc_part, " remote_vars_pa = 0x%016lx\n",
part_sn2->remote_vars_pa);
- part->last_heartbeat = remote_vars->heartbeat;
+ part->last_heartbeat = remote_vars->heartbeat - 1;
dev_dbg(xpc_part, " last_heartbeat = 0x%016lx\n",
part->last_heartbeat);
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
index c092c39..5b91a85 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/3c503.c
@@ -177,6 +177,7 @@ static const struct net_device_ops el2_netdev_ops = {
.ndo_get_stats = eip_get_stats,
.ndo_set_multicast_list = eip_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = eip_poll,
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 665e7fd..cdbbb62 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -3109,6 +3109,8 @@ static void acpi_set_WOL(struct net_device *dev)
struct vortex_private *vp = netdev_priv(dev);
void __iomem *ioaddr = vp->ioaddr;
+ device_set_wakeup_enable(vp->gendev, vp->enable_wol);
+
if (vp->enable_wol) {
/* Power up on: 1==Downloaded Filter, 2==Magic Packets, 4==Link Status. */
EL3WINDOW(7);
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index dd7ac82..4e19ae3 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -1821,6 +1821,7 @@ static const struct net_device_ops cp_netdev_ops = {
.ndo_open = cp_open,
.ndo_stop = cp_close,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_set_multicast_list = cp_set_rx_mode,
.ndo_get_stats = cp_get_stats,
.ndo_do_ioctl = cp_ioctl,
@@ -1832,6 +1833,7 @@ static const struct net_device_ops cp_netdev_ops = {
#ifdef BROKEN
.ndo_change_mtu = cp_change_mtu,
#endif
+
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = cp_poll_controller,
#endif
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index fe370f8..a5b2420 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -917,6 +917,7 @@ static const struct net_device_ops rtl8139_netdev_ops = {
.ndo_stop = rtl8139_close,
.ndo_get_stats = rtl8139_get_stats,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_start_xmit = rtl8139_start_xmit,
.ndo_set_multicast_list = rtl8139_set_rx_mode,
.ndo_do_ioctl = netdev_ioctl,
@@ -924,7 +925,6 @@ static const struct net_device_ops rtl8139_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = rtl8139_poll_controller,
#endif
-
};
static int __devinit rtl8139_init_one (struct pci_dev *pdev,
diff --git a/drivers/net/8390.c b/drivers/net/8390.c
index fbe609a..ec3e22e 100644
--- a/drivers/net/8390.c
+++ b/drivers/net/8390.c
@@ -63,6 +63,7 @@ const struct net_device_ops ei_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/net/8390p.c b/drivers/net/8390p.c
index ee70b35..da863c9 100644
--- a/drivers/net/8390p.c
+++ b/drivers/net/8390p.c
@@ -68,6 +68,7 @@ const struct net_device_ops eip_netdev_ops = {
.ndo_get_stats = eip_get_stats,
.ndo_set_multicast_list = eip_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = eip_poll,
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 65afda4..9fe8cb7 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1600,7 +1600,7 @@ config 8139_OLD_RX_RESET
old RX-reset behavior. If unsure, say N.
config R6040
- tristate "RDC R6040 Fast Ethernet Adapter support (EXPERIMENTAL)"
+ tristate "RDC R6040 Fast Ethernet Adapter support"
depends on NET_PCI && PCI
select CRC32
select MII
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index 5b396ff..9589d620 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -460,6 +460,7 @@ static const struct net_device_ops ace_netdev_ops = {
.ndo_get_stats = ace_get_stats,
.ndo_start_xmit = ace_start_xmit,
.ndo_set_multicast_list = ace_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = ace_set_mac_addr,
.ndo_change_mtu = ace_change_mtu,
#if ACENIC_DO_VLAN
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c
index 6278606..d15d8b7 100644
--- a/drivers/net/arm/etherh.c
+++ b/drivers/net/arm/etherh.c
@@ -646,6 +646,7 @@ static const struct net_device_ops etherh_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_set_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c
index 9ad22d1..1cf2f94 100644
--- a/drivers/net/arm/ks8695net.c
+++ b/drivers/net/arm/ks8695net.c
@@ -1357,6 +1357,7 @@ static const struct net_device_ops ks8695_netdev_ops = {
.ndo_start_xmit = ks8695_start_xmit,
.ndo_tx_timeout = ks8695_timeout,
.ndo_set_mac_address = ks8695_set_mac,
+ .ndo_validate_addr = eth_validate_addr,
.ndo_set_multicast_list = ks8695_set_multicast,
};
diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
index 337488e..a4eb6c4 100644
--- a/drivers/net/ax88796.c
+++ b/drivers/net/ax88796.c
@@ -37,7 +37,10 @@ static int phy_debug = 0;
#define __ei_open ax_ei_open
#define __ei_close ax_ei_close
#define __ei_poll ax_ei_poll
+#define __ei_start_xmit ax_ei_start_xmit
#define __ei_tx_timeout ax_ei_tx_timeout
+#define __ei_get_stats ax_ei_get_stats
+#define __ei_set_multicast_list ax_ei_set_multicast_list
#define __ei_interrupt ax_ei_interrupt
#define ____alloc_ei_netdev ax__alloc_ei_netdev
#define __NS8390_init ax_NS8390_init
@@ -623,6 +626,23 @@ static void ax_eeprom_register_write(struct eeprom_93cx6 *eeprom)
}
#endif
+static const struct net_device_ops ax_netdev_ops = {
+ .ndo_open = ax_open,
+ .ndo_stop = ax_close,
+ .ndo_do_ioctl = ax_ioctl,
+
+ .ndo_start_xmit = ax_ei_start_xmit,
+ .ndo_tx_timeout = ax_ei_tx_timeout,
+ .ndo_get_stats = ax_ei_get_stats,
+ .ndo_set_multicast_list = ax_ei_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_change_mtu = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = ax_ei_poll,
+#endif
+};
+
/* setup code */
static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local)
@@ -738,9 +758,7 @@ static int ax_init_dev(struct net_device *dev, int first_init)
ei_status.get_8390_hdr = &ax_get_8390_hdr;
ei_status.priv = 0;
- dev->open = ax_open;
- dev->stop = ax_close;
- dev->do_ioctl = ax_ioctl;
+ dev->netdev_ops = &ax_netdev_ops;
dev->ethtool_ops = &ax_ethtool_ops;
ax->msg_enable = NETIF_MSG_LINK;
@@ -753,9 +771,6 @@ static int ax_init_dev(struct net_device *dev, int first_init)
ax->mii.mdio_write = ax_phy_write;
ax->mii.dev = dev;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = ax_ei_poll;
-#endif
ax_NS8390_init(dev, 0);
if (first_init)
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 6926ebe..c38512e 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -73,8 +73,8 @@
(BP)->tx_cons - (BP)->tx_prod - TX_RING_GAP(BP))
#define NEXT_TX(N) (((N) + 1) & (B44_TX_RING_SIZE - 1))
-#define RX_PKT_OFFSET 30
-#define RX_PKT_BUF_SZ (1536 + RX_PKT_OFFSET + 64)
+#define RX_PKT_OFFSET (RX_HEADER_LEN + 2)
+#define RX_PKT_BUF_SZ (1536 + RX_PKT_OFFSET)
/* minimum number of free TX descriptors required to wake up TX process */
#define B44_TX_WAKEUP_THRESH (B44_TX_RING_SIZE / 4)
@@ -679,10 +679,10 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
dev_kfree_skb_any(skb);
return -ENOMEM;
}
+ bp->force_copybreak = 1;
}
rh = (struct rx_header *) skb->data;
- skb_reserve(skb, RX_PKT_OFFSET);
rh->len = 0;
rh->flags = 0;
@@ -693,13 +693,13 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
if (src_map != NULL)
src_map->skb = NULL;
- ctrl = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - RX_PKT_OFFSET));
+ ctrl = (DESC_CTRL_LEN & RX_PKT_BUF_SZ);
if (dest_idx == (B44_RX_RING_SIZE - 1))
ctrl |= DESC_CTRL_EOT;
dp = &bp->rx_ring[dest_idx];
dp->ctrl = cpu_to_le32(ctrl);
- dp->addr = cpu_to_le32((u32) mapping + RX_PKT_OFFSET + bp->dma_offset);
+ dp->addr = cpu_to_le32((u32) mapping + bp->dma_offset);
if (bp->flags & B44_FLAG_RX_RING_HACK)
b44_sync_dma_desc_for_device(bp->sdev, bp->rx_ring_dma,
@@ -801,7 +801,7 @@ static int b44_rx(struct b44 *bp, int budget)
/* Omit CRC. */
len -= 4;
- if (len > RX_COPY_THRESHOLD) {
+ if (!bp->force_copybreak && len > RX_COPY_THRESHOLD) {
int skb_size;
skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod);
if (skb_size < 0)
@@ -809,8 +809,8 @@ static int b44_rx(struct b44 *bp, int budget)
ssb_dma_unmap_single(bp->sdev, map,
skb_size, DMA_FROM_DEVICE);
/* Leave out rx_header */
- skb_put(skb, len + RX_PKT_OFFSET);
- skb_pull(skb, RX_PKT_OFFSET);
+ skb_put(skb, len + RX_PKT_OFFSET);
+ skb_pull(skb, RX_PKT_OFFSET);
} else {
struct sk_buff *copy_skb;
@@ -2153,6 +2153,7 @@ static int __devinit b44_init_one(struct ssb_device *sdev,
bp = netdev_priv(dev);
bp->sdev = sdev;
bp->dev = dev;
+ bp->force_copybreak = 0;
bp->msg_enable = netif_msg_init(b44_debug, B44_DEF_MSG_ENABLE);
diff --git a/drivers/net/b44.h b/drivers/net/b44.h
index 7db0c84..e678498 100644
--- a/drivers/net/b44.h
+++ b/drivers/net/b44.h
@@ -395,7 +395,7 @@ struct b44 {
u32 rx_pending;
u32 tx_pending;
u8 phy_addr;
-
+ u8 force_copybreak;
struct mii_if_info mii_if;
};
diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h
index fd705d1..6fcccef 100644
--- a/drivers/net/bnx2x.h
+++ b/drivers/net/bnx2x.h
@@ -20,6 +20,11 @@
* (you will need to reboot afterwards) */
/* #define BNX2X_STOP_ON_ERROR */
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+#define BCM_VLAN 1
+#endif
+
+
/* error/debug prints */
#define DRV_MODULE_NAME "bnx2x"
@@ -78,11 +83,6 @@
#endif
-#ifdef NETIF_F_HW_VLAN_TX
-#define BCM_VLAN 1
-#endif
-
-
#define U64_LO(x) (u32)(((u64)(x)) & 0xffffffff)
#define U64_HI(x) (u32)(((u64)(x)) >> 32)
#define HILO_U64(hi, lo) ((((u64)(hi)) << 32) + (lo))
@@ -150,6 +150,9 @@ struct sw_rx_page {
#define PAGES_PER_SGE_SHIFT 0
#define PAGES_PER_SGE (1 << PAGES_PER_SGE_SHIFT)
+#define SGE_PAGE_SIZE PAGE_SIZE
+#define SGE_PAGE_SHIFT PAGE_SHIFT
+#define SGE_PAGE_ALIGN(addr) PAGE_ALIGN(addr)
#define BCM_RX_ETH_PAYLOAD_ALIGN 64
@@ -736,7 +739,7 @@ struct bnx2x {
struct bnx2x_fastpath fp[MAX_CONTEXT];
void __iomem *regview;
void __iomem *doorbells;
-#define BNX2X_DB_SIZE (16*2048)
+#define BNX2X_DB_SIZE (16*BCM_PAGE_SIZE)
struct net_device *dev;
struct pci_dev *pdev;
@@ -801,6 +804,8 @@ struct bnx2x {
#define TPA_ENABLE_FLAG 0x80
#define NO_MCP_FLAG 0x100
#define BP_NOMCP(bp) (bp->flags & NO_MCP_FLAG)
+#define HW_VLAN_TX_FLAG 0x400
+#define HW_VLAN_RX_FLAG 0x800
int func;
#define BP_PORT(bp) (bp->func % PORT_MAX)
@@ -811,7 +816,7 @@ struct bnx2x {
int pm_cap;
int pcie_cap;
- struct work_struct sp_task;
+ struct delayed_work sp_task;
struct work_struct reset_task;
struct timer_list timer;
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c
index 4be0584..7c53379 100644
--- a/drivers/net/bnx2x_main.c
+++ b/drivers/net/bnx2x_main.c
@@ -38,9 +38,7 @@
#include <linux/time.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
-#ifdef NETIF_F_HW_VLAN_TX
- #include <linux/if_vlan.h>
-#endif
+#include <linux/if_vlan.h>
#include <net/ip.h>
#include <net/tcp.h>
#include <net/checksum.h>
@@ -95,6 +93,7 @@ MODULE_PARM_DESC(debug, "default debug msglevel");
module_param(use_multi, int, 0);
MODULE_PARM_DESC(use_multi, "use per-CPU queues");
#endif
+static struct workqueue_struct *bnx2x_wq;
enum bnx2x_board_type {
BCM57710 = 0,
@@ -671,7 +670,8 @@ static void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw)
synchronize_irq(bp->pdev->irq);
/* make sure sp_task is not running */
- cancel_work_sync(&bp->sp_task);
+ cancel_delayed_work(&bp->sp_task);
+ flush_workqueue(bnx2x_wq);
}
/* fast path */
@@ -972,7 +972,7 @@ static inline void bnx2x_free_rx_sge(struct bnx2x *bp,
return;
pci_unmap_page(bp->pdev, pci_unmap_addr(sw_buf, mapping),
- BCM_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE);
+ SGE_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE);
__free_pages(page, PAGES_PER_SGE_SHIFT);
sw_buf->page = NULL;
@@ -1000,7 +1000,7 @@ static inline int bnx2x_alloc_rx_sge(struct bnx2x *bp,
if (unlikely(page == NULL))
return -ENOMEM;
- mapping = pci_map_page(bp->pdev, page, 0, BCM_PAGE_SIZE*PAGES_PER_SGE,
+ mapping = pci_map_page(bp->pdev, page, 0, SGE_PAGE_SIZE*PAGES_PER_SGE,
PCI_DMA_FROMDEVICE);
if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
__free_pages(page, PAGES_PER_SGE_SHIFT);
@@ -1096,9 +1096,9 @@ static void bnx2x_update_sge_prod(struct bnx2x_fastpath *fp,
struct eth_fast_path_rx_cqe *fp_cqe)
{
struct bnx2x *bp = fp->bp;
- u16 sge_len = BCM_PAGE_ALIGN(le16_to_cpu(fp_cqe->pkt_len) -
+ u16 sge_len = SGE_PAGE_ALIGN(le16_to_cpu(fp_cqe->pkt_len) -
le16_to_cpu(fp_cqe->len_on_bd)) >>
- BCM_PAGE_SHIFT;
+ SGE_PAGE_SHIFT;
u16 last_max, last_elem, first_elem;
u16 delta = 0;
u16 i;
@@ -1203,22 +1203,22 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
u16 cqe_idx)
{
struct sw_rx_page *rx_pg, old_rx_pg;
- struct page *sge;
u16 len_on_bd = le16_to_cpu(fp_cqe->len_on_bd);
u32 i, frag_len, frag_size, pages;
int err;
int j;
frag_size = le16_to_cpu(fp_cqe->pkt_len) - len_on_bd;
- pages = BCM_PAGE_ALIGN(frag_size) >> BCM_PAGE_SHIFT;
+ pages = SGE_PAGE_ALIGN(frag_size) >> SGE_PAGE_SHIFT;
/* This is needed in order to enable forwarding support */
if (frag_size)
- skb_shinfo(skb)->gso_size = min((u32)BCM_PAGE_SIZE,
+ skb_shinfo(skb)->gso_size = min((u32)SGE_PAGE_SIZE,
max(frag_size, (u32)len_on_bd));
#ifdef BNX2X_STOP_ON_ERROR
- if (pages > 8*PAGES_PER_SGE) {
+ if (pages >
+ min((u32)8, (u32)MAX_SKB_FRAGS) * SGE_PAGE_SIZE * PAGES_PER_SGE) {
BNX2X_ERR("SGL length is too long: %d. CQE index is %d\n",
pages, cqe_idx);
BNX2X_ERR("fp_cqe->pkt_len = %d fp_cqe->len_on_bd = %d\n",
@@ -1234,9 +1234,8 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
/* FW gives the indices of the SGE as if the ring is an array
(meaning that "next" element will consume 2 indices) */
- frag_len = min(frag_size, (u32)(BCM_PAGE_SIZE*PAGES_PER_SGE));
+ frag_len = min(frag_size, (u32)(SGE_PAGE_SIZE*PAGES_PER_SGE));
rx_pg = &fp->rx_page_ring[sge_idx];
- sge = rx_pg->page;
old_rx_pg = *rx_pg;
/* If we fail to allocate a substitute page, we simply stop
@@ -1249,7 +1248,7 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
/* Unmap the page as we r going to pass it to the stack */
pci_unmap_page(bp->pdev, pci_unmap_addr(&old_rx_pg, mapping),
- BCM_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE);
+ SGE_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE);
/* Add one frag and update the appropriate fields in the skb */
skb_fill_page_desc(skb, j, old_rx_pg.page, 0, frag_len);
@@ -1282,6 +1281,13 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
if (likely(new_skb)) {
/* fix ip xsum and give it to the stack */
/* (no need to map the new skb) */
+#ifdef BCM_VLAN
+ int is_vlan_cqe =
+ (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
+ PARSING_FLAGS_VLAN);
+ int is_not_hwaccel_vlan_cqe =
+ (is_vlan_cqe && (!(bp->flags & HW_VLAN_RX_FLAG)));
+#endif
prefetch(skb);
prefetch(((char *)(skb)) + 128);
@@ -1306,6 +1312,12 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
struct iphdr *iph;
iph = (struct iphdr *)skb->data;
+#ifdef BCM_VLAN
+ /* If there is no Rx VLAN offloading -
+ take VLAN tag into an account */
+ if (unlikely(is_not_hwaccel_vlan_cqe))
+ iph = (struct iphdr *)((u8 *)iph + VLAN_HLEN);
+#endif
iph->check = 0;
iph->check = ip_fast_csum((u8 *)iph, iph->ihl);
}
@@ -1313,9 +1325,8 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
if (!bnx2x_fill_frag_skb(bp, fp, skb,
&cqe->fast_path_cqe, cqe_idx)) {
#ifdef BCM_VLAN
- if ((bp->vlgrp != NULL) &&
- (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
- PARSING_FLAGS_VLAN))
+ if ((bp->vlgrp != NULL) && is_vlan_cqe &&
+ (!is_not_hwaccel_vlan_cqe))
vlan_hwaccel_receive_skb(skb, bp->vlgrp,
le16_to_cpu(cqe->fast_path_cqe.
vlan_tag));
@@ -1355,11 +1366,23 @@ static inline void bnx2x_update_rx_prod(struct bnx2x *bp,
rx_prods.cqe_prod = rx_comp_prod;
rx_prods.sge_prod = rx_sge_prod;
+ /*
+ * Make sure that the BD and SGE data is updated before updating the
+ * producers since FW might read the BD/SGE right after the producer
+ * is updated.
+ * This is only applicable for weak-ordered memory model archs such
+ * as IA-64. The following barrier is also mandatory since FW will
+ * assumes BDs must have buffers.
+ */
+ wmb();
+
for (i = 0; i < sizeof(struct tstorm_eth_rx_producers)/4; i++)
REG_WR(bp, BAR_TSTRORM_INTMEM +
TSTORM_RX_PRODS_OFFSET(BP_PORT(bp), FP_CL_ID(fp)) + i*4,
((u32 *)&rx_prods)[i]);
+ mmiowb(); /* keep prod updates ordered */
+
DP(NETIF_MSG_RX_STATUS,
"Wrote: bd_prod %u cqe_prod %u sge_prod %u\n",
bd_prod, rx_comp_prod, rx_sge_prod);
@@ -1415,7 +1438,7 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
DP(NETIF_MSG_RX_STATUS, "CQE type %x err %x status %x"
" queue %x vlan %x len %u\n", CQE_TYPE(cqe_fp_flags),
cqe_fp_flags, cqe->fast_path_cqe.status_flags,
- cqe->fast_path_cqe.rss_hash_result,
+ le32_to_cpu(cqe->fast_path_cqe.rss_hash_result),
le16_to_cpu(cqe->fast_path_cqe.vlan_tag),
le16_to_cpu(cqe->fast_path_cqe.pkt_len));
@@ -1547,7 +1570,7 @@ reuse_rx:
}
#ifdef BCM_VLAN
- if ((bp->vlgrp != NULL) &&
+ if ((bp->vlgrp != NULL) && (bp->flags & HW_VLAN_RX_FLAG) &&
(le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
PARSING_FLAGS_VLAN))
vlan_hwaccel_receive_skb(skb, bp->vlgrp,
@@ -1580,7 +1603,6 @@ next_cqe:
/* Update producers */
bnx2x_update_rx_prod(bp, fp, bd_prod_fw, sw_comp_prod,
fp->rx_sge_prod);
- mmiowb(); /* keep prod updates ordered */
fp->rx_pkt += rx_pkt;
fp->rx_calls++;
@@ -1660,7 +1682,7 @@ static irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
if (unlikely(status & 0x1)) {
- schedule_work(&bp->sp_task);
+ queue_delayed_work(bnx2x_wq, &bp->sp_task, 0);
status &= ~0x1;
if (!status)
@@ -1887,7 +1909,8 @@ static int bnx2x_set_spio(struct bnx2x *bp, int spio_num, u32 mode)
static void bnx2x_calc_fc_adv(struct bnx2x *bp)
{
- switch (bp->link_vars.ieee_fc) {
+ switch (bp->link_vars.ieee_fc &
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK) {
case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE:
bp->port.advertising &= ~(ADVERTISED_Asym_Pause |
ADVERTISED_Pause);
@@ -1957,10 +1980,11 @@ static u8 bnx2x_initial_phy_init(struct bnx2x *bp)
rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars);
bnx2x_release_phy_lock(bp);
+ bnx2x_calc_fc_adv(bp);
+
if (bp->link_vars.link_up)
bnx2x_link_report(bp);
- bnx2x_calc_fc_adv(bp);
return rc;
}
@@ -2220,9 +2244,7 @@ static void bnx2x_link_attn(struct bnx2x *bp)
/* Make sure that we are synced with the current statistics */
bnx2x_stats_handle(bp, STATS_EVENT_STOP);
- bnx2x_acquire_phy_lock(bp);
bnx2x_link_update(&bp->link_params, &bp->link_vars);
- bnx2x_release_phy_lock(bp);
if (bp->link_vars.link_up) {
@@ -2471,6 +2493,8 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
if (asserted & ATTN_HARD_WIRED_MASK) {
if (asserted & ATTN_NIG_FOR_FUNC) {
+ bnx2x_acquire_phy_lock(bp);
+
/* save nig interrupt mask */
bp->nig_mask = REG_RD(bp, nig_int_mask_addr);
REG_WR(bp, nig_int_mask_addr, 0);
@@ -2526,8 +2550,10 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
REG_WR(bp, hc_addr, asserted);
/* now set back the mask */
- if (asserted & ATTN_NIG_FOR_FUNC)
+ if (asserted & ATTN_NIG_FOR_FUNC) {
REG_WR(bp, nig_int_mask_addr, bp->nig_mask);
+ bnx2x_release_phy_lock(bp);
+ }
}
static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
@@ -2795,8 +2821,10 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
static void bnx2x_attn_int(struct bnx2x *bp)
{
/* read local copy of bits */
- u32 attn_bits = bp->def_status_blk->atten_status_block.attn_bits;
- u32 attn_ack = bp->def_status_blk->atten_status_block.attn_bits_ack;
+ u32 attn_bits = le32_to_cpu(bp->def_status_blk->atten_status_block.
+ attn_bits);
+ u32 attn_ack = le32_to_cpu(bp->def_status_blk->atten_status_block.
+ attn_bits_ack);
u32 attn_state = bp->attn_state;
/* look for changed bits */
@@ -2820,7 +2848,7 @@ static void bnx2x_attn_int(struct bnx2x *bp)
static void bnx2x_sp_task(struct work_struct *work)
{
- struct bnx2x *bp = container_of(work, struct bnx2x, sp_task);
+ struct bnx2x *bp = container_of(work, struct bnx2x, sp_task.work);
u16 status;
@@ -2844,7 +2872,7 @@ static void bnx2x_sp_task(struct work_struct *work)
if (status & 0x2)
bp->stats_pending = 0;
- bnx2x_ack_sb(bp, DEF_SB_ID, ATTENTION_ID, bp->def_att_idx,
+ bnx2x_ack_sb(bp, DEF_SB_ID, ATTENTION_ID, le16_to_cpu(bp->def_att_idx),
IGU_INT_NOP, 1);
bnx2x_ack_sb(bp, DEF_SB_ID, USTORM_ID, le16_to_cpu(bp->def_u_idx),
IGU_INT_NOP, 1);
@@ -2875,7 +2903,7 @@ static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
return IRQ_HANDLED;
#endif
- schedule_work(&bp->sp_task);
+ queue_delayed_work(bnx2x_wq, &bp->sp_task, 0);
return IRQ_HANDLED;
}
@@ -2892,7 +2920,7 @@ static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
#define ADD_64(s_hi, a_hi, s_lo, a_lo) \
do { \
s_lo += a_lo; \
- s_hi += a_hi + (s_lo < a_lo) ? 1 : 0; \
+ s_hi += a_hi + ((s_lo < a_lo) ? 1 : 0); \
} while (0)
/* difference = minuend - subtrahend */
@@ -4496,7 +4524,7 @@ static void bnx2x_init_context(struct bnx2x *bp)
static void bnx2x_init_ind_table(struct bnx2x *bp)
{
- int port = BP_PORT(bp);
+ int func = BP_FUNC(bp);
int i;
if (!is_multi(bp))
@@ -4505,10 +4533,8 @@ static void bnx2x_init_ind_table(struct bnx2x *bp)
DP(NETIF_MSG_IFUP, "Initializing indirection table\n");
for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
REG_WR8(bp, BAR_TSTRORM_INTMEM +
- TSTORM_INDIRECTION_TABLE_OFFSET(port) + i,
- i % bp->num_queues);
-
- REG_WR(bp, PRS_REG_A_PRSU_20, 0xf);
+ TSTORM_INDIRECTION_TABLE_OFFSET(func) + i,
+ BP_CL_ID(bp) + (i % bp->num_queues));
}
static void bnx2x_set_client_config(struct bnx2x *bp)
@@ -4517,12 +4543,12 @@ static void bnx2x_set_client_config(struct bnx2x *bp)
int port = BP_PORT(bp);
int i;
- tstorm_client.mtu = bp->dev->mtu + ETH_OVREHEAD;
+ tstorm_client.mtu = bp->dev->mtu;
tstorm_client.statistics_counter_id = BP_CL_ID(bp);
tstorm_client.config_flags =
TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE;
#ifdef BCM_VLAN
- if (bp->rx_mode && bp->vlgrp) {
+ if (bp->rx_mode && bp->vlgrp && (bp->flags & HW_VLAN_RX_FLAG)) {
tstorm_client.config_flags |=
TSTORM_ETH_CLIENT_CONFIG_VLAN_REMOVAL_ENABLE;
DP(NETIF_MSG_IFUP, "vlan removal enabled\n");
@@ -4531,7 +4557,7 @@ static void bnx2x_set_client_config(struct bnx2x *bp)
if (bp->flags & TPA_ENABLE_FLAG) {
tstorm_client.max_sges_for_packet =
- BCM_PAGE_ALIGN(tstorm_client.mtu) >> BCM_PAGE_SHIFT;
+ SGE_PAGE_ALIGN(tstorm_client.mtu) >> SGE_PAGE_SHIFT;
tstorm_client.max_sges_for_packet =
((tstorm_client.max_sges_for_packet +
PAGES_PER_SGE - 1) & (~(PAGES_PER_SGE - 1))) >>
@@ -4714,10 +4740,11 @@ static void bnx2x_init_internal_func(struct bnx2x *bp)
bp->e1hov);
}
- /* Init CQ ring mapping and aggregation size */
- max_agg_size = min((u32)(bp->rx_buf_size +
- 8*BCM_PAGE_SIZE*PAGES_PER_SGE),
- (u32)0xffff);
+ /* Init CQ ring mapping and aggregation size, the FW limit is 8 frags */
+ max_agg_size =
+ min((u32)(min((u32)8, (u32)MAX_SKB_FRAGS) *
+ SGE_PAGE_SIZE * PAGES_PER_SGE),
+ (u32)0xffff);
for_each_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
@@ -4785,6 +4812,15 @@ static void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
bnx2x_init_context(bp);
bnx2x_init_internal(bp, load_code);
bnx2x_init_ind_table(bp);
+ bnx2x_stats_init(bp);
+
+ /* At this point, we are ready for interrupts */
+ atomic_set(&bp->intr_sem, 0);
+
+ /* flush all before enabling interrupts */
+ mb();
+ mmiowb();
+
bnx2x_int_enable(bp);
}
@@ -5134,7 +5170,6 @@ static int bnx2x_init_common(struct bnx2x *bp)
REG_WR(bp, PXP2_REG_RQ_SRC_ENDIAN_M, 1);
REG_WR(bp, PXP2_REG_RQ_CDU_ENDIAN_M, 1);
REG_WR(bp, PXP2_REG_RQ_DBG_ENDIAN_M, 1);
- REG_WR(bp, PXP2_REG_RQ_HC_ENDIAN_M, 1);
/* REG_WR(bp, PXP2_REG_RD_PBF_SWAP_MODE, 1); */
REG_WR(bp, PXP2_REG_RD_QM_SWAP_MODE, 1);
@@ -5212,6 +5247,7 @@ static int bnx2x_init_common(struct bnx2x *bp)
}
bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END);
+ REG_WR(bp, PRS_REG_A_PRSU_20, 0xf);
/* set NIC mode */
REG_WR(bp, PRS_REG_NIC_MODE, 1);
if (CHIP_IS_E1H(bp))
@@ -6393,17 +6429,8 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
}
}
- bnx2x_stats_init(bp);
-
bp->state = BNX2X_STATE_OPENING_WAIT4_PORT;
- /* Enable Rx interrupt handling before sending the ramrod
- as it's completed on Rx FP queue */
- bnx2x_napi_enable(bp);
-
- /* Enable interrupt handling */
- atomic_set(&bp->intr_sem, 0);
-
rc = bnx2x_setup_leading(bp);
if (rc) {
BNX2X_ERR("Setup leading failed!\n");
@@ -7501,7 +7528,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
mutex_init(&bp->port.phy_mutex);
- INIT_WORK(&bp->sp_task, bnx2x_sp_task);
+ INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
INIT_WORK(&bp->reset_task, bnx2x_reset_task);
rc = bnx2x_get_hwinfo(bp);
@@ -8727,6 +8754,8 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
tx_bd->general_data = ((UNICAST_ADDRESS <<
ETH_TX_BD_ETH_ADDR_TYPE_SHIFT) | 1);
+ wmb();
+
fp->hw_tx_prods->bds_prod =
cpu_to_le16(le16_to_cpu(fp->hw_tx_prods->bds_prod) + 1);
mb(); /* FW restriction: must not reorder writing nbd and packets */
@@ -8778,7 +8807,6 @@ test_loopback_rx_exit:
/* Update producers */
bnx2x_update_rx_prod(bp, fp, fp->rx_bd_prod, fp->rx_comp_prod,
fp->rx_sge_prod);
- mmiowb(); /* keep prod updates ordered */
test_loopback_exit:
bp->link_params.loopback_mode = LOOPBACK_NONE;
@@ -9549,11 +9577,14 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
"sending pkt %u @%p next_idx %u bd %u @%p\n",
pkt_prod, tx_buf, fp->tx_pkt_prod, bd_prod, tx_bd);
- if ((bp->vlgrp != NULL) && vlan_tx_tag_present(skb)) {
+#ifdef BCM_VLAN
+ if ((bp->vlgrp != NULL) && vlan_tx_tag_present(skb) &&
+ (bp->flags & HW_VLAN_TX_FLAG)) {
tx_bd->vlan = cpu_to_le16(vlan_tx_tag_get(skb));
tx_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_VLAN_TAG;
vlan_off += 4;
} else
+#endif
tx_bd->vlan = cpu_to_le16(pkt_prod);
if (xmit_type) {
@@ -9705,6 +9736,15 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
DP(NETIF_MSG_TX_QUEUED, "doorbell: nbd %d bd %u\n", nbd, bd_prod);
+ /*
+ * Make sure that the BD data is updated before updating the producer
+ * since FW might read the BD right after the producer is updated.
+ * This is only applicable for weak-ordered memory model archs such
+ * as IA-64. The following barrier is also mandatory since FW will
+ * assumes packets must have BDs.
+ */
+ wmb();
+
fp->hw_tx_prods->bds_prod =
cpu_to_le16(le16_to_cpu(fp->hw_tx_prods->bds_prod) + nbd);
mb(); /* FW restriction: must not reorder writing nbd and packets */
@@ -9718,6 +9758,9 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
if (unlikely(bnx2x_tx_avail(fp) < MAX_SKB_FRAGS + 3)) {
+ /* We want bnx2x_tx_int to "see" the updated tx_bd_prod
+ if we put Tx into XOFF state. */
+ smp_mb();
netif_stop_queue(dev);
bp->eth_stats.driver_xoff++;
if (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3)
@@ -9987,6 +10030,16 @@ static void bnx2x_vlan_rx_register(struct net_device *dev,
struct bnx2x *bp = netdev_priv(dev);
bp->vlgrp = vlgrp;
+
+ /* Set flags according to the required capabilities */
+ bp->flags &= ~(HW_VLAN_RX_FLAG | HW_VLAN_TX_FLAG);
+
+ if (dev->features & NETIF_F_HW_VLAN_TX)
+ bp->flags |= HW_VLAN_TX_FLAG;
+
+ if (dev->features & NETIF_F_HW_VLAN_RX)
+ bp->flags |= HW_VLAN_RX_FLAG;
+
if (netif_running(dev))
bnx2x_set_client_config(bp);
}
@@ -10143,6 +10196,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
dev->features |= NETIF_F_HIGHDMA;
#ifdef BCM_VLAN
dev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
+ bp->flags |= (HW_VLAN_RX_FLAG | HW_VLAN_TX_FLAG);
#endif
dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
dev->features |= NETIF_F_TSO6;
@@ -10519,12 +10573,20 @@ static struct pci_driver bnx2x_pci_driver = {
static int __init bnx2x_init(void)
{
+ bnx2x_wq = create_singlethread_workqueue("bnx2x");
+ if (bnx2x_wq == NULL) {
+ printk(KERN_ERR PFX "Cannot create workqueue\n");
+ return -ENOMEM;
+ }
+
return pci_register_driver(&bnx2x_pci_driver);
}
static void __exit bnx2x_cleanup(void)
{
pci_unregister_driver(&bnx2x_pci_driver);
+
+ destroy_workqueue(bnx2x_wq);
}
module_init(bnx2x_init);
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
index 5b346f9..a89d8cc 100644
--- a/drivers/net/cxgb3/adapter.h
+++ b/drivers/net/cxgb3/adapter.h
@@ -50,12 +50,17 @@ struct vlan_group;
struct adapter;
struct sge_qset;
+enum { /* rx_offload flags */
+ T3_RX_CSUM = 1 << 0,
+ T3_LRO = 1 << 1,
+};
+
struct port_info {
struct adapter *adapter;
struct vlan_group *vlan_grp;
struct sge_qset *qs;
u8 port_id;
- u8 rx_csum_offload;
+ u8 rx_offload;
u8 nqsets;
u8 first_qset;
struct cphy phy;
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index 2847f94..0089746 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -546,7 +546,7 @@ static int setup_sge_qsets(struct adapter *adap)
pi->qs = &adap->sge.qs[pi->first_qset];
for (j = pi->first_qset; j < pi->first_qset + pi->nqsets;
++j, ++qset_idx) {
- set_qset_lro(dev, qset_idx, pi->rx_csum_offload);
+ set_qset_lro(dev, qset_idx, pi->rx_offload & T3_LRO);
err = t3_sge_alloc_qset(adap, qset_idx, 1,
(adap->flags & USING_MSIX) ? qset_idx + 1 :
irq_idx,
@@ -1657,17 +1657,19 @@ static u32 get_rx_csum(struct net_device *dev)
{
struct port_info *p = netdev_priv(dev);
- return p->rx_csum_offload;
+ return p->rx_offload & T3_RX_CSUM;
}
static int set_rx_csum(struct net_device *dev, u32 data)
{
struct port_info *p = netdev_priv(dev);
- p->rx_csum_offload = data;
- if (!data) {
+ if (data) {
+ p->rx_offload |= T3_RX_CSUM;
+ } else {
int i;
+ p->rx_offload &= ~(T3_RX_CSUM | T3_LRO);
for (i = p->first_qset; i < p->first_qset + p->nqsets; i++)
set_qset_lro(dev, i, 0);
}
@@ -1830,15 +1832,18 @@ static int cxgb3_set_flags(struct net_device *dev, u32 data)
int i;
if (data & ETH_FLAG_LRO) {
- if (!pi->rx_csum_offload)
+ if (!(pi->rx_offload & T3_RX_CSUM))
return -EINVAL;
+ pi->rx_offload |= T3_LRO;
for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++)
set_qset_lro(dev, i, 1);
- } else
+ } else {
+ pi->rx_offload &= ~T3_LRO;
for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++)
set_qset_lro(dev, i, 0);
+ }
return 0;
}
@@ -1926,7 +1931,7 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
pi = adap2pinfo(adapter, i);
if (t.qset_idx >= pi->first_qset &&
t.qset_idx < pi->first_qset + pi->nqsets &&
- !pi->rx_csum_offload)
+ !(pi->rx_offload & T3_RX_CSUM))
return -EINVAL;
}
@@ -2946,7 +2951,7 @@ static int __devinit init_one(struct pci_dev *pdev,
adapter->port[i] = netdev;
pi = netdev_priv(netdev);
pi->adapter = adapter;
- pi->rx_csum_offload = 1;
+ pi->rx_offload = T3_RX_CSUM | T3_LRO;
pi->port_id = i;
netif_carrier_off(netdev);
netif_tx_stop_all_queues(netdev);
@@ -2955,6 +2960,7 @@ static int __devinit init_one(struct pci_dev *pdev,
netdev->mem_end = mmio_start + mmio_len - 1;
netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
netdev->features |= NETIF_F_LLTX;
+ netdev->features |= NETIF_F_LRO;
if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index 6c641a8..14f9fb3 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -1932,7 +1932,7 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
skb_pull(skb, sizeof(*p) + pad);
skb->protocol = eth_type_trans(skb, adap->port[p->iff]);
pi = netdev_priv(skb->dev);
- if (pi->rx_csum_offload && p->csum_valid && p->csum == htons(0xffff) &&
+ if ((pi->rx_offload & T3_RX_CSUM) && p->csum_valid && p->csum == htons(0xffff) &&
!p->fragment) {
qs->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++;
skb->ip_summed = CHECKSUM_UNNECESSARY;
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index f2a5963..e415e81 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -390,7 +390,8 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
}
static DEFINE_MUTEX(nvm_mutex);
-static pid_t nvm_owner = -1;
+static pid_t nvm_owner_pid = -1;
+static char nvm_owner_name[TASK_COMM_LEN] = "";
/**
* e1000_acquire_swflag_ich8lan - Acquire software control flag
@@ -408,11 +409,15 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
might_sleep();
if (!mutex_trylock(&nvm_mutex)) {
- WARN(1, KERN_ERR "e1000e mutex contention. Owned by pid %d\n",
- nvm_owner);
+ WARN(1, KERN_ERR "e1000e mutex contention. Owned by process "
+ "%s (pid %d), required by process %s (pid %d)\n",
+ nvm_owner_name, nvm_owner_pid,
+ current->comm, current->pid);
+
mutex_lock(&nvm_mutex);
}
- nvm_owner = current->pid;
+ nvm_owner_pid = current->pid;
+ strncpy(nvm_owner_name, current->comm, TASK_COMM_LEN);
while (timeout) {
extcnf_ctrl = er32(EXTCNF_CTRL);
@@ -430,7 +435,8 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
hw_dbg(hw, "FW or HW has locked the resource for too long.\n");
extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
ew32(EXTCNF_CTRL, extcnf_ctrl);
- nvm_owner = -1;
+ nvm_owner_pid = -1;
+ strcpy(nvm_owner_name, "");
mutex_unlock(&nvm_mutex);
return -E1000_ERR_CONFIG;
}
@@ -454,7 +460,8 @@ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw)
extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
ew32(EXTCNF_CTRL, extcnf_ctrl);
- nvm_owner = -1;
+ nvm_owner_pid = -1;
+ strcpy(nvm_owner_name, "");
mutex_unlock(&nvm_mutex);
}
diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c
index 20eb05c..b07ba19 100644
--- a/drivers/net/e2100.c
+++ b/drivers/net/e2100.c
@@ -169,6 +169,7 @@ static const struct net_device_ops e21_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index e3131ea..dfe9226 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -132,7 +132,7 @@ void ehea_dump(void *adr, int len, char *msg)
int x;
unsigned char *deb = adr;
for (x = 0; x < len; x += 16) {
- printk(DRV_NAME " %s adr=%p ofs=%04x %016lx %016lx\n", msg,
+ printk(DRV_NAME " %s adr=%p ofs=%04x %016llx %016llx\n", msg,
deb, x, *((u64 *)&deb[0]), *((u64 *)&deb[8]));
deb += 16;
}
@@ -883,7 +883,7 @@ static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param)
while (eqe) {
qp_token = EHEA_BMASK_GET(EHEA_EQE_QP_TOKEN, eqe->entry);
- ehea_error("QP aff_err: entry=0x%lx, token=0x%x",
+ ehea_error("QP aff_err: entry=0x%llx, token=0x%x",
eqe->entry, qp_token);
qp = port->port_res[qp_token].qp;
@@ -1159,7 +1159,7 @@ static void ehea_parse_eqe(struct ehea_adapter *adapter, u64 eqe)
netif_stop_queue(port->netdev);
break;
default:
- ehea_error("unknown event code %x, eqe=0x%lX", ec, eqe);
+ ehea_error("unknown event code %x, eqe=0x%llX", ec, eqe);
break;
}
}
@@ -1971,7 +1971,7 @@ static void ehea_set_multicast_list(struct net_device *dev)
}
if (dev->mc_count > port->adapter->max_mc_mac) {
- ehea_info("Mcast registration limit reached (0x%lx). "
+ ehea_info("Mcast registration limit reached (0x%llx). "
"Use ALLMULTI!",
port->adapter->max_mc_mac);
goto out;
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c
index 225c692..49d766e 100644
--- a/drivers/net/ehea/ehea_qmr.c
+++ b/drivers/net/ehea/ehea_qmr.c
@@ -168,7 +168,7 @@ struct ehea_cq *ehea_create_cq(struct ehea_adapter *adapter,
cq->fw_handle, rpage, 1);
if (hret < H_SUCCESS) {
ehea_error("register_rpage_cq failed ehea_cq=%p "
- "hret=%lx counter=%i act_pages=%i",
+ "hret=%llx counter=%i act_pages=%i",
cq, hret, counter, cq->attr.nr_pages);
goto out_kill_hwq;
}
@@ -178,13 +178,13 @@ struct ehea_cq *ehea_create_cq(struct ehea_adapter *adapter,
if ((hret != H_SUCCESS) || (vpage)) {
ehea_error("registration of pages not "
- "complete hret=%lx\n", hret);
+ "complete hret=%llx\n", hret);
goto out_kill_hwq;
}
} else {
if (hret != H_PAGE_REGISTERED) {
ehea_error("CQ: registration of page failed "
- "hret=%lx\n", hret);
+ "hret=%llx\n", hret);
goto out_kill_hwq;
}
}
@@ -986,15 +986,15 @@ void print_error_data(u64 *data)
length = EHEA_PAGESIZE;
if (type == 0x8) /* Queue Pair */
- ehea_error("QP (resource=%lX) state: AER=0x%lX, AERR=0x%lX, "
- "port=%lX", resource, data[6], data[12], data[22]);
+ ehea_error("QP (resource=%llX) state: AER=0x%llX, AERR=0x%llX, "
+ "port=%llX", resource, data[6], data[12], data[22]);
if (type == 0x4) /* Completion Queue */
- ehea_error("CQ (resource=%lX) state: AER=0x%lX", resource,
+ ehea_error("CQ (resource=%llX) state: AER=0x%llX", resource,
data[6]);
if (type == 0x3) /* Event Queue */
- ehea_error("EQ (resource=%lX) state: AER=0x%lX", resource,
+ ehea_error("EQ (resource=%llX) state: AER=0x%llX", resource,
data[6]);
ehea_dump(data, length, "error data");
@@ -1016,11 +1016,11 @@ void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle)
rblock);
if (ret == H_R_STATE)
- ehea_error("No error data is available: %lX.", res_handle);
+ ehea_error("No error data is available: %llX.", res_handle);
else if (ret == H_SUCCESS)
print_error_data(rblock);
else
- ehea_error("Error data could not be fetched: %lX", res_handle);
+ ehea_error("Error data could not be fetched: %llX", res_handle);
kfree(rblock);
}
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index d039e16..7d60551 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -1599,6 +1599,7 @@ static const struct net_device_ops enic_netdev_ops = {
.ndo_start_xmit = enic_hard_start_xmit,
.ndo_get_stats = enic_get_stats,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_set_multicast_list = enic_set_multicast_list,
.ndo_change_mtu = enic_change_mtu,
.ndo_vlan_rx_register = enic_vlan_rx_register,
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 5b68dc2..5b910cf 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -13,7 +13,7 @@
* Copyright (C) 2004 Andrew de Quincey (wol support)
* Copyright (C) 2004 Carl-Daniel Hailfinger (invalid MAC handling, insane
* IRQ rate fixes, bigendian fixes, cleanups, verification)
- * Copyright (c) 2004,2005,2006,2007,2008 NVIDIA Corporation
+ * Copyright (c) 2004,2005,2006,2007,2008,2009 NVIDIA Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -39,7 +39,7 @@
* DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
* superfluous timer interrupts from the nic.
*/
-#define FORCEDETH_VERSION "0.61"
+#define FORCEDETH_VERSION "0.62"
#define DRV_NAME "forcedeth"
#include <linux/module.h>
@@ -2096,14 +2096,15 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
((skb_shinfo(skb)->frags[i].size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
}
+ spin_lock_irqsave(&np->lock, flags);
empty_slots = nv_get_empty_tx_slots(np);
if (unlikely(empty_slots <= entries)) {
- spin_lock_irqsave(&np->lock, flags);
netif_stop_queue(dev);
np->tx_stop = 1;
spin_unlock_irqrestore(&np->lock, flags);
return NETDEV_TX_BUSY;
}
+ spin_unlock_irqrestore(&np->lock, flags);
start_tx = put_tx = np->put_tx.orig;
@@ -2214,14 +2215,15 @@ static int nv_start_xmit_optimized(struct sk_buff *skb, struct net_device *dev)
((skb_shinfo(skb)->frags[i].size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
}
+ spin_lock_irqsave(&np->lock, flags);
empty_slots = nv_get_empty_tx_slots(np);
if (unlikely(empty_slots <= entries)) {
- spin_lock_irqsave(&np->lock, flags);
netif_stop_queue(dev);
np->tx_stop = 1;
spin_unlock_irqrestore(&np->lock, flags);
return NETDEV_TX_BUSY;
}
+ spin_unlock_irqrestore(&np->lock, flags);
start_tx = put_tx = np->put_tx.ex;
start_tx_ctx = np->put_tx_ctx;
@@ -3403,10 +3405,10 @@ static irqreturn_t nv_nic_irq(int foo, void *data)
#ifdef CONFIG_FORCEDETH_NAPI
if (events & NVREG_IRQ_RX_ALL) {
+ spin_lock(&np->lock);
netif_rx_schedule(&np->napi);
/* Disable furthur receive irq's */
- spin_lock(&np->lock);
np->irqmask &= ~NVREG_IRQ_RX_ALL;
if (np->msi_flags & NV_MSI_X_ENABLED)
@@ -3520,10 +3522,10 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data)
#ifdef CONFIG_FORCEDETH_NAPI
if (events & NVREG_IRQ_RX_ALL) {
+ spin_lock(&np->lock);
netif_rx_schedule(&np->napi);
/* Disable furthur receive irq's */
- spin_lock(&np->lock);
np->irqmask &= ~NVREG_IRQ_RX_ALL;
if (np->msi_flags & NV_MSI_X_ENABLED)
@@ -6167,19 +6169,19 @@ static struct pci_device_id pci_tbl[] = {
},
{ /* MCP79 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36),
- .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
},
{ /* MCP79 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
},
{ /* MCP79 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_38),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
},
{ /* MCP79 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_39),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
},
{0,},
};
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 4e6a919..ce900e5 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -795,6 +795,7 @@ static int fs_enet_open(struct net_device *dev)
err = fs_init_phy(dev);
if (err) {
+ free_irq(fep->interrupt, dev);
if (fep->fpi->use_napi)
napi_disable(&fep->napi);
return err;
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 1b8deca..ea53067 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -296,6 +296,20 @@ err_out:
return err;
}
+/* Ioctl MII Interface */
+static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+
+ if (!netif_running(dev))
+ return -EINVAL;
+
+ if (!priv->phydev)
+ return -ENODEV;
+
+ return phy_mii_ioctl(priv->phydev, if_mii(rq), cmd);
+}
+
/* Set up the ethernet device structure, private data,
* and anything else we need before we start */
static int gfar_probe(struct of_device *ofdev,
@@ -366,6 +380,7 @@ static int gfar_probe(struct of_device *ofdev,
dev->set_multicast_list = gfar_set_multi;
dev->ethtool_ops = &gfar_ethtool_ops;
+ dev->do_ioctl = gfar_ioctl;
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) {
priv->rx_csum_enable = 1;
@@ -1607,10 +1622,18 @@ static int gfar_clean_tx_ring(struct net_device *dev)
static void gfar_schedule_cleanup(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->txlock, flags);
+ spin_lock(&priv->rxlock);
+
if (netif_rx_schedule_prep(&priv->napi)) {
gfar_write(&priv->regs->imask, IMASK_RTX_DISABLED);
__netif_rx_schedule(&priv->napi);
}
+
+ spin_unlock(&priv->rxlock);
+ spin_unlock_irqrestore(&priv->txlock, flags);
}
/* Interrupt Handler for Transmit complete */
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index 3220022..7e8b3c5 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -576,6 +576,7 @@ static const struct net_device_ops hamachi_netdev_ops = {
.ndo_set_multicast_list = set_rx_mode,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_tx_timeout = hamachi_tx_timeout,
.ndo_do_ioctl = netdev_ioctl,
};
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 50f1e17..2d40898 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -717,11 +717,12 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct sixpack *sp = sp_get(tty);
- struct net_device *dev = sp->dev;
+ struct net_device *dev;
unsigned int tmp, err;
if (!sp)
return -ENXIO;
+ dev = sp->dev;
switch(cmd) {
case SIOCGIFNAME:
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
index b507dbc..5e070f4 100644
--- a/drivers/net/hp-plus.c
+++ b/drivers/net/hp-plus.c
@@ -166,6 +166,7 @@ static const struct net_device_ops hpp_netdev_ops = {
.ndo_get_stats = eip_get_stats,
.ndo_set_multicast_list = eip_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = eip_poll,
diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c
index 9cb38a8..8ac0930 100644
--- a/drivers/net/hydra.c
+++ b/drivers/net/hydra.c
@@ -103,6 +103,7 @@ static const struct net_device_ops hydra_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c
index ecf9798..2a2fc17 100644
--- a/drivers/net/ibm_newemac/mal.c
+++ b/drivers/net/ibm_newemac/mal.c
@@ -613,7 +613,9 @@ static int __devinit mal_probe(struct of_device *ofdev,
INIT_LIST_HEAD(&mal->list);
spin_lock_init(&mal->lock);
- netif_napi_add(NULL, &mal->napi, mal_poll,
+ init_dummy_netdev(&mal->dummy_dev);
+
+ netif_napi_add(&mal->dummy_dev, &mal->napi, mal_poll,
CONFIG_IBM_NEW_EMAC_POLL_WEIGHT);
/* Load power-on reset defaults */
diff --git a/drivers/net/ibm_newemac/mal.h b/drivers/net/ibm_newemac/mal.h
index 2f0a873..9ededfb 100644
--- a/drivers/net/ibm_newemac/mal.h
+++ b/drivers/net/ibm_newemac/mal.h
@@ -214,6 +214,8 @@ struct mal_instance {
int index;
spinlock_t lock;
+ struct net_device dummy_dev;
+
unsigned int features;
};
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index ca3bb9f..dfa6348 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -602,7 +602,7 @@ static int ibmveth_open(struct net_device *netdev)
if(lpar_rc != H_SUCCESS) {
ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc);
- ibmveth_error_printk("buffer TCE:0x%lx filter TCE:0x%lx rxq desc:0x%lx MAC:0x%lx\n",
+ ibmveth_error_printk("buffer TCE:0x%llx filter TCE:0x%llx rxq desc:0x%llx MAC:0x%llx\n",
adapter->buffer_list_dma,
adapter->filter_list_dma,
rxq_desc.desc,
@@ -1378,13 +1378,13 @@ static int ibmveth_show(struct seq_file *seq, void *v)
seq_printf(seq, "Firmware MAC: %pM\n", firmware_mac);
seq_printf(seq, "\nAdapter Statistics:\n");
- seq_printf(seq, " TX: vio_map_single failres: %ld\n", adapter->tx_map_failed);
- seq_printf(seq, " send failures: %ld\n", adapter->tx_send_failed);
- seq_printf(seq, " RX: replenish task cycles: %ld\n", adapter->replenish_task_cycles);
- seq_printf(seq, " alloc_skb_failures: %ld\n", adapter->replenish_no_mem);
- seq_printf(seq, " add buffer failures: %ld\n", adapter->replenish_add_buff_failure);
- seq_printf(seq, " invalid buffers: %ld\n", adapter->rx_invalid_buffer);
- seq_printf(seq, " no buffers: %ld\n", adapter->rx_no_buffer);
+ seq_printf(seq, " TX: vio_map_single failres: %lld\n", adapter->tx_map_failed);
+ seq_printf(seq, " send failures: %lld\n", adapter->tx_send_failed);
+ seq_printf(seq, " RX: replenish task cycles: %lld\n", adapter->replenish_task_cycles);
+ seq_printf(seq, " alloc_skb_failures: %lld\n", adapter->replenish_no_mem);
+ seq_printf(seq, " add buffer failures: %lld\n", adapter->replenish_add_buff_failure);
+ seq_printf(seq, " invalid buffers: %lld\n", adapter->rx_invalid_buffer);
+ seq_printf(seq, " no buffers: %lld\n", adapter->rx_no_buffer);
return 0;
}
diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c
index 75a1d0a..9411640 100644
--- a/drivers/net/irda/au1k_ir.c
+++ b/drivers/net/irda/au1k_ir.c
@@ -594,7 +594,7 @@ static int au1k_irda_rx(struct net_device *dev)
update_rx_stats(dev, flags, count);
skb=alloc_skb(count+1,GFP_ATOMIC);
if (skb == NULL) {
- aup->stats.rx_dropped++;
+ aup->netdev->stats.rx_dropped++;
continue;
}
skb_reserve(skb, 1);
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index 687c2d5..6f3e7f7 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -1194,13 +1194,13 @@ toshoboe_interrupt (int irq, void *dev_id)
txp = txpc;
txpc++;
txpc %= TX_SLOTS;
- self->stats.tx_packets++;
+ self->netdev->stats.tx_packets++;
if (self->ring->tx[txpc].control & OBOE_CTL_TX_HW_OWNS)
self->ring->tx[txp].control &= ~OBOE_CTL_TX_RTCENTX;
}
- self->stats.tx_packets--;
+ self->netdev->stats.tx_packets--;
#else
- self->stats.tx_packets++;
+ self->netdev->stats.tx_packets++;
#endif
toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX);
}
@@ -1280,7 +1280,7 @@ dumpbufs(self->rx_bufs[self->rxs],len,'<');
skb_put (skb, len);
skb_copy_to_linear_data(skb, self->rx_bufs[self->rxs],
len);
- self->stats.rx_packets++;
+ self->netdev->stats.rx_packets++;
skb->dev = self->netdev;
skb_reset_mac_header(skb);
skb->protocol = htons (ETH_P_IRDA);
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 29118f5..3a22dc4 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1073,7 +1073,7 @@ static int stir421x_patch_device(struct irda_usb_cb *self)
{
unsigned int i;
int ret;
- char stir421x_fw_name[11];
+ char stir421x_fw_name[12];
const struct firmware *fw;
const unsigned char *fw_version_ptr; /* pointer to version string */
unsigned long fw_version = 0;
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index c7457f9..cb793c2 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -429,7 +429,7 @@ SIMPLE_PORT_ATTR(promiscuous);
SIMPLE_PORT_ATTR(num_mcast);
CUSTOM_PORT_ATTR(lpar_map, "0x%X\n", port->lpar_map);
CUSTOM_PORT_ATTR(stopped_map, "0x%X\n", port->stopped_map);
-CUSTOM_PORT_ATTR(mac_addr, "0x%lX\n", port->mac_addr);
+CUSTOM_PORT_ATTR(mac_addr, "0x%llX\n", port->mac_addr);
#define GET_PORT_ATTR(_name) (&veth_port_attr_##_name.attr)
static struct attribute *veth_port_default_attrs[] = {
diff --git a/drivers/net/korina.c b/drivers/net/korina.c
index 4a5580c..1d6e48e 100644
--- a/drivers/net/korina.c
+++ b/drivers/net/korina.c
@@ -84,7 +84,10 @@
#define KORINA_NUM_RDS 64 /* number of receive descriptors */
#define KORINA_NUM_TDS 64 /* number of transmit descriptors */
-#define KORINA_RBSIZE 536 /* size of one resource buffer = Ether MTU */
+/* KORINA_RBSIZE is the hardware's default maximum receive
+ * frame size in bytes. Having this hardcoded means that there
+ * is no support for MTU sizes greater than 1500. */
+#define KORINA_RBSIZE 1536 /* size of one resource buffer = Ether MTU */
#define KORINA_RDS_MASK (KORINA_NUM_RDS - 1)
#define KORINA_TDS_MASK (KORINA_NUM_TDS - 1)
#define RD_RING_SIZE (KORINA_NUM_RDS * sizeof(struct dma_desc))
@@ -196,7 +199,7 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
struct korina_private *lp = netdev_priv(dev);
unsigned long flags;
u32 length;
- u32 chain_index;
+ u32 chain_prev, chain_next;
struct dma_desc *td;
spin_lock_irqsave(&lp->lock, flags);
@@ -228,8 +231,8 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
/* Setup the transmit descriptor. */
dma_cache_inv((u32) td, sizeof(*td));
td->ca = CPHYSADDR(skb->data);
- chain_index = (lp->tx_chain_tail - 1) &
- KORINA_TDS_MASK;
+ chain_prev = (lp->tx_chain_tail - 1) & KORINA_TDS_MASK;
+ chain_next = (lp->tx_chain_tail + 1) & KORINA_TDS_MASK;
if (readl(&(lp->tx_dma_regs->dmandptr)) == 0) {
if (lp->tx_chain_status == desc_empty) {
@@ -237,7 +240,7 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
td->control = DMA_COUNT(length) |
DMA_DESC_COF | DMA_DESC_IOF;
/* Move tail */
- lp->tx_chain_tail = chain_index;
+ lp->tx_chain_tail = chain_next;
/* Write to NDPTR */
writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
&lp->tx_dma_regs->dmandptr);
@@ -248,12 +251,12 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
td->control = DMA_COUNT(length) |
DMA_DESC_COF | DMA_DESC_IOF;
/* Link to prev */
- lp->td_ring[chain_index].control &=
+ lp->td_ring[chain_prev].control &=
~DMA_DESC_COF;
/* Link to prev */
- lp->td_ring[chain_index].link = CPHYSADDR(td);
+ lp->td_ring[chain_prev].link = CPHYSADDR(td);
/* Move tail */
- lp->tx_chain_tail = chain_index;
+ lp->tx_chain_tail = chain_next;
/* Write to NDPTR */
writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
&(lp->tx_dma_regs->dmandptr));
@@ -267,17 +270,16 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
td->control = DMA_COUNT(length) |
DMA_DESC_COF | DMA_DESC_IOF;
/* Move tail */
- lp->tx_chain_tail = chain_index;
+ lp->tx_chain_tail = chain_next;
lp->tx_chain_status = desc_filled;
- netif_stop_queue(dev);
} else {
/* Update tail */
td->control = DMA_COUNT(length) |
DMA_DESC_COF | DMA_DESC_IOF;
- lp->td_ring[chain_index].control &=
+ lp->td_ring[chain_prev].control &=
~DMA_DESC_COF;
- lp->td_ring[chain_index].link = CPHYSADDR(td);
- lp->tx_chain_tail = chain_index;
+ lp->td_ring[chain_prev].link = CPHYSADDR(td);
+ lp->tx_chain_tail = chain_next;
}
}
dma_cache_wback((u32) td, sizeof(*td));
@@ -327,13 +329,13 @@ static irqreturn_t korina_rx_dma_interrupt(int irq, void *dev_id)
dmas = readl(&lp->rx_dma_regs->dmas);
if (dmas & (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR)) {
- netif_rx_schedule_prep(&lp->napi);
-
dmasm = readl(&lp->rx_dma_regs->dmasm);
writel(dmasm | (DMA_STAT_DONE |
DMA_STAT_HALT | DMA_STAT_ERR),
&lp->rx_dma_regs->dmasm);
+ netif_rx_schedule(&lp->napi);
+
if (dmas & DMA_STAT_ERR)
printk(KERN_ERR DRV_NAME "%s: DMA error\n", dev->name);
@@ -350,15 +352,20 @@ static int korina_rx(struct net_device *dev, int limit)
struct dma_desc *rd = &lp->rd_ring[lp->rx_next_done];
struct sk_buff *skb, *skb_new;
u8 *pkt_buf;
- u32 devcs, pkt_len, dmas, rx_free_desc;
+ u32 devcs, pkt_len, dmas;
int count;
dma_cache_inv((u32)rd, sizeof(*rd));
for (count = 0; count < limit; count++) {
+ skb = lp->rx_skb[lp->rx_next_done];
+ skb_new = NULL;
devcs = rd->devcs;
+ if ((KORINA_RBSIZE - (u32)DMA_COUNT(rd->control)) == 0)
+ break;
+
/* Update statistics counters */
if (devcs & ETH_RX_CRC)
dev->stats.rx_crc_errors++;
@@ -381,63 +388,55 @@ static int korina_rx(struct net_device *dev, int limit)
* in Rc32434 (errata ref #077) */
dev->stats.rx_errors++;
dev->stats.rx_dropped++;
- }
-
- while ((rx_free_desc = KORINA_RBSIZE - (u32)DMA_COUNT(rd->control)) != 0) {
- /* init the var. used for the later
- * operations within the while loop */
- skb_new = NULL;
+ } else if ((devcs & ETH_RX_ROK)) {
pkt_len = RCVPKT_LENGTH(devcs);
- skb = lp->rx_skb[lp->rx_next_done];
-
- if ((devcs & ETH_RX_ROK)) {
- /* must be the (first and) last
- * descriptor then */
- pkt_buf = (u8 *)lp->rx_skb[lp->rx_next_done]->data;
-
- /* invalidate the cache */
- dma_cache_inv((unsigned long)pkt_buf, pkt_len - 4);
-
- /* Malloc up new buffer. */
- skb_new = netdev_alloc_skb(dev, KORINA_RBSIZE + 2);
-
- if (!skb_new)
- break;
- /* Do not count the CRC */
- skb_put(skb, pkt_len - 4);
- skb->protocol = eth_type_trans(skb, dev);
-
- /* Pass the packet to upper layers */
- netif_receive_skb(skb);
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += pkt_len;
-
- /* Update the mcast stats */
- if (devcs & ETH_RX_MP)
- dev->stats.multicast++;
-
- lp->rx_skb[lp->rx_next_done] = skb_new;
- }
-
- rd->devcs = 0;
-
- /* Restore descriptor's curr_addr */
- if (skb_new)
- rd->ca = CPHYSADDR(skb_new->data);
- else
- rd->ca = CPHYSADDR(skb->data);
-
- rd->control = DMA_COUNT(KORINA_RBSIZE) |
- DMA_DESC_COD | DMA_DESC_IOD;
- lp->rd_ring[(lp->rx_next_done - 1) &
- KORINA_RDS_MASK].control &=
- ~DMA_DESC_COD;
-
- lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK;
- dma_cache_wback((u32)rd, sizeof(*rd));
- rd = &lp->rd_ring[lp->rx_next_done];
- writel(~DMA_STAT_DONE, &lp->rx_dma_regs->dmas);
+
+ /* must be the (first and) last
+ * descriptor then */
+ pkt_buf = (u8 *)lp->rx_skb[lp->rx_next_done]->data;
+
+ /* invalidate the cache */
+ dma_cache_inv((unsigned long)pkt_buf, pkt_len - 4);
+
+ /* Malloc up new buffer. */
+ skb_new = netdev_alloc_skb(dev, KORINA_RBSIZE + 2);
+
+ if (!skb_new)
+ break;
+ /* Do not count the CRC */
+ skb_put(skb, pkt_len - 4);
+ skb->protocol = eth_type_trans(skb, dev);
+
+ /* Pass the packet to upper layers */
+ netif_receive_skb(skb);
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += pkt_len;
+
+ /* Update the mcast stats */
+ if (devcs & ETH_RX_MP)
+ dev->stats.multicast++;
+
+ lp->rx_skb[lp->rx_next_done] = skb_new;
}
+
+ rd->devcs = 0;
+
+ /* Restore descriptor's curr_addr */
+ if (skb_new)
+ rd->ca = CPHYSADDR(skb_new->data);
+ else
+ rd->ca = CPHYSADDR(skb->data);
+
+ rd->control = DMA_COUNT(KORINA_RBSIZE) |
+ DMA_DESC_COD | DMA_DESC_IOD;
+ lp->rd_ring[(lp->rx_next_done - 1) &
+ KORINA_RDS_MASK].control &=
+ ~DMA_DESC_COD;
+
+ lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK;
+ dma_cache_wback((u32)rd, sizeof(*rd));
+ rd = &lp->rd_ring[lp->rx_next_done];
+ writel(~DMA_STAT_DONE, &lp->rx_dma_regs->dmas);
}
dmas = readl(&lp->rx_dma_regs->dmas);
@@ -623,12 +622,12 @@ korina_tx_dma_interrupt(int irq, void *dev_id)
dmas = readl(&lp->tx_dma_regs->dmas);
if (dmas & (DMA_STAT_FINI | DMA_STAT_ERR)) {
- korina_tx(dev);
-
dmasm = readl(&lp->tx_dma_regs->dmasm);
writel(dmasm | (DMA_STAT_FINI | DMA_STAT_ERR),
&lp->tx_dma_regs->dmasm);
+ korina_tx(dev);
+
if (lp->tx_chain_status == desc_filled &&
(readl(&(lp->tx_dma_regs->dmandptr)) == 0)) {
writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
@@ -901,6 +900,8 @@ static int korina_restart(struct net_device *dev)
korina_free_ring(dev);
+ napi_disable(&lp->napi);
+
ret = korina_init(dev);
if (ret < 0) {
printk(KERN_ERR DRV_NAME "%s: cannot restart device\n",
@@ -999,14 +1000,14 @@ static int korina_open(struct net_device *dev)
* that handles the Done Finished
* Ovr and Und Events */
ret = request_irq(lp->rx_irq, &korina_rx_dma_interrupt,
- IRQF_SHARED | IRQF_DISABLED, "Korina ethernet Rx", dev);
+ IRQF_DISABLED, "Korina ethernet Rx", dev);
if (ret < 0) {
printk(KERN_ERR DRV_NAME "%s: unable to get Rx DMA IRQ %d\n",
dev->name, lp->rx_irq);
goto err_release;
}
ret = request_irq(lp->tx_irq, &korina_tx_dma_interrupt,
- IRQF_SHARED | IRQF_DISABLED, "Korina ethernet Tx", dev);
+ IRQF_DISABLED, "Korina ethernet Tx", dev);
if (ret < 0) {
printk(KERN_ERR DRV_NAME "%s: unable to get Tx DMA IRQ %d\n",
dev->name, lp->tx_irq);
@@ -1015,7 +1016,7 @@ static int korina_open(struct net_device *dev)
/* Install handler for overrun error. */
ret = request_irq(lp->ovr_irq, &korina_ovr_interrupt,
- IRQF_SHARED | IRQF_DISABLED, "Ethernet Overflow", dev);
+ IRQF_DISABLED, "Ethernet Overflow", dev);
if (ret < 0) {
printk(KERN_ERR DRV_NAME"%s: unable to get OVR IRQ %d\n",
dev->name, lp->ovr_irq);
@@ -1024,7 +1025,7 @@ static int korina_open(struct net_device *dev)
/* Install handler for underflow error. */
ret = request_irq(lp->und_irq, &korina_und_interrupt,
- IRQF_SHARED | IRQF_DISABLED, "Ethernet Underflow", dev);
+ IRQF_DISABLED, "Ethernet Underflow", dev);
if (ret < 0) {
printk(KERN_ERR DRV_NAME "%s: unable to get UND IRQ %d\n",
dev->name, lp->und_irq);
@@ -1067,6 +1068,8 @@ static int korina_close(struct net_device *dev)
korina_free_ring(dev);
+ napi_disable(&lp->napi);
+
free_irq(lp->rx_irq, dev);
free_irq(lp->tx_irq, dev);
free_irq(lp->ovr_irq, dev);
@@ -1089,7 +1092,6 @@ static int korina_probe(struct platform_device *pdev)
return -ENOMEM;
}
SET_NETDEV_DEV(dev, &pdev->dev);
- platform_set_drvdata(pdev, dev);
lp = netdev_priv(dev);
bif->dev = dev;
diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c
index 57716e2..8e88486 100644
--- a/drivers/net/mac8390.c
+++ b/drivers/net/mac8390.c
@@ -486,6 +486,7 @@ static const struct net_device_ops mac8390_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 15bb38d9..9f6644a 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -952,6 +952,7 @@ static const struct net_device_ops mlx4_netdev_ops = {
.ndo_get_stats = mlx4_en_get_stats,
.ndo_set_multicast_list = mlx4_en_set_multicast,
.ndo_set_mac_address = mlx4_en_set_mac,
+ .ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = mlx4_en_change_mtu,
.ndo_tx_timeout = mlx4_en_tx_timeout,
.ndo_vlan_rx_register = mlx4_en_vlan_rx_register,
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 710c79e..6ef2490 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -912,8 +912,8 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
int i;
if (msi_x) {
- nreq = min(dev->caps.num_eqs - dev->caps.reserved_eqs,
- num_possible_cpus() + 1);
+ nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs,
+ num_possible_cpus() + 1);
entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL);
if (!entries)
goto no_msi;
diff --git a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c
index b572391..7bd6662 100644
--- a/drivers/net/ne-h8300.c
+++ b/drivers/net/ne-h8300.c
@@ -202,6 +202,7 @@ static const struct net_device_ops ne_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
index 62f20ba..f090d3b 100644
--- a/drivers/net/ne2k-pci.c
+++ b/drivers/net/ne2k-pci.c
@@ -208,6 +208,7 @@ static const struct net_device_ops ne2k_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index f8e601c..c11c568 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -308,27 +308,16 @@ struct netxen_ring_ctx {
#define netxen_set_cmd_desc_ctxid(cmd_desc, var) \
((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0))
-#define netxen_set_cmd_desc_flags(cmd_desc, val) \
- (cmd_desc)->flags_opcode = ((cmd_desc)->flags_opcode & \
- ~cpu_to_le16(0x7f)) | cpu_to_le16((val) & 0x7f)
-#define netxen_set_cmd_desc_opcode(cmd_desc, val) \
- (cmd_desc)->flags_opcode = ((cmd_desc)->flags_opcode & \
- ~cpu_to_le16((u16)0x3f << 7)) | cpu_to_le16(((val) & 0x3f) << 7)
-
-#define netxen_set_cmd_desc_num_of_buff(cmd_desc, val) \
- (cmd_desc)->num_of_buffers_total_length = \
- ((cmd_desc)->num_of_buffers_total_length & \
- ~cpu_to_le32(0xff)) | cpu_to_le32((val) & 0xff)
-#define netxen_set_cmd_desc_totallength(cmd_desc, val) \
- (cmd_desc)->num_of_buffers_total_length = \
- ((cmd_desc)->num_of_buffers_total_length & \
- ~cpu_to_le32((u32)0xffffff << 8)) | \
- cpu_to_le32(((val) & 0xffffff) << 8)
-
-#define netxen_get_cmd_desc_opcode(cmd_desc) \
- ((le16_to_cpu((cmd_desc)->flags_opcode) >> 7) & 0x003f)
-#define netxen_get_cmd_desc_totallength(cmd_desc) \
- ((le32_to_cpu((cmd_desc)->num_of_buffers_total_length) >> 8) & 0xffffff)
+#define netxen_set_tx_port(_desc, _port) \
+ (_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0)
+
+#define netxen_set_tx_flags_opcode(_desc, _flags, _opcode) \
+ (_desc)->flags_opcode = \
+ cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7))
+
+#define netxen_set_tx_frags_len(_desc, _frags, _len) \
+ (_desc)->num_of_buffers_total_length = \
+ cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8))
struct cmd_desc_type0 {
u8 tcp_hdr_offset; /* For LSO only */
@@ -510,7 +499,8 @@ typedef enum {
NETXEN_BRDTYPE_P3_10G_SFP_CT = 0x002a,
NETXEN_BRDTYPE_P3_10G_SFP_QT = 0x002b,
NETXEN_BRDTYPE_P3_10G_CX4 = 0x0031,
- NETXEN_BRDTYPE_P3_10G_XFP = 0x0032
+ NETXEN_BRDTYPE_P3_10G_XFP = 0x0032,
+ NETXEN_BRDTYPE_P3_10G_TP = 0x0080
} netxen_brdtype_t;
@@ -757,7 +747,7 @@ extern char netxen_nic_driver_name[];
*/
struct netxen_skb_frag {
u64 dma;
- u32 length;
+ ulong length;
};
#define _netxen_set_bits(config_word, start, bits, val) {\
@@ -783,13 +773,7 @@ struct netxen_skb_frag {
struct netxen_cmd_buffer {
struct sk_buff *skb;
struct netxen_skb_frag frag_array[MAX_BUFFERS_PER_CMD + 1];
- u32 total_length;
- u32 mss;
- u16 port;
- u8 cmd;
- u8 frag_count;
- unsigned long time_stamp;
- u32 state;
+ u32 frag_count;
};
/* In rx_buffer, we do not need multiple fragments as is a single buffer */
@@ -876,7 +860,6 @@ struct nx_host_rds_ring {
u32 skb_size;
struct netxen_rx_buffer *rx_buf_arr; /* rx buffers for receive */
struct list_head free_list;
- int begin_alloc;
};
/*
@@ -995,31 +978,31 @@ struct netxen_recv_context {
*/
typedef struct {
- u64 host_phys_addr; /* Ring base addr */
- u32 ring_size; /* Ring entries */
- u16 msi_index;
- u16 rsvd; /* Padding */
+ __le64 host_phys_addr; /* Ring base addr */
+ __le32 ring_size; /* Ring entries */
+ __le16 msi_index;
+ __le16 rsvd; /* Padding */
} nx_hostrq_sds_ring_t;
typedef struct {
- u64 host_phys_addr; /* Ring base addr */
- u64 buff_size; /* Packet buffer size */
- u32 ring_size; /* Ring entries */
- u32 ring_kind; /* Class of ring */
+ __le64 host_phys_addr; /* Ring base addr */
+ __le64 buff_size; /* Packet buffer size */
+ __le32 ring_size; /* Ring entries */
+ __le32 ring_kind; /* Class of ring */
} nx_hostrq_rds_ring_t;
typedef struct {
- u64 host_rsp_dma_addr; /* Response dma'd here */
- u32 capabilities[4]; /* Flag bit vector */
- u32 host_int_crb_mode; /* Interrupt crb usage */
- u32 host_rds_crb_mode; /* RDS crb usage */
+ __le64 host_rsp_dma_addr; /* Response dma'd here */
+ __le32 capabilities[4]; /* Flag bit vector */
+ __le32 host_int_crb_mode; /* Interrupt crb usage */
+ __le32 host_rds_crb_mode; /* RDS crb usage */
/* These ring offsets are relative to data[0] below */
- u32 rds_ring_offset; /* Offset to RDS config */
- u32 sds_ring_offset; /* Offset to SDS config */
- u16 num_rds_rings; /* Count of RDS rings */
- u16 num_sds_rings; /* Count of SDS rings */
- u16 rsvd1; /* Padding */
- u16 rsvd2; /* Padding */
+ __le32 rds_ring_offset; /* Offset to RDS config */
+ __le32 sds_ring_offset; /* Offset to SDS config */
+ __le16 num_rds_rings; /* Count of RDS rings */
+ __le16 num_sds_rings; /* Count of SDS rings */
+ __le16 rsvd1; /* Padding */
+ __le16 rsvd2; /* Padding */
u8 reserved[128]; /* reserve space for future expansion*/
/* MUST BE 64-bit aligned.
The following is packed:
@@ -1029,24 +1012,24 @@ typedef struct {
} nx_hostrq_rx_ctx_t;
typedef struct {
- u32 host_producer_crb; /* Crb to use */
- u32 rsvd1; /* Padding */
+ __le32 host_producer_crb; /* Crb to use */
+ __le32 rsvd1; /* Padding */
} nx_cardrsp_rds_ring_t;
typedef struct {
- u32 host_consumer_crb; /* Crb to use */
- u32 interrupt_crb; /* Crb to use */
+ __le32 host_consumer_crb; /* Crb to use */
+ __le32 interrupt_crb; /* Crb to use */
} nx_cardrsp_sds_ring_t;
typedef struct {
/* These ring offsets are relative to data[0] below */
- u32 rds_ring_offset; /* Offset to RDS config */
- u32 sds_ring_offset; /* Offset to SDS config */
- u32 host_ctx_state; /* Starting State */
- u32 num_fn_per_port; /* How many PCI fn share the port */
- u16 num_rds_rings; /* Count of RDS rings */
- u16 num_sds_rings; /* Count of SDS rings */
- u16 context_id; /* Handle for context */
+ __le32 rds_ring_offset; /* Offset to RDS config */
+ __le32 sds_ring_offset; /* Offset to SDS config */
+ __le32 host_ctx_state; /* Starting State */
+ __le32 num_fn_per_port; /* How many PCI fn share the port */
+ __le16 num_rds_rings; /* Count of RDS rings */
+ __le16 num_sds_rings; /* Count of SDS rings */
+ __le16 context_id; /* Handle for context */
u8 phys_port; /* Physical id of port */
u8 virt_port; /* Virtual/Logical id of port */
u8 reserved[128]; /* save space for future expansion */
@@ -1072,34 +1055,34 @@ typedef struct {
*/
typedef struct {
- u64 host_phys_addr; /* Ring base addr */
- u32 ring_size; /* Ring entries */
- u32 rsvd; /* Padding */
+ __le64 host_phys_addr; /* Ring base addr */
+ __le32 ring_size; /* Ring entries */
+ __le32 rsvd; /* Padding */
} nx_hostrq_cds_ring_t;
typedef struct {
- u64 host_rsp_dma_addr; /* Response dma'd here */
- u64 cmd_cons_dma_addr; /* */
- u64 dummy_dma_addr; /* */
- u32 capabilities[4]; /* Flag bit vector */
- u32 host_int_crb_mode; /* Interrupt crb usage */
- u32 rsvd1; /* Padding */
- u16 rsvd2; /* Padding */
- u16 interrupt_ctl;
- u16 msi_index;
- u16 rsvd3; /* Padding */
+ __le64 host_rsp_dma_addr; /* Response dma'd here */
+ __le64 cmd_cons_dma_addr; /* */
+ __le64 dummy_dma_addr; /* */
+ __le32 capabilities[4]; /* Flag bit vector */
+ __le32 host_int_crb_mode; /* Interrupt crb usage */
+ __le32 rsvd1; /* Padding */
+ __le16 rsvd2; /* Padding */
+ __le16 interrupt_ctl;
+ __le16 msi_index;
+ __le16 rsvd3; /* Padding */
nx_hostrq_cds_ring_t cds_ring; /* Desc of cds ring */
u8 reserved[128]; /* future expansion */
} nx_hostrq_tx_ctx_t;
typedef struct {
- u32 host_producer_crb; /* Crb to use */
- u32 interrupt_crb; /* Crb to use */
+ __le32 host_producer_crb; /* Crb to use */
+ __le32 interrupt_crb; /* Crb to use */
} nx_cardrsp_cds_ring_t;
typedef struct {
- u32 host_ctx_state; /* Starting state */
- u16 context_id; /* Handle for context */
+ __le32 host_ctx_state; /* Starting state */
+ __le16 context_id; /* Handle for context */
u8 phys_port; /* Physical id of port */
u8 virt_port; /* Virtual/Logical id of port */
nx_cardrsp_cds_ring_t cds_ring; /* Card cds settings */
@@ -1202,9 +1185,9 @@ enum {
#define VPORT_MISS_MODE_ACCEPT_MULTI 2 /* accept unmatched multicast */
typedef struct {
- u64 qhdr;
- u64 req_hdr;
- u64 words[6];
+ __le64 qhdr;
+ __le64 req_hdr;
+ __le64 words[6];
} nx_nic_req_t;
typedef struct {
@@ -1486,8 +1469,6 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter);
void netxen_initialize_adapter_ops(struct netxen_adapter *adapter);
int netxen_init_firmware(struct netxen_adapter *adapter);
-void netxen_tso_check(struct netxen_adapter *adapter,
- struct cmd_desc_type0 *desc, struct sk_buff *skb);
void netxen_nic_clear_stats(struct netxen_adapter *adapter);
void netxen_watchdog_task(struct work_struct *work);
void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx,
@@ -1496,6 +1477,7 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter);
u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max);
void netxen_p2_nic_set_multi(struct net_device *netdev);
void netxen_p3_nic_set_multi(struct net_device *netdev);
+void netxen_p3_free_mac_list(struct netxen_adapter *adapter);
int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32);
int netxen_config_intr_coalesce(struct netxen_adapter *adapter);
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c
index 64b5164..746bdb4 100644
--- a/drivers/net/netxen/netxen_nic_ctx.c
+++ b/drivers/net/netxen/netxen_nic_ctx.c
@@ -76,7 +76,7 @@ netxen_api_unlock(struct netxen_adapter *adapter)
static u32
netxen_poll_rsp(struct netxen_adapter *adapter)
{
- u32 raw_rsp, rsp = NX_CDRP_RSP_OK;
+ u32 rsp = NX_CDRP_RSP_OK;
int timeout = 0;
do {
@@ -86,10 +86,7 @@ netxen_poll_rsp(struct netxen_adapter *adapter)
if (++timeout > NX_OS_CRB_RETRY_COUNT)
return NX_CDRP_RSP_TIMEOUT;
- netxen_nic_read_w1(adapter, NX_CDRP_CRB_OFFSET,
- &raw_rsp);
-
- rsp = le32_to_cpu(raw_rsp);
+ netxen_nic_read_w1(adapter, NX_CDRP_CRB_OFFSET, &rsp);
} while (!NX_CDRP_IS_RSP(rsp));
return rsp;
@@ -109,20 +106,16 @@ netxen_issue_cmd(struct netxen_adapter *adapter,
if (netxen_api_lock(adapter))
return NX_RCODE_TIMEOUT;
- netxen_nic_write_w1(adapter, NX_SIGN_CRB_OFFSET,
- cpu_to_le32(signature));
+ netxen_nic_write_w1(adapter, NX_SIGN_CRB_OFFSET, signature);
- netxen_nic_write_w1(adapter, NX_ARG1_CRB_OFFSET,
- cpu_to_le32(arg1));
+ netxen_nic_write_w1(adapter, NX_ARG1_CRB_OFFSET, arg1);
- netxen_nic_write_w1(adapter, NX_ARG2_CRB_OFFSET,
- cpu_to_le32(arg2));
+ netxen_nic_write_w1(adapter, NX_ARG2_CRB_OFFSET, arg2);
- netxen_nic_write_w1(adapter, NX_ARG3_CRB_OFFSET,
- cpu_to_le32(arg3));
+ netxen_nic_write_w1(adapter, NX_ARG3_CRB_OFFSET, arg3);
netxen_nic_write_w1(adapter, NX_CDRP_CRB_OFFSET,
- cpu_to_le32(NX_CDRP_FORM_CMD(cmd)));
+ NX_CDRP_FORM_CMD(cmd));
rsp = netxen_poll_rsp(adapter);
@@ -133,7 +126,6 @@ netxen_issue_cmd(struct netxen_adapter *adapter,
rcode = NX_RCODE_TIMEOUT;
} else if (rsp == NX_CDRP_RSP_FAIL) {
netxen_nic_read_w1(adapter, NX_ARG1_CRB_OFFSET, &rcode);
- rcode = le32_to_cpu(rcode);
printk(KERN_ERR "%s: failed card response code:0x%x\n",
netxen_nic_driver_name, rcode);
@@ -183,7 +175,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
int i, nrds_rings, nsds_rings;
size_t rq_size, rsp_size;
- u32 cap, reg;
+ u32 cap, reg, val;
int err;
@@ -225,11 +217,14 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
prq->num_rds_rings = cpu_to_le16(nrds_rings);
prq->num_sds_rings = cpu_to_le16(nsds_rings);
- prq->rds_ring_offset = 0;
- prq->sds_ring_offset = prq->rds_ring_offset +
+ prq->rds_ring_offset = cpu_to_le32(0);
+
+ val = le32_to_cpu(prq->rds_ring_offset) +
(sizeof(nx_hostrq_rds_ring_t) * nrds_rings);
+ prq->sds_ring_offset = cpu_to_le32(val);
- prq_rds = (nx_hostrq_rds_ring_t *)(prq->data + prq->rds_ring_offset);
+ prq_rds = (nx_hostrq_rds_ring_t *)(prq->data +
+ le32_to_cpu(prq->rds_ring_offset));
for (i = 0; i < nrds_rings; i++) {
@@ -241,17 +236,14 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
prq_rds[i].buff_size = cpu_to_le64(rds_ring->dma_size);
}
- prq_sds = (nx_hostrq_sds_ring_t *)(prq->data + prq->sds_ring_offset);
+ prq_sds = (nx_hostrq_sds_ring_t *)(prq->data +
+ le32_to_cpu(prq->sds_ring_offset));
prq_sds[0].host_phys_addr =
cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr);
prq_sds[0].ring_size = cpu_to_le32(adapter->max_rx_desc_count);
/* only one msix vector for now */
- prq_sds[0].msi_index = cpu_to_le32(0);
-
- /* now byteswap offsets */
- prq->rds_ring_offset = cpu_to_le32(prq->rds_ring_offset);
- prq->sds_ring_offset = cpu_to_le32(prq->sds_ring_offset);
+ prq_sds[0].msi_index = cpu_to_le16(0);
phys_addr = hostrq_phys_addr;
err = netxen_issue_cmd(adapter,
@@ -269,9 +261,9 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
prsp_rds = ((nx_cardrsp_rds_ring_t *)
- &prsp->data[prsp->rds_ring_offset]);
+ &prsp->data[le32_to_cpu(prsp->rds_ring_offset)]);
- for (i = 0; i < le32_to_cpu(prsp->num_rds_rings); i++) {
+ for (i = 0; i < le16_to_cpu(prsp->num_rds_rings); i++) {
rds_ring = &recv_ctx->rds_rings[i];
reg = le32_to_cpu(prsp_rds[i].host_producer_crb);
@@ -279,7 +271,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
}
prsp_sds = ((nx_cardrsp_sds_ring_t *)
- &prsp->data[prsp->sds_ring_offset]);
+ &prsp->data[le32_to_cpu(prsp->sds_ring_offset)]);
reg = le32_to_cpu(prsp_sds[0].host_consumer_crb);
recv_ctx->crb_sts_consumer = NETXEN_NIC_REG(reg - 0x200);
@@ -288,7 +280,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
recv_ctx->state = le32_to_cpu(prsp->host_ctx_state);
recv_ctx->context_id = le16_to_cpu(prsp->context_id);
- recv_ctx->virt_port = le16_to_cpu(prsp->virt_port);
+ recv_ctx->virt_port = prsp->virt_port;
out_free_rsp:
pci_free_consistent(adapter->pdev, rsp_size, prsp, cardrsp_phys_addr);
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
index e45ce29..c0bd40f 100644
--- a/drivers/net/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/netxen/netxen_nic_ethtool.c
@@ -136,11 +136,9 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
ecmd->port = PORT_TP;
- if (netif_running(dev)) {
- ecmd->speed = adapter->link_speed;
- ecmd->duplex = adapter->link_duplex;
- ecmd->autoneg = adapter->link_autoneg;
- }
+ ecmd->speed = adapter->link_speed;
+ ecmd->duplex = adapter->link_duplex;
+ ecmd->autoneg = adapter->link_autoneg;
} else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
u32 val;
@@ -171,7 +169,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
} else
return -EIO;
- ecmd->phy_address = adapter->portnum;
+ ecmd->phy_address = adapter->physical_port;
ecmd->transceiver = XCVR_EXTERNAL;
switch ((netxen_brdtype_t) boardinfo->board_type) {
@@ -180,13 +178,13 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
case NETXEN_BRDTYPE_P3_REF_QG:
case NETXEN_BRDTYPE_P3_4_GB:
case NETXEN_BRDTYPE_P3_4_GB_MM:
- case NETXEN_BRDTYPE_P3_10000_BASE_T:
ecmd->supported |= SUPPORTED_Autoneg;
ecmd->advertising |= ADVERTISED_Autoneg;
case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
case NETXEN_BRDTYPE_P3_10G_CX4:
case NETXEN_BRDTYPE_P3_10G_CX4_LP:
+ case NETXEN_BRDTYPE_P3_10000_BASE_T:
ecmd->supported |= SUPPORTED_TP;
ecmd->advertising |= ADVERTISED_TP;
ecmd->port = PORT_TP;
@@ -204,16 +202,33 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
ecmd->port = PORT_FIBRE;
ecmd->autoneg = AUTONEG_DISABLE;
break;
- case NETXEN_BRDTYPE_P2_SB31_10G:
case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
case NETXEN_BRDTYPE_P3_10G_SFP_CT:
case NETXEN_BRDTYPE_P3_10G_SFP_QT:
+ ecmd->advertising |= ADVERTISED_TP;
+ ecmd->supported |= SUPPORTED_TP;
+ case NETXEN_BRDTYPE_P2_SB31_10G:
case NETXEN_BRDTYPE_P3_10G_XFP:
ecmd->supported |= SUPPORTED_FIBRE;
ecmd->advertising |= ADVERTISED_FIBRE;
ecmd->port = PORT_FIBRE;
ecmd->autoneg = AUTONEG_DISABLE;
break;
+ case NETXEN_BRDTYPE_P3_10G_TP:
+ if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
+ ecmd->autoneg = AUTONEG_DISABLE;
+ ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
+ ecmd->advertising |=
+ (ADVERTISED_FIBRE | ADVERTISED_TP);
+ ecmd->port = PORT_FIBRE;
+ } else {
+ ecmd->autoneg = AUTONEG_ENABLE;
+ ecmd->supported |= (SUPPORTED_TP |SUPPORTED_Autoneg);
+ ecmd->advertising |=
+ (ADVERTISED_TP | ADVERTISED_Autoneg);
+ ecmd->port = PORT_TP;
+ }
+ break;
default:
printk(KERN_ERR "netxen-nic: Unsupported board model %d\n",
(netxen_brdtype_t) boardinfo->board_type);
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index aa6e603..821cff6 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -503,17 +503,15 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter,
i = 0;
+ netif_tx_lock_bh(adapter->netdev);
+
producer = adapter->cmd_producer;
do {
cmd_desc = &cmd_desc_arr[i];
pbuf = &adapter->cmd_buf_arr[producer];
- pbuf->mss = 0;
- pbuf->total_length = 0;
pbuf->skb = NULL;
- pbuf->cmd = 0;
pbuf->frag_count = 0;
- pbuf->port = 0;
/* adapter->ahw.cmd_desc_head[producer] = *cmd_desc; */
memcpy(&adapter->ahw.cmd_desc_head[producer],
@@ -531,6 +529,8 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter,
netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer);
+ netif_tx_unlock_bh(adapter->netdev);
+
return 0;
}
@@ -539,16 +539,19 @@ static int nx_p3_sre_macaddr_change(struct net_device *dev,
{
struct netxen_adapter *adapter = netdev_priv(dev);
nx_nic_req_t req;
- nx_mac_req_t mac_req;
+ nx_mac_req_t *mac_req;
+ u64 word;
int rv;
memset(&req, 0, sizeof(nx_nic_req_t));
- req.qhdr |= (NX_NIC_REQUEST << 23);
- req.req_hdr |= NX_MAC_EVENT;
- req.req_hdr |= ((u64)adapter->portnum << 16);
- mac_req.op = op;
- memcpy(&mac_req.mac_addr, addr, 6);
- req.words[0] = cpu_to_le64(*(u64 *)&mac_req);
+ req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23);
+
+ word = NX_MAC_EVENT | ((u64)adapter->portnum << 16);
+ req.req_hdr = cpu_to_le64(word);
+
+ mac_req = (nx_mac_req_t *)&req.words[0];
+ mac_req->op = op;
+ memcpy(mac_req->mac_addr, addr, 6);
rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
if (rv != 0) {
@@ -612,18 +615,35 @@ send_fw_cmd:
int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode)
{
nx_nic_req_t req;
+ u64 word;
memset(&req, 0, sizeof(nx_nic_req_t));
- req.qhdr |= (NX_HOST_REQUEST << 23);
- req.req_hdr |= NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE;
- req.req_hdr |= ((u64)adapter->portnum << 16);
+ req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
+
+ word = NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE |
+ ((u64)adapter->portnum << 16);
+ req.req_hdr = cpu_to_le64(word);
+
req.words[0] = cpu_to_le64(mode);
return netxen_send_cmd_descs(adapter,
(struct cmd_desc_type0 *)&req, 1);
}
+void netxen_p3_free_mac_list(struct netxen_adapter *adapter)
+{
+ nx_mac_list_t *cur, *next;
+
+ cur = adapter->mac_list;
+
+ while (cur) {
+ next = cur->next;
+ kfree(cur);
+ cur = next;
+ }
+}
+
#define NETXEN_CONFIG_INTR_COALESCE 3
/*
@@ -632,13 +652,15 @@ int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode)
int netxen_config_intr_coalesce(struct netxen_adapter *adapter)
{
nx_nic_req_t req;
+ u64 word;
int rv;
memset(&req, 0, sizeof(nx_nic_req_t));
- req.qhdr |= (NX_NIC_REQUEST << 23);
- req.req_hdr |= NETXEN_CONFIG_INTR_COALESCE;
- req.req_hdr |= ((u64)adapter->portnum << 16);
+ req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23);
+
+ word = NETXEN_CONFIG_INTR_COALESCE | ((u64)adapter->portnum << 16);
+ req.req_hdr = cpu_to_le64(word);
memcpy(&req.words[0], &adapter->coal, sizeof(adapter->coal));
@@ -772,13 +794,10 @@ int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac)
adapter->hw_read_wx(adapter, crbaddr, &mac_lo, 4);
adapter->hw_read_wx(adapter, crbaddr+4, &mac_hi, 4);
- mac_hi = cpu_to_le32(mac_hi);
- mac_lo = cpu_to_le32(mac_lo);
-
if (pci_func & 1)
- *mac = ((mac_lo >> 16) | ((u64)mac_hi << 16));
+ *mac = le64_to_cpu((mac_lo >> 16) | ((u64)mac_hi << 16));
else
- *mac = ((mac_lo) | ((u64)mac_hi << 32));
+ *mac = le64_to_cpu((u64)mac_lo | ((u64)mac_hi << 32));
return 0;
}
@@ -937,7 +956,7 @@ int netxen_load_firmware(struct netxen_adapter *adapter)
{
int i;
u32 data, size = 0;
- u32 flashaddr = NETXEN_BOOTLD_START, memaddr = NETXEN_BOOTLD_START;
+ u32 flashaddr = NETXEN_BOOTLD_START;
size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START)/4;
@@ -949,10 +968,8 @@ int netxen_load_firmware(struct netxen_adapter *adapter)
if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0)
return -EIO;
- adapter->pci_mem_write(adapter, memaddr, &data, 4);
+ adapter->pci_mem_write(adapter, flashaddr, &data, 4);
flashaddr += 4;
- memaddr += 4;
- cond_resched();
}
msleep(1);
@@ -2034,7 +2051,13 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter)
rv = -1;
}
- DPRINTK(INFO, "Discovered board type:0x%x ", boardinfo->board_type);
+ if (boardinfo->board_type == NETXEN_BRDTYPE_P3_4_GB_MM) {
+ u32 gpio = netxen_nic_reg_read(adapter,
+ NETXEN_ROMUSB_GLB_PAD_GPIO_I);
+ if ((gpio & 0x8000) == 0)
+ boardinfo->board_type = NETXEN_BRDTYPE_P3_10G_TP;
+ }
+
switch ((netxen_brdtype_t) boardinfo->board_type) {
case NETXEN_BRDTYPE_P2_SB35_4G:
adapter->ahw.board_type = NETXEN_NIC_GBE;
@@ -2053,7 +2076,6 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter)
case NETXEN_BRDTYPE_P3_10G_SFP_QT:
case NETXEN_BRDTYPE_P3_10G_XFP:
case NETXEN_BRDTYPE_P3_10000_BASE_T:
-
adapter->ahw.board_type = NETXEN_NIC_XGBE;
break;
case NETXEN_BRDTYPE_P1_BD:
@@ -2063,9 +2085,12 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter)
case NETXEN_BRDTYPE_P3_REF_QG:
case NETXEN_BRDTYPE_P3_4_GB:
case NETXEN_BRDTYPE_P3_4_GB_MM:
-
adapter->ahw.board_type = NETXEN_NIC_GBE;
break;
+ case NETXEN_BRDTYPE_P3_10G_TP:
+ adapter->ahw.board_type = (adapter->portnum < 2) ?
+ NETXEN_NIC_XGBE : NETXEN_NIC_GBE;
+ break;
default:
printk("%s: Unknown(%x)\n", netxen_nic_driver_name,
boardinfo->board_type);
@@ -2110,12 +2135,16 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter)
{
__u32 status;
__u32 autoneg;
- __u32 mode;
__u32 port_mode;
- netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, &mode);
- if (netxen_get_niu_enable_ge(mode)) { /* Gb 10/100/1000 Mbps mode */
+ if (!netif_carrier_ok(adapter->netdev)) {
+ adapter->link_speed = 0;
+ adapter->link_duplex = -1;
+ adapter->link_autoneg = AUTONEG_ENABLE;
+ return;
+ }
+ if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
adapter->hw_read_wx(adapter,
NETXEN_PORT_MODE_ADDR, &port_mode, 4);
if (port_mode == NETXEN_PORT_MODE_802_3_AP) {
@@ -2141,7 +2170,7 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter)
adapter->link_speed = SPEED_1000;
break;
default:
- adapter->link_speed = -1;
+ adapter->link_speed = 0;
break;
}
switch (netxen_get_phy_duplex(status)) {
@@ -2164,7 +2193,7 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter)
goto link_down;
} else {
link_down:
- adapter->link_speed = -1;
+ adapter->link_speed = 0;
adapter->link_duplex = -1;
}
}
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index d924468..ca7c8d8 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -308,7 +308,6 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
}
memset(rds_ring->rx_buf_arr, 0, RCV_BUFFSIZE);
INIT_LIST_HEAD(&rds_ring->free_list);
- rds_ring->begin_alloc = 0;
/*
* Now go through all of them, set reference handles
* and put them in the queues.
@@ -439,6 +438,8 @@ static int netxen_wait_rom_done(struct netxen_adapter *adapter)
long timeout = 0;
long done = 0;
+ cond_resched();
+
while (done == 0) {
done = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_GLB_STATUS);
done &= 2;
@@ -533,12 +534,9 @@ static int do_rom_fast_write(struct netxen_adapter *adapter, int addr,
static int do_rom_fast_read(struct netxen_adapter *adapter,
int addr, int *valp)
{
- cond_resched();
-
netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
- netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
- 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_ABYTE_CNT, 3);
netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb);
if (netxen_wait_rom_done(adapter)) {
printk("Error waiting for rom done\n");
@@ -546,7 +544,7 @@ static int do_rom_fast_read(struct netxen_adapter *adapter,
}
/* reset abyte_cnt and dummy_byte_cnt */
netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
- udelay(100); /* prevent bursting on CRB */
+ udelay(10);
netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
*valp = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_ROM_RDATA);
@@ -884,14 +882,16 @@ int netxen_flash_unlock(struct netxen_adapter *adapter)
int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
{
int addr, val;
- int i, init_delay = 0;
+ int i, n, init_delay = 0;
struct crb_addr_pair *buf;
- unsigned offset, n;
+ unsigned offset;
u32 off;
/* resetall */
+ rom_lock(adapter);
netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
0xffffffff);
+ netxen_rom_unlock(adapter);
if (verbose) {
if (netxen_rom_fast_read(adapter, NETXEN_BOARDTYPE, &val) == 0)
@@ -910,7 +910,7 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
if (netxen_rom_fast_read(adapter, 0, &n) != 0 ||
- (n != 0xcafecafeUL) ||
+ (n != 0xcafecafe) ||
netxen_rom_fast_read(adapter, 4, &n) != 0) {
printk(KERN_ERR "%s: ERROR Reading crb_init area: "
"n: %08x\n", netxen_nic_driver_name, n);
@@ -975,6 +975,14 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
/* do not reset PCI */
if (off == (ROMUSB_GLB + 0xbc))
continue;
+ if (off == (ROMUSB_GLB + 0xa8))
+ continue;
+ if (off == (ROMUSB_GLB + 0xc8)) /* core clock */
+ continue;
+ if (off == (ROMUSB_GLB + 0x24)) /* MN clock */
+ continue;
+ if (off == (ROMUSB_GLB + 0x1c)) /* MS clock */
+ continue;
if (off == (NETXEN_CRB_PEG_NET_1 + 0x18))
buf[i].data = 0x1020;
/* skip the function enable register */
@@ -992,23 +1000,21 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
continue;
}
+ init_delay = 1;
/* After writing this register, HW needs time for CRB */
/* to quiet down (else crb_window returns 0xffffffff) */
if (off == NETXEN_ROMUSB_GLB_SW_RESET) {
- init_delay = 1;
+ init_delay = 1000;
if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
/* hold xdma in reset also */
buf[i].data = NETXEN_NIC_XDMA_RESET;
+ buf[i].data = 0x8000ff;
}
}
adapter->hw_write_wx(adapter, off, &buf[i].data, 4);
- if (init_delay == 1) {
- msleep(1000);
- init_delay = 0;
- }
- msleep(1);
+ msleep(init_delay);
}
kfree(buf);
@@ -1277,7 +1283,7 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
dev_kfree_skb_any(skb);
for (i = 0; i < nr_frags; i++) {
- index = frag_desc->frag_handles[i];
+ index = le16_to_cpu(frag_desc->frag_handles[i]);
skb = netxen_process_rxbuf(adapter,
rds_ring, index, cksum);
if (skb)
@@ -1428,7 +1434,6 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
struct rcv_desc *pdesc;
struct netxen_rx_buffer *buffer;
int count = 0;
- int index = 0;
netxen_ctx_msg msg = 0;
dma_addr_t dma;
struct list_head *head;
@@ -1436,7 +1441,6 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
rds_ring = &recv_ctx->rds_rings[ringid];
producer = rds_ring->producer;
- index = rds_ring->begin_alloc;
head = &rds_ring->free_list;
/* We can start writing rx descriptors into the phantom memory. */
@@ -1444,39 +1448,37 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
skb = dev_alloc_skb(rds_ring->skb_size);
if (unlikely(!skb)) {
- rds_ring->begin_alloc = index;
break;
}
+ if (!adapter->ahw.cut_through)
+ skb_reserve(skb, 2);
+
+ dma = pci_map_single(pdev, skb->data,
+ rds_ring->dma_size, PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(pdev, dma)) {
+ dev_kfree_skb_any(skb);
+ break;
+ }
+
+ count++;
buffer = list_entry(head->next, struct netxen_rx_buffer, list);
list_del(&buffer->list);
- count++; /* now there should be no failure */
- pdesc = &rds_ring->desc_head[producer];
-
- if (!adapter->ahw.cut_through)
- skb_reserve(skb, 2);
- /* This will be setup when we receive the
- * buffer after it has been filled FSL TBD TBD
- * skb->dev = netdev;
- */
- dma = pci_map_single(pdev, skb->data, rds_ring->dma_size,
- PCI_DMA_FROMDEVICE);
- pdesc->addr_buffer = cpu_to_le64(dma);
buffer->skb = skb;
buffer->state = NETXEN_BUFFER_BUSY;
buffer->dma = dma;
+
/* make a rcv descriptor */
+ pdesc = &rds_ring->desc_head[producer];
+ pdesc->addr_buffer = cpu_to_le64(dma);
pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
- DPRINTK(INFO, "done writing descripter\n");
- producer =
- get_next_index(producer, rds_ring->max_rx_desc_count);
- index = get_next_index(index, rds_ring->max_rx_desc_count);
+
+ producer = get_next_index(producer, rds_ring->max_rx_desc_count);
}
/* if we did allocate buffers, then write the count to Phantom */
if (count) {
- rds_ring->begin_alloc = index;
rds_ring->producer = producer;
/* Window = 1 */
adapter->pci_write_normalize(adapter,
@@ -1515,49 +1517,50 @@ static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
struct rcv_desc *pdesc;
struct netxen_rx_buffer *buffer;
int count = 0;
- int index = 0;
struct list_head *head;
+ dma_addr_t dma;
rds_ring = &recv_ctx->rds_rings[ringid];
producer = rds_ring->producer;
- index = rds_ring->begin_alloc;
head = &rds_ring->free_list;
/* We can start writing rx descriptors into the phantom memory. */
while (!list_empty(head)) {
skb = dev_alloc_skb(rds_ring->skb_size);
if (unlikely(!skb)) {
- rds_ring->begin_alloc = index;
break;
}
+ if (!adapter->ahw.cut_through)
+ skb_reserve(skb, 2);
+
+ dma = pci_map_single(pdev, skb->data,
+ rds_ring->dma_size, PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(pdev, dma)) {
+ dev_kfree_skb_any(skb);
+ break;
+ }
+
+ count++;
buffer = list_entry(head->next, struct netxen_rx_buffer, list);
list_del(&buffer->list);
- count++; /* now there should be no failure */
- pdesc = &rds_ring->desc_head[producer];
- if (!adapter->ahw.cut_through)
- skb_reserve(skb, 2);
buffer->skb = skb;
buffer->state = NETXEN_BUFFER_BUSY;
- buffer->dma = pci_map_single(pdev, skb->data,
- rds_ring->dma_size,
- PCI_DMA_FROMDEVICE);
+ buffer->dma = dma;
/* make a rcv descriptor */
+ pdesc = &rds_ring->desc_head[producer];
pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
pdesc->addr_buffer = cpu_to_le64(buffer->dma);
- producer =
- get_next_index(producer, rds_ring->max_rx_desc_count);
- index = get_next_index(index, rds_ring->max_rx_desc_count);
- buffer = &rds_ring->rx_buf_arr[index];
+
+ producer = get_next_index(producer, rds_ring->max_rx_desc_count);
}
/* if we did allocate buffers, then write the count to Phantom */
if (count) {
- rds_ring->begin_alloc = index;
rds_ring->producer = producer;
/* Window = 1 */
adapter->pci_write_normalize(adapter,
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index ba01524..8686740 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -39,6 +39,7 @@
#include "netxen_nic_phan_reg.h"
#include <linux/dma-mapping.h>
+#include <linux/if_vlan.h>
#include <net/ip.h>
MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver");
@@ -242,7 +243,7 @@ static void netxen_check_options(struct netxen_adapter *adapter)
case NETXEN_BRDTYPE_P3_4_GB:
case NETXEN_BRDTYPE_P3_4_GB_MM:
adapter->msix_supported = !!use_msi_x;
- adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G;
+ adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
break;
case NETXEN_BRDTYPE_P2_SB35_4G:
@@ -251,6 +252,14 @@ static void netxen_check_options(struct netxen_adapter *adapter)
adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
break;
+ case NETXEN_BRDTYPE_P3_10G_TP:
+ adapter->msix_supported = !!use_msi_x;
+ if (adapter->ahw.board_type == NETXEN_NIC_XGBE)
+ adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G;
+ else
+ adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
+ break;
+
default:
adapter->msix_supported = 0;
adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
@@ -271,10 +280,15 @@ static void netxen_check_options(struct netxen_adapter *adapter)
static int
netxen_check_hw_init(struct netxen_adapter *adapter, int first_boot)
{
- int ret = 0;
+ u32 val, timeout;
if (first_boot == 0x55555555) {
/* This is the first boot after power up */
+ adapter->pci_write_normalize(adapter,
+ NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
+
+ if (!NX_IS_REVISION_P2(adapter->ahw.revision_id))
+ return 0;
/* PCI bus master workaround */
adapter->hw_read_wx(adapter,
@@ -294,18 +308,26 @@ netxen_check_hw_init(struct netxen_adapter *adapter, int first_boot)
/* clear the register for future unloads/loads */
adapter->pci_write_normalize(adapter,
NETXEN_CAM_RAM(0x1fc), 0);
- ret = -1;
+ return -EIO;
}
- if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
- /* Start P2 boot loader */
- adapter->pci_write_normalize(adapter,
- NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
- adapter->pci_write_normalize(adapter,
- NETXEN_ROMUSB_GLB_PEGTUNE_DONE, 1);
- }
+ /* Start P2 boot loader */
+ val = adapter->pci_read_normalize(adapter,
+ NETXEN_ROMUSB_GLB_PEGTUNE_DONE);
+ adapter->pci_write_normalize(adapter,
+ NETXEN_ROMUSB_GLB_PEGTUNE_DONE, val | 0x1);
+ timeout = 0;
+ do {
+ msleep(1);
+ val = adapter->pci_read_normalize(adapter,
+ NETXEN_CAM_RAM(0x1fc));
+
+ if (++timeout > 5000)
+ return -EIO;
+
+ } while (val == NETXEN_BDINFO_MAGIC);
}
- return ret;
+ return 0;
}
static void netxen_set_port_mode(struct netxen_adapter *adapter)
@@ -784,8 +806,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
CRB_CMDPEG_STATE, 0);
netxen_pinit_from_rom(adapter, 0);
msleep(1);
- netxen_load_firmware(adapter);
}
+ netxen_load_firmware(adapter);
if (NX_IS_REVISION_P3(revision_id))
netxen_pcie_strap_init(adapter);
@@ -801,13 +823,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
- if ((first_boot == 0x55555555) &&
- (NX_IS_REVISION_P2(revision_id))) {
- /* Unlock the HW, prompting the boot sequence */
- adapter->pci_write_normalize(adapter,
- NETXEN_ROMUSB_GLB_PEGTUNE_DONE, 1);
- }
-
err = netxen_initialize_adapter_offload(adapter);
if (err)
goto err_out_iounmap;
@@ -821,7 +836,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->pci_write_normalize(adapter, CRB_DRIVER_VERSION, i);
/* Handshake with the card before we register the devices. */
- netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
+ err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
+ if (err)
+ goto err_out_free_offload;
} /* first_driver */
@@ -925,6 +942,7 @@ err_out_disable_msi:
if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
pci_disable_msi(pdev);
+err_out_free_offload:
if (first_driver)
netxen_free_adapter_offload(adapter);
@@ -968,6 +986,9 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
netxen_free_hw_resources(adapter);
netxen_release_rx_buffers(adapter);
netxen_free_sw_resources(adapter);
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ netxen_p3_free_mac_list(adapter);
}
if (adapter->portnum == 0)
@@ -1137,29 +1158,64 @@ static int netxen_nic_close(struct net_device *netdev)
return 0;
}
-void netxen_tso_check(struct netxen_adapter *adapter,
+static bool netxen_tso_check(struct net_device *netdev,
struct cmd_desc_type0 *desc, struct sk_buff *skb)
{
- if (desc->mss) {
- desc->total_hdr_length = (sizeof(struct ethhdr) +
- ip_hdrlen(skb) + tcp_hdrlen(skb));
+ bool tso = false;
+ u8 opcode = TX_ETHER_PKT;
- if ((NX_IS_REVISION_P3(adapter->ahw.revision_id)) &&
- (skb->protocol == htons(ETH_P_IPV6)))
- netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO6);
- else
- netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO);
+ if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
+ skb_shinfo(skb)->gso_size > 0) {
+
+ desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
+ desc->total_hdr_length =
+ skb_transport_offset(skb) + tcp_hdrlen(skb);
+
+ opcode = (skb->protocol == htons(ETH_P_IPV6)) ?
+ TX_TCP_LSO6 : TX_TCP_LSO;
+ tso = true;
} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
- if (ip_hdr(skb)->protocol == IPPROTO_TCP)
- netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT);
- else if (ip_hdr(skb)->protocol == IPPROTO_UDP)
- netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT);
- else
- return;
+ u8 l4proto;
+
+ if (skb->protocol == htons(ETH_P_IP)) {
+ l4proto = ip_hdr(skb)->protocol;
+
+ if (l4proto == IPPROTO_TCP)
+ opcode = TX_TCP_PKT;
+ else if(l4proto == IPPROTO_UDP)
+ opcode = TX_UDP_PKT;
+ } else if (skb->protocol == htons(ETH_P_IPV6)) {
+ l4proto = ipv6_hdr(skb)->nexthdr;
+
+ if (l4proto == IPPROTO_TCP)
+ opcode = TX_TCPV6_PKT;
+ else if(l4proto == IPPROTO_UDP)
+ opcode = TX_UDPV6_PKT;
+ }
}
desc->tcp_hdr_offset = skb_transport_offset(skb);
desc->ip_hdr_offset = skb_network_offset(skb);
+ netxen_set_tx_flags_opcode(desc, 0, opcode);
+ return tso;
+}
+
+static void
+netxen_clean_tx_dma_mapping(struct pci_dev *pdev,
+ struct netxen_cmd_buffer *pbuf, int last)
+{
+ int k;
+ struct netxen_skb_frag *buffrag;
+
+ buffrag = &pbuf->frag_array[0];
+ pci_unmap_single(pdev, buffrag->dma,
+ buffrag->length, PCI_DMA_TODEVICE);
+
+ for (k = 1; k < last; k++) {
+ buffrag = &pbuf->frag_array[k];
+ pci_unmap_page(pdev, buffrag->dma,
+ buffrag->length, PCI_DMA_TODEVICE);
+ }
}
static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
@@ -1167,33 +1223,22 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
struct netxen_adapter *adapter = netdev_priv(netdev);
struct netxen_hardware_context *hw = &adapter->ahw;
unsigned int first_seg_len = skb->len - skb->data_len;
+ struct netxen_cmd_buffer *pbuf;
struct netxen_skb_frag *buffrag;
- unsigned int i;
+ struct cmd_desc_type0 *hwdesc;
+ struct pci_dev *pdev = adapter->pdev;
+ dma_addr_t temp_dma;
+ int i, k;
u32 producer, consumer;
- u32 saved_producer = 0;
- struct cmd_desc_type0 *hwdesc;
- int k;
- struct netxen_cmd_buffer *pbuf = NULL;
- int frag_count;
- int no_of_desc;
+ int frag_count, no_of_desc;
u32 num_txd = adapter->max_tx_desc_count;
+ bool is_tso = false;
frag_count = skb_shinfo(skb)->nr_frags + 1;
/* There 4 fragments per descriptor */
no_of_desc = (frag_count + 3) >> 2;
- if (netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) {
- if (skb_shinfo(skb)->gso_size > 0) {
-
- no_of_desc++;
- if ((ip_hdrlen(skb) + tcp_hdrlen(skb) +
- sizeof(struct ethhdr)) >
- (sizeof(struct cmd_desc_type0) - 2)) {
- no_of_desc++;
- }
- }
- }
producer = adapter->cmd_producer;
smp_mb();
@@ -1205,34 +1250,26 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
}
/* Copy the descriptors into the hardware */
- saved_producer = producer;
hwdesc = &hw->cmd_desc_head[producer];
memset(hwdesc, 0, sizeof(struct cmd_desc_type0));
/* Take skb->data itself */
pbuf = &adapter->cmd_buf_arr[producer];
- if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
- skb_shinfo(skb)->gso_size > 0) {
- pbuf->mss = skb_shinfo(skb)->gso_size;
- hwdesc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
- } else {
- pbuf->mss = 0;
- hwdesc->mss = 0;
- }
- pbuf->total_length = skb->len;
+
+ is_tso = netxen_tso_check(netdev, hwdesc, skb);
+
pbuf->skb = skb;
- pbuf->cmd = TX_ETHER_PKT;
pbuf->frag_count = frag_count;
- pbuf->port = adapter->portnum;
buffrag = &pbuf->frag_array[0];
- buffrag->dma = pci_map_single(adapter->pdev, skb->data, first_seg_len,
+ temp_dma = pci_map_single(pdev, skb->data, first_seg_len,
PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(pdev, temp_dma))
+ goto drop_packet;
+
+ buffrag->dma = temp_dma;
buffrag->length = first_seg_len;
- netxen_set_cmd_desc_totallength(hwdesc, skb->len);
- netxen_set_cmd_desc_num_of_buff(hwdesc, frag_count);
- netxen_set_cmd_desc_opcode(hwdesc, TX_ETHER_PKT);
+ netxen_set_tx_frags_len(hwdesc, frag_count, skb->len);
+ netxen_set_tx_port(hwdesc, adapter->portnum);
- netxen_set_cmd_desc_port(hwdesc, adapter->portnum);
- netxen_set_cmd_desc_ctxid(hwdesc, adapter->portnum);
hwdesc->buffer1_length = cpu_to_le16(first_seg_len);
hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
@@ -1240,7 +1277,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
struct skb_frag_struct *frag;
int len, temp_len;
unsigned long offset;
- dma_addr_t temp_dma;
/* move to next desc. if there is a need */
if ((i & 0x3) == 0) {
@@ -1256,8 +1292,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
offset = frag->page_offset;
temp_len = len;
- temp_dma = pci_map_page(adapter->pdev, frag->page, offset,
+ temp_dma = pci_map_page(pdev, frag->page, offset,
len, PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(pdev, temp_dma)) {
+ netxen_clean_tx_dma_mapping(pdev, pbuf, i);
+ goto drop_packet;
+ }
buffrag++;
buffrag->dma = temp_dma;
@@ -1285,16 +1325,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
}
producer = get_next_index(producer, num_txd);
- /* might change opcode to TX_TCP_LSO */
- netxen_tso_check(adapter, &hw->cmd_desc_head[saved_producer], skb);
-
/* For LSO, we need to copy the MAC/IP/TCP headers into
* the descriptor ring
*/
- if (netxen_get_cmd_desc_opcode(&hw->cmd_desc_head[saved_producer])
- == TX_TCP_LSO) {
+ if (is_tso) {
int hdr_len, first_hdr_len, more_hdr;
- hdr_len = hw->cmd_desc_head[saved_producer].total_hdr_length;
+ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
if (hdr_len > (sizeof(struct cmd_desc_type0) - 2)) {
first_hdr_len = sizeof(struct cmd_desc_type0) - 2;
more_hdr = 1;
@@ -1336,6 +1372,11 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
netdev->trans_start = jiffies;
return NETDEV_TX_OK;
+
+drop_packet:
+ adapter->stats.txdropped++;
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
}
static int netxen_nic_check_temp(struct netxen_adapter *adapter)
@@ -1407,6 +1448,8 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
netif_carrier_off(netdev);
netif_stop_queue(netdev);
}
+
+ netxen_nic_set_link_parameters(adapter);
} else if (!adapter->ahw.linkup && linkup) {
printk(KERN_INFO "%s: %s NIC Link is up\n",
netxen_nic_driver_name, netdev->name);
@@ -1415,6 +1458,8 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
netif_carrier_on(netdev);
netif_wake_queue(netdev);
}
+
+ netxen_nic_set_link_parameters(adapter);
}
}
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index 42021ac..e80294d 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -1956,6 +1956,7 @@ static const struct net_device_ops netdev_ops = {
.ndo_change_mtu = ns83820_change_mtu,
.ndo_set_multicast_list = ns83820_set_multicast,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_tx_timeout = ns83820_tx_timeout,
#ifdef NS83820_VLAN_ACCEL_SUPPORT
.ndo_vlan_rx_register = ns83820_vlan_rx_register,
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index 5b7a574..d0349e7 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -712,7 +712,7 @@ static inline void pasemi_mac_rx_error(const struct pasemi_mac *mac,
rcmdsta = read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
ccmdsta = read_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(chan->chno));
- printk(KERN_ERR "pasemi_mac: rx error. macrx %016lx, rx status %lx\n",
+ printk(KERN_ERR "pasemi_mac: rx error. macrx %016llx, rx status %llx\n",
macrx, *chan->status);
printk(KERN_ERR "pasemi_mac: rcmdsta %08x ccmdsta %08x\n",
@@ -730,8 +730,8 @@ static inline void pasemi_mac_tx_error(const struct pasemi_mac *mac,
cmdsta = read_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(chan->chno));
- printk(KERN_ERR "pasemi_mac: tx error. mactx 0x%016lx, "\
- "tx status 0x%016lx\n", mactx, *chan->status);
+ printk(KERN_ERR "pasemi_mac: tx error. mactx 0x%016llx, "\
+ "tx status 0x%016llx\n", mactx, *chan->status);
printk(KERN_ERR "pasemi_mac: tcmdsta 0x%08x\n", cmdsta);
}
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index e354601..0a06e4f 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -231,15 +231,6 @@ struct phy_device * get_phy_device(struct mii_bus *bus, int addr)
if ((phy_id & 0x1fffffff) == 0x1fffffff)
return NULL;
- /*
- * Broken hardware is sometimes missing the pull-up resistor on the
- * MDIO line, which results in reads to non-existent devices returning
- * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent
- * device as well.
- */
- if (phy_id == 0)
- return NULL;
-
dev = phy_device_create(bus, addr, phy_id);
return dev;
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 06b4482..7b2728b 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -250,6 +250,7 @@ static int ppp_connect_channel(struct channel *pch, int unit);
static int ppp_disconnect_channel(struct channel *pch);
static void ppp_destroy_channel(struct channel *pch);
static int unit_get(struct idr *p, void *ptr);
+static int unit_set(struct idr *p, void *ptr, int n);
static void unit_put(struct idr *p, int n);
static void *unit_find(struct idr *p, int n);
@@ -2432,11 +2433,18 @@ ppp_create_interface(int unit, int *retp)
} else {
if (unit_find(&ppp_units_idr, unit))
goto out2; /* unit already exists */
- else {
- /* darn, someone is cheating us? */
- *retp = -EINVAL;
+ /*
+ * if caller need a specified unit number
+ * lets try to satisfy him, otherwise --
+ * he should better ask us for new unit number
+ *
+ * NOTE: yes I know that returning EEXIST it's not
+ * fair but at least pppd will ask us to allocate
+ * new unit in this case so user is happy :)
+ */
+ unit = unit_set(&ppp_units_idr, ppp, unit);
+ if (unit < 0)
goto out2;
- }
}
/* Initialize the new ppp unit */
@@ -2677,14 +2685,37 @@ static void __exit ppp_cleanup(void)
* by holding all_ppp_mutex
*/
+/* associate pointer with specified number */
+static int unit_set(struct idr *p, void *ptr, int n)
+{
+ int unit, err;
+
+again:
+ if (!idr_pre_get(p, GFP_KERNEL)) {
+ printk(KERN_ERR "PPP: No free memory for idr\n");
+ return -ENOMEM;
+ }
+
+ err = idr_get_new_above(p, ptr, n, &unit);
+ if (err == -EAGAIN)
+ goto again;
+
+ if (unit != n) {
+ idr_remove(p, unit);
+ return -EINVAL;
+ }
+
+ return unit;
+}
+
/* get new free unit number and associate pointer with it */
static int unit_get(struct idr *p, void *ptr)
{
int unit, err;
again:
- if (idr_pre_get(p, GFP_KERNEL) == 0) {
- printk(KERN_ERR "Out of memory expanding drawable idr\n");
+ if (!idr_pre_get(p, GFP_KERNEL)) {
+ printk(KERN_ERR "PPP: No free memory for idr\n");
return -ENOMEM;
}
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h
index 459663a..c1dadad 100644
--- a/drivers/net/qlge/qlge.h
+++ b/drivers/net/qlge/qlge.h
@@ -28,11 +28,11 @@
} while (0)
#define QLGE_VENDOR_ID 0x1077
-#define QLGE_DEVICE_ID1 0x8012
-#define QLGE_DEVICE_ID 0x8000
+#define QLGE_DEVICE_ID 0x8012
-#define MAX_RX_RINGS 128
-#define MAX_TX_RINGS 128
+#define MAX_CPUS 8
+#define MAX_TX_RINGS MAX_CPUS
+#define MAX_RX_RINGS ((MAX_CPUS * 2) + 1)
#define NUM_TX_RING_ENTRIES 256
#define NUM_RX_RING_ENTRIES 256
@@ -45,6 +45,7 @@
#define MAX_SPLIT_SIZE 1023
#define QLGE_SB_PAD 32
+#define MAX_CQ 128
#define DFLT_COALESCE_WAIT 100 /* 100 usec wait for coalescing */
#define MAX_INTER_FRAME_WAIT 10 /* 10 usec max interframe-wait for coalescing */
#define DFLT_INTER_FRAME_WAIT (MAX_INTER_FRAME_WAIT/2)
@@ -961,8 +962,7 @@ struct ib_mac_iocb_rsp {
#define IB_MAC_IOCB_RSP_DS 0x40 /* data is in small buffer */
#define IB_MAC_IOCB_RSP_DL 0x80 /* data is in large buffer */
__le32 data_len; /* */
- __le32 data_addr_lo; /* */
- __le32 data_addr_hi; /* */
+ __le64 data_addr; /* */
__le32 rss; /* */
__le16 vlan_id; /* 12 bits */
#define IB_MAC_IOCB_RSP_C 0x1000 /* VLAN CFI bit */
@@ -976,8 +976,7 @@ struct ib_mac_iocb_rsp {
#define IB_MAC_IOCB_RSP_HS 0x40
#define IB_MAC_IOCB_RSP_HL 0x80
__le32 hdr_len; /* */
- __le32 hdr_addr_lo; /* */
- __le32 hdr_addr_hi; /* */
+ __le64 hdr_addr; /* */
} __attribute((packed));
struct ib_ae_iocb_rsp {
@@ -1042,10 +1041,8 @@ struct wqicb {
__le16 cq_id_rss;
#define Q_CQ_ID_RSS_RV 0x8000
__le16 rid;
- __le32 addr_lo;
- __le32 addr_hi;
- __le32 cnsmr_idx_addr_lo;
- __le32 cnsmr_idx_addr_hi;
+ __le64 addr;
+ __le64 cnsmr_idx_addr;
} __attribute((packed));
/*
@@ -1070,18 +1067,14 @@ struct cqicb {
#define LEN_CPP_64 0x0002
#define LEN_CPP_128 0x0003
__le16 rid;
- __le32 addr_lo;
- __le32 addr_hi;
- __le32 prod_idx_addr_lo;
- __le32 prod_idx_addr_hi;
+ __le64 addr;
+ __le64 prod_idx_addr;
__le16 pkt_delay;
__le16 irq_delay;
- __le32 lbq_addr_lo;
- __le32 lbq_addr_hi;
+ __le64 lbq_addr;
__le16 lbq_buf_size;
__le16 lbq_len; /* entry count */
- __le32 sbq_addr_lo;
- __le32 sbq_addr_hi;
+ __le64 sbq_addr;
__le16 sbq_buf_size;
__le16 sbq_len; /* entry count */
} __attribute((packed));
@@ -1145,7 +1138,7 @@ struct tx_ring {
struct wqicb wqicb; /* structure used to inform chip of new queue */
void *wq_base; /* pci_alloc:virtual addr for tx */
dma_addr_t wq_base_dma; /* pci_alloc:dma addr for tx */
- u32 *cnsmr_idx_sh_reg; /* shadow copy of consumer idx */
+ __le32 *cnsmr_idx_sh_reg; /* shadow copy of consumer idx */
dma_addr_t cnsmr_idx_sh_reg_dma; /* dma-shadow copy of consumer */
u32 wq_size; /* size in bytes of queue area */
u32 wq_len; /* number of entries in queue */
@@ -1181,7 +1174,7 @@ struct rx_ring {
u32 cq_size;
u32 cq_len;
u16 cq_id;
- volatile __le32 *prod_idx_sh_reg; /* Shadowed producer register. */
+ __le32 *prod_idx_sh_reg; /* Shadowed producer register. */
dma_addr_t prod_idx_sh_reg_dma;
void __iomem *cnsmr_idx_db_reg; /* PCI doorbell mem area + 0 */
u32 cnsmr_idx; /* current sw idx */
@@ -1402,9 +1395,11 @@ struct ql_adapter {
int rx_ring_count;
int ring_mem_size;
void *ring_mem;
- struct rx_ring *rx_ring;
+
+ struct rx_ring rx_ring[MAX_RX_RINGS];
+ struct tx_ring tx_ring[MAX_TX_RINGS];
+
int rx_csum;
- struct tx_ring *tx_ring;
u32 default_rx_queue;
u16 rx_coalesce_usecs; /* cqicb->int_delay */
@@ -1459,6 +1454,24 @@ static inline void ql_write_db_reg(u32 val, void __iomem *addr)
mmiowb();
}
+/*
+ * Shadow Registers:
+ * Outbound queues have a consumer index that is maintained by the chip.
+ * Inbound queues have a producer index that is maintained by the chip.
+ * For lower overhead, these registers are "shadowed" to host memory
+ * which allows the device driver to track the queue progress without
+ * PCI reads. When an entry is placed on an inbound queue, the chip will
+ * update the relevant index register and then copy the value to the
+ * shadow register in host memory.
+ */
+static inline u32 ql_read_sh_reg(__le32 *addr)
+{
+ u32 reg;
+ reg = le32_to_cpu(*addr);
+ rmb();
+ return reg;
+}
+
extern char qlge_driver_name[];
extern const char qlge_driver_version[];
extern const struct ethtool_ops qlge_ethtool_ops;
diff --git a/drivers/net/qlge/qlge_dbg.c b/drivers/net/qlge/qlge_dbg.c
index 3f5e02d..379b895 100644
--- a/drivers/net/qlge/qlge_dbg.c
+++ b/drivers/net/qlge/qlge_dbg.c
@@ -435,14 +435,10 @@ void ql_dump_wqicb(struct wqicb *wqicb)
printk(KERN_ERR PFX "wqicb->cq_id_rss = %d.\n",
le16_to_cpu(wqicb->cq_id_rss));
printk(KERN_ERR PFX "wqicb->rid = 0x%x.\n", le16_to_cpu(wqicb->rid));
- printk(KERN_ERR PFX "wqicb->wq_addr_lo = 0x%.08x.\n",
- le32_to_cpu(wqicb->addr_lo));
- printk(KERN_ERR PFX "wqicb->wq_addr_hi = 0x%.08x.\n",
- le32_to_cpu(wqicb->addr_hi));
- printk(KERN_ERR PFX "wqicb->wq_cnsmr_idx_addr_lo = 0x%.08x.\n",
- le32_to_cpu(wqicb->cnsmr_idx_addr_lo));
- printk(KERN_ERR PFX "wqicb->wq_cnsmr_idx_addr_hi = 0x%.08x.\n",
- le32_to_cpu(wqicb->cnsmr_idx_addr_hi));
+ printk(KERN_ERR PFX "wqicb->wq_addr = 0x%llx.\n",
+ (unsigned long long) le64_to_cpu(wqicb->addr));
+ printk(KERN_ERR PFX "wqicb->wq_cnsmr_idx_addr = 0x%llx.\n",
+ (unsigned long long) le64_to_cpu(wqicb->cnsmr_idx_addr));
}
void ql_dump_tx_ring(struct tx_ring *tx_ring)
@@ -455,10 +451,11 @@ void ql_dump_tx_ring(struct tx_ring *tx_ring)
printk(KERN_ERR PFX "tx_ring->base = %p.\n", tx_ring->wq_base);
printk(KERN_ERR PFX "tx_ring->base_dma = 0x%llx.\n",
(unsigned long long) tx_ring->wq_base_dma);
- printk(KERN_ERR PFX "tx_ring->cnsmr_idx_sh_reg = %p.\n",
- tx_ring->cnsmr_idx_sh_reg);
- printk(KERN_ERR PFX "tx_ring->cnsmr_idx_sh_reg_dma = 0x%llx.\n",
- (unsigned long long) tx_ring->cnsmr_idx_sh_reg_dma);
+ printk(KERN_ERR PFX
+ "tx_ring->cnsmr_idx_sh_reg, addr = 0x%p, value = %d.\n",
+ tx_ring->cnsmr_idx_sh_reg,
+ tx_ring->cnsmr_idx_sh_reg
+ ? ql_read_sh_reg(tx_ring->cnsmr_idx_sh_reg) : 0);
printk(KERN_ERR PFX "tx_ring->size = %d.\n", tx_ring->wq_size);
printk(KERN_ERR PFX "tx_ring->len = %d.\n", tx_ring->wq_len);
printk(KERN_ERR PFX "tx_ring->prod_idx_db_reg = %p.\n",
@@ -510,30 +507,22 @@ void ql_dump_cqicb(struct cqicb *cqicb)
printk(KERN_ERR PFX "cqicb->msix_vect = %d.\n", cqicb->msix_vect);
printk(KERN_ERR PFX "cqicb->flags = %x.\n", cqicb->flags);
printk(KERN_ERR PFX "cqicb->len = %d.\n", le16_to_cpu(cqicb->len));
- printk(KERN_ERR PFX "cqicb->addr_lo = %x.\n",
- le32_to_cpu(cqicb->addr_lo));
- printk(KERN_ERR PFX "cqicb->addr_hi = %x.\n",
- le32_to_cpu(cqicb->addr_hi));
- printk(KERN_ERR PFX "cqicb->prod_idx_addr_lo = %x.\n",
- le32_to_cpu(cqicb->prod_idx_addr_lo));
- printk(KERN_ERR PFX "cqicb->prod_idx_addr_hi = %x.\n",
- le32_to_cpu(cqicb->prod_idx_addr_hi));
+ printk(KERN_ERR PFX "cqicb->addr = 0x%llx.\n",
+ (unsigned long long) le64_to_cpu(cqicb->addr));
+ printk(KERN_ERR PFX "cqicb->prod_idx_addr = 0x%llx.\n",
+ (unsigned long long) le64_to_cpu(cqicb->prod_idx_addr));
printk(KERN_ERR PFX "cqicb->pkt_delay = 0x%.04x.\n",
le16_to_cpu(cqicb->pkt_delay));
printk(KERN_ERR PFX "cqicb->irq_delay = 0x%.04x.\n",
le16_to_cpu(cqicb->irq_delay));
- printk(KERN_ERR PFX "cqicb->lbq_addr_lo = %x.\n",
- le32_to_cpu(cqicb->lbq_addr_lo));
- printk(KERN_ERR PFX "cqicb->lbq_addr_hi = %x.\n",
- le32_to_cpu(cqicb->lbq_addr_hi));
+ printk(KERN_ERR PFX "cqicb->lbq_addr = 0x%llx.\n",
+ (unsigned long long) le64_to_cpu(cqicb->lbq_addr));
printk(KERN_ERR PFX "cqicb->lbq_buf_size = 0x%.04x.\n",
le16_to_cpu(cqicb->lbq_buf_size));
printk(KERN_ERR PFX "cqicb->lbq_len = 0x%.04x.\n",
le16_to_cpu(cqicb->lbq_len));
- printk(KERN_ERR PFX "cqicb->sbq_addr_lo = %x.\n",
- le32_to_cpu(cqicb->sbq_addr_lo));
- printk(KERN_ERR PFX "cqicb->sbq_addr_hi = %x.\n",
- le32_to_cpu(cqicb->sbq_addr_hi));
+ printk(KERN_ERR PFX "cqicb->sbq_addr = 0x%llx.\n",
+ (unsigned long long) le64_to_cpu(cqicb->sbq_addr));
printk(KERN_ERR PFX "cqicb->sbq_buf_size = 0x%.04x.\n",
le16_to_cpu(cqicb->sbq_buf_size));
printk(KERN_ERR PFX "cqicb->sbq_len = 0x%.04x.\n",
@@ -558,9 +547,10 @@ void ql_dump_rx_ring(struct rx_ring *rx_ring)
printk(KERN_ERR PFX "rx_ring->cq_size = %d.\n", rx_ring->cq_size);
printk(KERN_ERR PFX "rx_ring->cq_len = %d.\n", rx_ring->cq_len);
printk(KERN_ERR PFX
- "rx_ring->prod_idx_sh_reg, addr = %p, value = %d.\n",
+ "rx_ring->prod_idx_sh_reg, addr = 0x%p, value = %d.\n",
rx_ring->prod_idx_sh_reg,
- rx_ring->prod_idx_sh_reg ? *(rx_ring->prod_idx_sh_reg) : 0);
+ rx_ring->prod_idx_sh_reg
+ ? ql_read_sh_reg(rx_ring->prod_idx_sh_reg) : 0);
printk(KERN_ERR PFX "rx_ring->prod_idx_sh_reg_dma = %llx.\n",
(unsigned long long) rx_ring->prod_idx_sh_reg_dma);
printk(KERN_ERR PFX "rx_ring->cnsmr_idx_db_reg = %p.\n",
@@ -809,10 +799,8 @@ void ql_dump_ib_mac_rsp(struct ib_mac_iocb_rsp *ib_mac_rsp)
printk(KERN_ERR PFX "data_len = %d\n",
le32_to_cpu(ib_mac_rsp->data_len));
- printk(KERN_ERR PFX "data_addr_hi = 0x%x\n",
- le32_to_cpu(ib_mac_rsp->data_addr_hi));
- printk(KERN_ERR PFX "data_addr_lo = 0x%x\n",
- le32_to_cpu(ib_mac_rsp->data_addr_lo));
+ printk(KERN_ERR PFX "data_addr = 0x%llx\n",
+ (unsigned long long) le64_to_cpu(ib_mac_rsp->data_addr));
if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK)
printk(KERN_ERR PFX "rss = %x\n",
le32_to_cpu(ib_mac_rsp->rss));
@@ -828,10 +816,8 @@ void ql_dump_ib_mac_rsp(struct ib_mac_iocb_rsp *ib_mac_rsp)
if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV) {
printk(KERN_ERR PFX "hdr length = %d.\n",
le32_to_cpu(ib_mac_rsp->hdr_len));
- printk(KERN_ERR PFX "hdr addr_hi = 0x%x.\n",
- le32_to_cpu(ib_mac_rsp->hdr_addr_hi));
- printk(KERN_ERR PFX "hdr addr_lo = 0x%x.\n",
- le32_to_cpu(ib_mac_rsp->hdr_addr_lo));
+ printk(KERN_ERR PFX "hdr addr = 0x%llx.\n",
+ (unsigned long long) le64_to_cpu(ib_mac_rsp->hdr_addr));
}
}
#endif
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index f4c0160..45421c8 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -76,7 +76,6 @@ MODULE_PARM_DESC(irq_type, "0 = MSI-X, 1 = MSI, 2 = Legacy.");
static struct pci_device_id qlge_pci_tbl[] __devinitdata = {
{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID)},
- {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID1)},
/* required last entry */
{0,}
};
@@ -127,12 +126,12 @@ static int ql_sem_trylock(struct ql_adapter *qdev, u32 sem_mask)
int ql_sem_spinlock(struct ql_adapter *qdev, u32 sem_mask)
{
- unsigned int seconds = 3;
+ unsigned int wait_count = 30;
do {
if (!ql_sem_trylock(qdev, sem_mask))
return 0;
- ssleep(1);
- } while (--seconds);
+ udelay(100);
+ } while (--wait_count);
return -ETIMEDOUT;
}
@@ -1545,7 +1544,7 @@ static void ql_process_chip_ae_intr(struct ql_adapter *qdev,
static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring)
{
struct ql_adapter *qdev = rx_ring->qdev;
- u32 prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg);
+ u32 prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg);
struct ob_mac_iocb_rsp *net_rsp = NULL;
int count = 0;
@@ -1571,7 +1570,7 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring)
}
count++;
ql_update_cq(rx_ring);
- prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg);
+ prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg);
}
ql_write_cq_idx(rx_ring);
if (netif_queue_stopped(qdev->ndev) && net_rsp != NULL) {
@@ -1591,7 +1590,7 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring)
static int ql_clean_inbound_rx_ring(struct rx_ring *rx_ring, int budget)
{
struct ql_adapter *qdev = rx_ring->qdev;
- u32 prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg);
+ u32 prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg);
struct ql_net_rsp_iocb *net_rsp;
int count = 0;
@@ -1624,7 +1623,7 @@ static int ql_clean_inbound_rx_ring(struct rx_ring *rx_ring, int budget)
}
count++;
ql_update_cq(rx_ring);
- prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg);
+ prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg);
if (count == budget)
break;
}
@@ -1787,7 +1786,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id)
* Check the default queue and wake handler if active.
*/
rx_ring = &qdev->rx_ring[0];
- if (le32_to_cpu(*rx_ring->prod_idx_sh_reg) != rx_ring->cnsmr_idx) {
+ if (ql_read_sh_reg(rx_ring->prod_idx_sh_reg) != rx_ring->cnsmr_idx) {
QPRINTK(qdev, INTR, INFO, "Waking handler for rx_ring[0].\n");
ql_disable_completion_interrupt(qdev, intr_context->intr);
queue_delayed_work_on(smp_processor_id(), qdev->q_workqueue,
@@ -1801,7 +1800,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id)
*/
for (i = 1; i < qdev->rx_ring_count; i++) {
rx_ring = &qdev->rx_ring[i];
- if (le32_to_cpu(*rx_ring->prod_idx_sh_reg) !=
+ if (ql_read_sh_reg(rx_ring->prod_idx_sh_reg) !=
rx_ring->cnsmr_idx) {
QPRINTK(qdev, INTR, INFO,
"Waking handler for rx_ring[%d].\n", i);
@@ -2356,28 +2355,6 @@ static void ql_tx_ring_clean(struct ql_adapter *qdev)
}
}
-static void ql_free_ring_cb(struct ql_adapter *qdev)
-{
- kfree(qdev->ring_mem);
-}
-
-static int ql_alloc_ring_cb(struct ql_adapter *qdev)
-{
- /* Allocate space for tx/rx ring control blocks. */
- qdev->ring_mem_size =
- (qdev->tx_ring_count * sizeof(struct tx_ring)) +
- (qdev->rx_ring_count * sizeof(struct rx_ring));
- qdev->ring_mem = kmalloc(qdev->ring_mem_size, GFP_KERNEL);
- if (qdev->ring_mem == NULL) {
- return -ENOMEM;
- } else {
- qdev->rx_ring = qdev->ring_mem;
- qdev->tx_ring = qdev->ring_mem +
- (qdev->rx_ring_count * sizeof(struct rx_ring));
- }
- return 0;
-}
-
static void ql_free_mem_resources(struct ql_adapter *qdev)
{
int i;
@@ -2467,12 +2444,9 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
bq_len = (rx_ring->cq_len == 65536) ? 0 : (u16) rx_ring->cq_len;
cqicb->len = cpu_to_le16(bq_len | LEN_V | LEN_CPP_CONT);
- cqicb->addr_lo = cpu_to_le32(rx_ring->cq_base_dma);
- cqicb->addr_hi = cpu_to_le32((u64) rx_ring->cq_base_dma >> 32);
+ cqicb->addr = cpu_to_le64(rx_ring->cq_base_dma);
- cqicb->prod_idx_addr_lo = cpu_to_le32(rx_ring->prod_idx_sh_reg_dma);
- cqicb->prod_idx_addr_hi =
- cpu_to_le32((u64) rx_ring->prod_idx_sh_reg_dma >> 32);
+ cqicb->prod_idx_addr = cpu_to_le64(rx_ring->prod_idx_sh_reg_dma);
/*
* Set up the control block load flags.
@@ -2483,10 +2457,8 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
if (rx_ring->lbq_len) {
cqicb->flags |= FLAGS_LL; /* Load lbq values */
*((u64 *) rx_ring->lbq_base_indirect) = rx_ring->lbq_base_dma;
- cqicb->lbq_addr_lo =
- cpu_to_le32(rx_ring->lbq_base_indirect_dma);
- cqicb->lbq_addr_hi =
- cpu_to_le32((u64) rx_ring->lbq_base_indirect_dma >> 32);
+ cqicb->lbq_addr =
+ cpu_to_le64(rx_ring->lbq_base_indirect_dma);
bq_len = (rx_ring->lbq_buf_size == 65536) ? 0 :
(u16) rx_ring->lbq_buf_size;
cqicb->lbq_buf_size = cpu_to_le16(bq_len);
@@ -2501,10 +2473,8 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
if (rx_ring->sbq_len) {
cqicb->flags |= FLAGS_LS; /* Load sbq values */
*((u64 *) rx_ring->sbq_base_indirect) = rx_ring->sbq_base_dma;
- cqicb->sbq_addr_lo =
- cpu_to_le32(rx_ring->sbq_base_indirect_dma);
- cqicb->sbq_addr_hi =
- cpu_to_le32((u64) rx_ring->sbq_base_indirect_dma >> 32);
+ cqicb->sbq_addr =
+ cpu_to_le64(rx_ring->sbq_base_indirect_dma);
cqicb->sbq_buf_size =
cpu_to_le16(((rx_ring->sbq_buf_size / 2) + 8) & 0xfffffff8);
bq_len = (rx_ring->sbq_len == 65536) ? 0 :
@@ -2611,12 +2581,9 @@ static int ql_start_tx_ring(struct ql_adapter *qdev, struct tx_ring *tx_ring)
Q_FLAGS_LB | Q_FLAGS_LI | Q_FLAGS_LO);
wqicb->cq_id_rss = cpu_to_le16(tx_ring->cq_id);
wqicb->rid = 0;
- wqicb->addr_lo = cpu_to_le32(tx_ring->wq_base_dma);
- wqicb->addr_hi = cpu_to_le32((u64) tx_ring->wq_base_dma >> 32);
+ wqicb->addr = cpu_to_le64(tx_ring->wq_base_dma);
- wqicb->cnsmr_idx_addr_lo = cpu_to_le32(tx_ring->cnsmr_idx_sh_reg_dma);
- wqicb->cnsmr_idx_addr_hi =
- cpu_to_le32((u64) tx_ring->cnsmr_idx_sh_reg_dma >> 32);
+ wqicb->cnsmr_idx_addr = cpu_to_le64(tx_ring->cnsmr_idx_sh_reg_dma);
ql_init_tx_ring(qdev, tx_ring);
@@ -2746,14 +2713,14 @@ static void ql_resolve_queues_to_irqs(struct ql_adapter *qdev)
* Outbound queue is for outbound completions only.
*/
intr_context->handler = qlge_msix_tx_isr;
- sprintf(intr_context->name, "%s-txq-%d",
+ sprintf(intr_context->name, "%s-tx-%d",
qdev->ndev->name, i);
} else {
/*
* Inbound queues handle unicast frames only.
*/
intr_context->handler = qlge_msix_rx_isr;
- sprintf(intr_context->name, "%s-rxq-%d",
+ sprintf(intr_context->name, "%s-rx-%d",
qdev->ndev->name, i);
}
}
@@ -3247,7 +3214,6 @@ static int qlge_close(struct net_device *ndev)
msleep(1);
ql_adapter_down(qdev);
ql_release_adapter_resources(qdev);
- ql_free_ring_cb(qdev);
return 0;
}
@@ -3273,8 +3239,8 @@ static int ql_configure_rings(struct ql_adapter *qdev)
* This limitation can be removed when requested.
*/
- if (cpu_cnt > 8)
- cpu_cnt = 8;
+ if (cpu_cnt > MAX_CPUS)
+ cpu_cnt = MAX_CPUS;
/*
* rx_ring[0] is always the default queue.
@@ -3294,9 +3260,6 @@ static int ql_configure_rings(struct ql_adapter *qdev)
*/
qdev->rx_ring_count = qdev->tx_ring_count + qdev->rss_ring_count + 1;
- if (ql_alloc_ring_cb(qdev))
- return -ENOMEM;
-
for (i = 0; i < qdev->tx_ring_count; i++) {
tx_ring = &qdev->tx_ring[i];
memset((void *)tx_ring, 0, sizeof(tx_ring));
@@ -3393,7 +3356,6 @@ static int qlge_open(struct net_device *ndev)
error_up:
ql_release_adapter_resources(qdev);
- ql_free_ring_cb(qdev);
return err;
}
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c
index cf3a082..72fd9e9 100644
--- a/drivers/net/r6040.c
+++ b/drivers/net/r6040.c
@@ -49,8 +49,8 @@
#include <asm/processor.h>
#define DRV_NAME "r6040"
-#define DRV_VERSION "0.20"
-#define DRV_RELDATE "07Jan2009"
+#define DRV_VERSION "0.21"
+#define DRV_RELDATE "09Jan2009"
/* PHY CHIP Address */
#define PHY1_ADDR 1 /* For MAC1 */
@@ -457,22 +457,12 @@ static void r6040_down(struct net_device *dev)
iowrite16(adrp[0], ioaddr + MID_0L);
iowrite16(adrp[1], ioaddr + MID_0M);
iowrite16(adrp[2], ioaddr + MID_0H);
- free_irq(dev->irq, dev);
-
- /* Free RX buffer */
- r6040_free_rxbufs(dev);
-
- /* Free TX buffer */
- r6040_free_txbufs(dev);
-
- /* Free Descriptor memory */
- pci_free_consistent(pdev, RX_DESC_SIZE, lp->rx_ring, lp->rx_ring_dma);
- pci_free_consistent(pdev, TX_DESC_SIZE, lp->tx_ring, lp->tx_ring_dma);
}
static int r6040_close(struct net_device *dev)
{
struct r6040_private *lp = netdev_priv(dev);
+ struct pci_dev *pdev = lp->pdev;
/* deleted timer */
del_timer_sync(&lp->timer);
@@ -481,8 +471,28 @@ static int r6040_close(struct net_device *dev)
napi_disable(&lp->napi);
netif_stop_queue(dev);
r6040_down(dev);
+
+ free_irq(dev->irq, dev);
+
+ /* Free RX buffer */
+ r6040_free_rxbufs(dev);
+
+ /* Free TX buffer */
+ r6040_free_txbufs(dev);
+
spin_unlock_irq(&lp->lock);
+ /* Free Descriptor memory */
+ if (lp->rx_ring) {
+ pci_free_consistent(pdev, RX_DESC_SIZE, lp->rx_ring, lp->rx_ring_dma);
+ lp->rx_ring = 0;
+ }
+
+ if (lp->tx_ring) {
+ pci_free_consistent(pdev, TX_DESC_SIZE, lp->tx_ring, lp->tx_ring_dma);
+ lp->tx_ring = 0;
+ }
+
return 0;
}
@@ -1049,6 +1059,7 @@ static const struct net_device_ops r6040_netdev_ops = {
.ndo_set_multicast_list = r6040_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_do_ioctl = r6040_ioctl,
.ndo_tx_timeout = r6040_tx_timeout,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1143,8 +1154,10 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
/* Some bootloader/BIOSes do not initialize
* MAC address, warn about that */
- if (!(adrp[0] || adrp[1] || adrp[2]))
- printk(KERN_WARNING DRV_NAME ": MAC address not initialized\n");
+ if (!(adrp[0] || adrp[1] || adrp[2])) {
+ printk(KERN_WARNING DRV_NAME ": MAC address not initialized, generating random\n");
+ random_ether_addr(dev->dev_addr);
+ }
/* Link new device into r6040_root_dev */
lp->pdev = pdev;
diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c
index 42fd312..8b75bef 100644
--- a/drivers/net/sc92031.c
+++ b/drivers/net/sc92031.c
@@ -1408,6 +1408,7 @@ static const struct net_device_ops sc92031_netdev_ops = {
.ndo_set_multicast_list = sc92031_set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_tx_timeout = sc92031_tx_timeout,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = sc92031_poll_controller,
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index b976876..9ecb77d 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -636,10 +636,11 @@ static void tenxpress_phy_fini(struct efx_nic *efx)
{
int reg;
- if (efx->phy_type == PHY_TYPE_SFT9001B) {
+ if (efx->phy_type == PHY_TYPE_SFT9001B)
device_remove_file(&efx->pci_dev->dev,
&dev_attr_phy_short_reach);
- } else {
+
+ if (efx->phy_type == PHY_TYPE_SFX7101) {
/* Power down the LNPGA */
reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN);
mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 4acd41a..be4465b 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -389,6 +389,7 @@ static const struct net_device_ops sis900_netdev_ops = {
.ndo_set_multicast_list = set_rx_mode,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_do_ioctl = mii_ioctl,
.ndo_tx_timeout = sis900_tx_timeout,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -508,10 +509,10 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
else
ret = sis900_get_mac_addr(pci_dev, net_dev);
- if (ret == 0) {
- printk(KERN_WARNING "%s: Cannot read MAC address.\n", dev_name);
- ret = -ENODEV;
- goto err_unmap_rx;
+ if (!ret || !is_valid_ether_addr(net_dev->dev_addr)) {
+ random_ether_addr(net_dev->dev_addr);
+ printk(KERN_WARNING "%s: Unreadable or invalid MAC address,"
+ "using random generated one\n", dev_name);
}
/* 630ET : set the mii access mode as software-mode */
diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
index 404b80e..8d36d40 100644
--- a/drivers/net/smc-mca.c
+++ b/drivers/net/smc-mca.c
@@ -192,6 +192,7 @@ static const struct net_device_ops ultramca_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index b386608..2033fee 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -196,6 +196,7 @@ static const struct net_device_ops ultra_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
index dc3f110..f513bdf 100644
--- a/drivers/net/smsc911x.c
+++ b/drivers/net/smsc911x.c
@@ -144,6 +144,7 @@ static inline u32 smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg)
}
BUG();
+ return 0;
}
static inline void smsc911x_reg_write(struct smsc911x_data *pdata, u32 reg,
@@ -1740,6 +1741,7 @@ static const struct net_device_ops smsc911x_netdev_ops = {
.ndo_set_multicast_list = smsc911x_set_multicast_list,
.ndo_do_ioctl = smsc911x_do_ioctl,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = smsc911x_poll_controller,
#endif
@@ -1967,7 +1969,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
smsc911x_reg_write(pdata, INT_STS, 0xFFFFFFFF);
retval = request_irq(dev->irq, smsc911x_irqhandler, IRQF_DISABLED,
- SMSC_CHIPNAME, dev);
+ dev->name, dev);
if (retval) {
SMSC_WARNING(PROBE,
"Unable to claim requested irq: %d", dev->irq);
diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c
index 27e017d..c14a4c6 100644
--- a/drivers/net/smsc9420.c
+++ b/drivers/net/smsc9420.c
@@ -1551,6 +1551,7 @@ static const struct net_device_ops smsc9420_netdev_ops = {
.ndo_set_multicast_list = smsc9420_set_multicast_list,
.ndo_do_ioctl = smsc9420_do_ioctl,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = smsc9420_poll_controller,
#endif /* CONFIG_NET_POLL_CONTROLLER */
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 7d5a130..1144122 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -442,40 +442,30 @@ static void magic_packet_detection_enable(struct ucc_geth_private *ugeth)
{
struct ucc_fast_private *uccf;
struct ucc_geth __iomem *ug_regs;
- u32 maccfg2, uccm;
uccf = ugeth->uccf;
ug_regs = ugeth->ug_regs;
/* Enable interrupts for magic packet detection */
- uccm = in_be32(uccf->p_uccm);
- uccm |= UCCE_MPD;
- out_be32(uccf->p_uccm, uccm);
+ setbits32(uccf->p_uccm, UCC_GETH_UCCE_MPD);
/* Enable magic packet detection */
- maccfg2 = in_be32(&ug_regs->maccfg2);
- maccfg2 |= MACCFG2_MPE;
- out_be32(&ug_regs->maccfg2, maccfg2);
+ setbits32(&ug_regs->maccfg2, MACCFG2_MPE);
}
static void magic_packet_detection_disable(struct ucc_geth_private *ugeth)
{
struct ucc_fast_private *uccf;
struct ucc_geth __iomem *ug_regs;
- u32 maccfg2, uccm;
uccf = ugeth->uccf;
ug_regs = ugeth->ug_regs;
/* Disable interrupts for magic packet detection */
- uccm = in_be32(uccf->p_uccm);
- uccm &= ~UCCE_MPD;
- out_be32(uccf->p_uccm, uccm);
+ clrbits32(uccf->p_uccm, UCC_GETH_UCCE_MPD);
/* Disable magic packet detection */
- maccfg2 = in_be32(&ug_regs->maccfg2);
- maccfg2 &= ~MACCFG2_MPE;
- out_be32(&ug_regs->maccfg2, maccfg2);
+ clrbits32(&ug_regs->maccfg2, MACCFG2_MPE);
}
#endif /* MAGIC_PACKET */
@@ -585,7 +575,8 @@ static void get_statistics(struct ucc_geth_private *ugeth,
/* Hardware only if user handed pointer and driver actually
gathers hardware statistics */
- if (hardware_statistics && (in_be32(&uf_regs->upsmr) & UPSMR_HSE)) {
+ if (hardware_statistics &&
+ (in_be32(&uf_regs->upsmr) & UCC_GETH_UPSMR_HSE)) {
hardware_statistics->tx64 = in_be32(&ug_regs->tx64);
hardware_statistics->tx127 = in_be32(&ug_regs->tx127);
hardware_statistics->tx255 = in_be32(&ug_regs->tx255);
@@ -1181,9 +1172,7 @@ int init_flow_control_params(u32 automatic_flow_control_mode,
out_be32(uempr_register, value);
/* Set UPSMR register */
- value = in_be32(upsmr_register);
- value |= automatic_flow_control_mode;
- out_be32(upsmr_register, value);
+ setbits32(upsmr_register, automatic_flow_control_mode);
value = in_be32(maccfg1_register);
if (rx_flow_control_enable)
@@ -1200,14 +1189,11 @@ static int init_hw_statistics_gathering_mode(int enable_hardware_statistics,
u32 __iomem *upsmr_register,
u16 __iomem *uescr_register)
{
- u32 upsmr_value = 0;
u16 uescr_value = 0;
+
/* Enable hardware statistics gathering if requested */
- if (enable_hardware_statistics) {
- upsmr_value = in_be32(upsmr_register);
- upsmr_value |= UPSMR_HSE;
- out_be32(upsmr_register, upsmr_value);
- }
+ if (enable_hardware_statistics)
+ setbits32(upsmr_register, UCC_GETH_UPSMR_HSE);
/* Clear hardware statistics counters */
uescr_value = in_be16(uescr_register);
@@ -1233,23 +1219,17 @@ static int init_firmware_statistics_gathering_mode(int
{
/* Note: this function does not check if */
/* the parameters it receives are NULL */
- u16 temoder_value;
- u32 remoder_value;
if (enable_tx_firmware_statistics) {
out_be32(tx_rmon_base_ptr,
tx_firmware_statistics_structure_address);
- temoder_value = in_be16(temoder_register);
- temoder_value |= TEMODER_TX_RMON_STATISTICS_ENABLE;
- out_be16(temoder_register, temoder_value);
+ setbits16(temoder_register, TEMODER_TX_RMON_STATISTICS_ENABLE);
}
if (enable_rx_firmware_statistics) {
out_be32(rx_rmon_base_ptr,
rx_firmware_statistics_structure_address);
- remoder_value = in_be32(remoder_register);
- remoder_value |= REMODER_RX_RMON_STATISTICS_ENABLE;
- out_be32(remoder_register, remoder_value);
+ setbits32(remoder_register, REMODER_RX_RMON_STATISTICS_ENABLE);
}
return 0;
@@ -1316,15 +1296,12 @@ static int init_check_frame_length_mode(int length_check,
static int init_preamble_length(u8 preamble_length,
u32 __iomem *maccfg2_register)
{
- u32 value = 0;
-
if ((preamble_length < 3) || (preamble_length > 7))
return -EINVAL;
- value = in_be32(maccfg2_register);
- value &= ~MACCFG2_PREL_MASK;
- value |= (preamble_length << MACCFG2_PREL_SHIFT);
- out_be32(maccfg2_register, value);
+ clrsetbits_be32(maccfg2_register, MACCFG2_PREL_MASK,
+ preamble_length << MACCFG2_PREL_SHIFT);
+
return 0;
}
@@ -1337,19 +1314,19 @@ static int init_rx_parameters(int reject_broadcast,
value = in_be32(upsmr_register);
if (reject_broadcast)
- value |= UPSMR_BRO;
+ value |= UCC_GETH_UPSMR_BRO;
else
- value &= ~UPSMR_BRO;
+ value &= ~UCC_GETH_UPSMR_BRO;
if (receive_short_frames)
- value |= UPSMR_RSH;
+ value |= UCC_GETH_UPSMR_RSH;
else
- value &= ~UPSMR_RSH;
+ value &= ~UCC_GETH_UPSMR_RSH;
if (promiscuous)
- value |= UPSMR_PRO;
+ value |= UCC_GETH_UPSMR_PRO;
else
- value &= ~UPSMR_PRO;
+ value &= ~UCC_GETH_UPSMR_PRO;
out_be32(upsmr_register, value);
@@ -1410,26 +1387,27 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth)
/* Set UPSMR */
upsmr = in_be32(&uf_regs->upsmr);
- upsmr &= ~(UPSMR_RPM | UPSMR_R10M | UPSMR_TBIM | UPSMR_RMM);
+ upsmr &= ~(UCC_GETH_UPSMR_RPM | UCC_GETH_UPSMR_R10M |
+ UCC_GETH_UPSMR_TBIM | UCC_GETH_UPSMR_RMM);
if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
- upsmr |= UPSMR_RPM;
+ upsmr |= UCC_GETH_UPSMR_RPM;
switch (ugeth->max_speed) {
case SPEED_10:
- upsmr |= UPSMR_R10M;
+ upsmr |= UCC_GETH_UPSMR_R10M;
/* FALLTHROUGH */
case SPEED_100:
if (ugeth->phy_interface != PHY_INTERFACE_MODE_RTBI)
- upsmr |= UPSMR_RMM;
+ upsmr |= UCC_GETH_UPSMR_RMM;
}
}
if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
- upsmr |= UPSMR_TBIM;
+ upsmr |= UCC_GETH_UPSMR_TBIM;
}
out_be32(&uf_regs->upsmr, upsmr);
@@ -1517,9 +1495,9 @@ static void adjust_link(struct net_device *dev)
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
if (phydev->speed == SPEED_10)
- upsmr |= UPSMR_R10M;
+ upsmr |= UCC_GETH_UPSMR_R10M;
else
- upsmr &= ~(UPSMR_R10M);
+ upsmr &= ~UCC_GETH_UPSMR_R10M;
}
break;
default:
@@ -1602,10 +1580,8 @@ static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth)
uccf = ugeth->uccf;
/* Mask GRACEFUL STOP TX interrupt bit and clear it */
- temp = in_be32(uccf->p_uccm);
- temp &= ~UCCE_GRA;
- out_be32(uccf->p_uccm, temp);
- out_be32(uccf->p_ucce, UCCE_GRA); /* clear by writing 1 */
+ clrbits32(uccf->p_uccm, UCC_GETH_UCCE_GRA);
+ out_be32(uccf->p_ucce, UCC_GETH_UCCE_GRA); /* clear by writing 1 */
/* Issue host command */
cecr_subblock =
@@ -1617,7 +1593,7 @@ static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth)
do {
msleep(10);
temp = in_be32(uccf->p_ucce);
- } while (!(temp & UCCE_GRA) && --i);
+ } while (!(temp & UCC_GETH_UCCE_GRA) && --i);
uccf->stopped_tx = 1;
@@ -1975,12 +1951,9 @@ static void ucc_geth_set_multi(struct net_device *dev)
uf_regs = ugeth->uccf->uf_regs;
if (dev->flags & IFF_PROMISC) {
-
- out_be32(&uf_regs->upsmr, in_be32(&uf_regs->upsmr) | UPSMR_PRO);
-
+ setbits32(&uf_regs->upsmr, UCC_GETH_UPSMR_PRO);
} else {
-
- out_be32(&uf_regs->upsmr, in_be32(&uf_regs->upsmr)&~UPSMR_PRO);
+ clrbits32(&uf_regs->upsmr, UCC_GETH_UPSMR_PRO);
p_82xx_addr_filt =
(struct ucc_geth_82xx_address_filtering_pram __iomem *) ugeth->
@@ -2020,7 +1993,6 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth)
{
struct ucc_geth __iomem *ug_regs = ugeth->ug_regs;
struct phy_device *phydev = ugeth->phydev;
- u32 tempval;
ugeth_vdbg("%s: IN", __func__);
@@ -2037,9 +2009,7 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth)
out_be32(ugeth->uccf->p_ucce, 0xffffffff);
/* Disable Rx and Tx */
- tempval = in_be32(&ug_regs->maccfg1);
- tempval &= ~(MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX);
- out_be32(&ug_regs->maccfg1, tempval);
+ clrbits32(&ug_regs->maccfg1, MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX);
ucc_geth_memclean(ugeth);
}
@@ -2153,10 +2123,10 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
/* Generate uccm_mask for receive */
uf_info->uccm_mask = ug_info->eventRegMask & UCCE_OTHER;/* Errors */
for (i = 0; i < ug_info->numQueuesRx; i++)
- uf_info->uccm_mask |= (UCCE_RXBF_SINGLE_MASK << i);
+ uf_info->uccm_mask |= (UCC_GETH_UCCE_RXF0 << i);
for (i = 0; i < ug_info->numQueuesTx; i++)
- uf_info->uccm_mask |= (UCCE_TXBF_SINGLE_MASK << i);
+ uf_info->uccm_mask |= (UCC_GETH_UCCE_TXB0 << i);
/* Initialize the general fast UCC block. */
if (ucc_fast_init(uf_info, &ugeth->uccf)) {
if (netif_msg_probe(ugeth))
@@ -2185,7 +2155,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
struct ucc_geth __iomem *ug_regs;
int ret_val = -EINVAL;
u32 remoder = UCC_GETH_REMODER_INIT;
- u32 init_enet_pram_offset, cecr_subblock, command, maccfg1;
+ u32 init_enet_pram_offset, cecr_subblock, command;
u32 ifstat, i, j, size, l2qt, l3qt, length;
u16 temoder = UCC_GETH_TEMODER_INIT;
u16 test;
@@ -2281,10 +2251,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
&uf_regs->upsmr,
&ug_regs->uempr, &ug_regs->maccfg1);
- maccfg1 = in_be32(&ug_regs->maccfg1);
- maccfg1 |= MACCFG1_ENABLE_RX;
- maccfg1 |= MACCFG1_ENABLE_TX;
- out_be32(&ug_regs->maccfg1, maccfg1);
+ setbits32(&ug_regs->maccfg1, MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX);
/* Set IPGIFG */
/* For more details see the hardware spec. */
@@ -3274,7 +3241,6 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ)
static int ucc_geth_poll(struct napi_struct *napi, int budget)
{
struct ucc_geth_private *ugeth = container_of(napi, struct ucc_geth_private, napi);
- struct net_device *dev = ugeth->dev;
struct ucc_geth_info *ug_info;
int howmany, i;
@@ -3285,14 +3251,8 @@ static int ucc_geth_poll(struct napi_struct *napi, int budget)
howmany += ucc_geth_rx(ugeth, i, budget - howmany);
if (howmany < budget) {
- struct ucc_fast_private *uccf;
- u32 uccm;
-
netif_rx_complete(napi);
- uccf = ugeth->uccf;
- uccm = in_be32(uccf->p_uccm);
- uccm |= UCCE_RX_EVENTS;
- out_be32(uccf->p_uccm, uccm);
+ setbits32(ugeth->uccf->p_uccm, UCCE_RX_EVENTS);
}
return howmany;
@@ -3332,7 +3292,7 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info)
/* Tx event processing */
if (ucce & UCCE_TX_EVENTS) {
spin_lock(&ugeth->lock);
- tx_mask = UCCE_TXBF_SINGLE_MASK;
+ tx_mask = UCC_GETH_UCCE_TXB0;
for (i = 0; i < ug_info->numQueuesTx; i++) {
if (ucce & tx_mask)
ucc_geth_tx(dev, i);
@@ -3344,12 +3304,10 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info)
/* Errors and other events */
if (ucce & UCCE_OTHER) {
- if (ucce & UCCE_BSY) {
+ if (ucce & UCC_GETH_UCCE_BSY)
dev->stats.rx_errors++;
- }
- if (ucce & UCCE_TXE) {
+ if (ucce & UCC_GETH_UCCE_TXE)
dev->stats.tx_errors++;
- }
}
return IRQ_HANDLED;
diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h
index d74d2f7..8f699cb 100644
--- a/drivers/net/ucc_geth.h
+++ b/drivers/net/ucc_geth.h
@@ -162,92 +162,27 @@ struct ucc_geth {
boundary */
/* UCC GETH Event Register */
-#define UCCE_MPD 0x80000000 /* Magic packet
- detection */
-#define UCCE_SCAR 0x40000000
-#define UCCE_GRA 0x20000000 /* Tx graceful
- stop
- complete */
-#define UCCE_CBPR 0x10000000
-#define UCCE_BSY 0x08000000
-#define UCCE_RXC 0x04000000
-#define UCCE_TXC 0x02000000
-#define UCCE_TXE 0x01000000
-#define UCCE_TXB7 0x00800000
-#define UCCE_TXB6 0x00400000
-#define UCCE_TXB5 0x00200000
-#define UCCE_TXB4 0x00100000
-#define UCCE_TXB3 0x00080000
-#define UCCE_TXB2 0x00040000
-#define UCCE_TXB1 0x00020000
-#define UCCE_TXB0 0x00010000
-#define UCCE_RXB7 0x00008000
-#define UCCE_RXB6 0x00004000
-#define UCCE_RXB5 0x00002000
-#define UCCE_RXB4 0x00001000
-#define UCCE_RXB3 0x00000800
-#define UCCE_RXB2 0x00000400
-#define UCCE_RXB1 0x00000200
-#define UCCE_RXB0 0x00000100
-#define UCCE_RXF7 0x00000080
-#define UCCE_RXF6 0x00000040
-#define UCCE_RXF5 0x00000020
-#define UCCE_RXF4 0x00000010
-#define UCCE_RXF3 0x00000008
-#define UCCE_RXF2 0x00000004
-#define UCCE_RXF1 0x00000002
-#define UCCE_RXF0 0x00000001
-
-#define UCCE_RXBF_SINGLE_MASK (UCCE_RXF0)
-#define UCCE_TXBF_SINGLE_MASK (UCCE_TXB0)
-
-#define UCCE_TXB (UCCE_TXB7 | UCCE_TXB6 | UCCE_TXB5 | UCCE_TXB4 |\
- UCCE_TXB3 | UCCE_TXB2 | UCCE_TXB1 | UCCE_TXB0)
-#define UCCE_RXB (UCCE_RXB7 | UCCE_RXB6 | UCCE_RXB5 | UCCE_RXB4 |\
- UCCE_RXB3 | UCCE_RXB2 | UCCE_RXB1 | UCCE_RXB0)
-#define UCCE_RXF (UCCE_RXF7 | UCCE_RXF6 | UCCE_RXF5 | UCCE_RXF4 |\
- UCCE_RXF3 | UCCE_RXF2 | UCCE_RXF1 | UCCE_RXF0)
-#define UCCE_OTHER (UCCE_SCAR | UCCE_GRA | UCCE_CBPR | UCCE_BSY |\
- UCCE_RXC | UCCE_TXC | UCCE_TXE)
-
-#define UCCE_RX_EVENTS (UCCE_RXF | UCCE_BSY)
-#define UCCE_TX_EVENTS (UCCE_TXB | UCCE_TXE)
-
-/* UCC GETH UPSMR (Protocol Specific Mode Register) */
-#define UPSMR_ECM 0x04000000 /* Enable CAM
- Miss or
- Enable
- Filtering
- Miss */
-#define UPSMR_HSE 0x02000000 /* Hardware
- Statistics
- Enable */
-#define UPSMR_PRO 0x00400000 /* Promiscuous*/
-#define UPSMR_CAP 0x00200000 /* CAM polarity
- */
-#define UPSMR_RSH 0x00100000 /* Receive
- Short Frames
- */
-#define UPSMR_RPM 0x00080000 /* Reduced Pin
- Mode
- interfaces */
-#define UPSMR_R10M 0x00040000 /* RGMII/RMII
- 10 Mode */
-#define UPSMR_RLPB 0x00020000 /* RMII
- Loopback
- Mode */
-#define UPSMR_TBIM 0x00010000 /* Ten-bit
- Interface
- Mode */
-#define UPSMR_RMM 0x00001000 /* RMII/RGMII
- Mode */
-#define UPSMR_CAM 0x00000400 /* CAM Address
- Matching */
-#define UPSMR_BRO 0x00000200 /* Broadcast
- Address */
-#define UPSMR_RES1 0x00002000 /* Reserved
- feild - must
- be 1 */
+#define UCCE_TXB (UCC_GETH_UCCE_TXB7 | UCC_GETH_UCCE_TXB6 | \
+ UCC_GETH_UCCE_TXB5 | UCC_GETH_UCCE_TXB4 | \
+ UCC_GETH_UCCE_TXB3 | UCC_GETH_UCCE_TXB2 | \
+ UCC_GETH_UCCE_TXB1 | UCC_GETH_UCCE_TXB0)
+
+#define UCCE_RXB (UCC_GETH_UCCE_RXB7 | UCC_GETH_UCCE_RXB6 | \
+ UCC_GETH_UCCE_RXB5 | UCC_GETH_UCCE_RXB4 | \
+ UCC_GETH_UCCE_RXB3 | UCC_GETH_UCCE_RXB2 | \
+ UCC_GETH_UCCE_RXB1 | UCC_GETH_UCCE_RXB0)
+
+#define UCCE_RXF (UCC_GETH_UCCE_RXF7 | UCC_GETH_UCCE_RXF6 | \
+ UCC_GETH_UCCE_RXF5 | UCC_GETH_UCCE_RXF4 | \
+ UCC_GETH_UCCE_RXF3 | UCC_GETH_UCCE_RXF2 | \
+ UCC_GETH_UCCE_RXF1 | UCC_GETH_UCCE_RXF0)
+
+#define UCCE_OTHER (UCC_GETH_UCCE_SCAR | UCC_GETH_UCCE_GRA | \
+ UCC_GETH_UCCE_CBPR | UCC_GETH_UCCE_BSY | \
+ UCC_GETH_UCCE_RXC | UCC_GETH_UCCE_TXC | UCC_GETH_UCCE_TXE)
+
+#define UCCE_RX_EVENTS (UCCE_RXF | UCC_GETH_UCCE_BSY)
+#define UCCE_TX_EVENTS (UCCE_TXB | UCC_GETH_UCCE_TXE)
/* UCC GETH MACCFG1 (MAC Configuration 1 Register) */
#define MACCFG1_FLOW_RX 0x00000020 /* Flow Control
@@ -945,9 +880,10 @@ struct ucc_geth_hardware_statistics {
#define UCC_GETH_REMODER_INIT 0 /* bits that must be
set */
#define UCC_GETH_TEMODER_INIT 0xC000 /* bits that must */
-#define UCC_GETH_UPSMR_INIT (UPSMR_RES1) /* Start value
- for this
- register */
+
+/* Initial value for UPSMR */
+#define UCC_GETH_UPSMR_INIT UCC_GETH_UPSMR_RES1
+
#define UCC_GETH_MACCFG1_INIT 0
#define UCC_GETH_MACCFG2_INIT (MACCFG2_RESERVED_1)
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index c4918b8..0d0fa91 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -1297,6 +1297,7 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp)
/* setup */
spin_lock_irq(&serial->serial_lock);
tty->driver_data = serial;
+ tty_kref_put(serial->tty);
serial->tty = tty_kref_get(tty);
spin_unlock_irq(&serial->serial_lock);
@@ -1792,8 +1793,8 @@ static int mux_device_request(struct hso_serial *serial, u8 type, u16 port,
/* initialize */
ctrl_req->wValue = 0;
- ctrl_req->wIndex = hso_port_to_mux(port);
- ctrl_req->wLength = size;
+ ctrl_req->wIndex = cpu_to_le16(hso_port_to_mux(port));
+ ctrl_req->wLength = cpu_to_le16(size);
if (type == USB_CDC_GET_ENCAPSULATED_RESPONSE) {
/* Reading command */
@@ -2043,9 +2044,8 @@ static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial)
return -2;
}
- spin_lock(&serial->serial_lock);
+ /* All callers to put_rxbuf_data hold serial_lock */
tty = tty_kref_get(serial->tty);
- spin_unlock(&serial->serial_lock);
/* Push data to tty */
if (tty) {
@@ -2053,8 +2053,10 @@ static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial)
serial->curr_rx_urb_offset;
D1("data to push to tty");
while (write_length_remaining) {
- if (test_bit(TTY_THROTTLED, &tty->flags))
+ if (test_bit(TTY_THROTTLED, &tty->flags)) {
+ tty_kref_put(tty);
return -1;
+ }
curr_write_len = tty_insert_flip_string
(tty, urb->transfer_buffer +
serial->curr_rx_urb_offset,
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index ac07cc6..3b8e632 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -622,6 +622,7 @@ static const struct net_device_ops rhine_netdev_ops = {
.ndo_get_stats = rhine_get_stats,
.ndo_set_multicast_list = rhine_set_rx_mode,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_do_ioctl = netdev_ioctl,
.ndo_tx_timeout = rhine_tx_timeout,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 58e25d0..a75f91d 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -855,6 +855,7 @@ static const struct net_device_ops velocity_netdev_ops = {
.ndo_start_xmit = velocity_xmit,
.ndo_get_stats = velocity_get_stats,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_set_multicast_list = velocity_set_multi,
.ndo_change_mtu = velocity_change_mtu,
.ndo_do_ioctl = velocity_ioctl,
diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index 2dc2416..0dbd85b 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -622,7 +622,7 @@ static void hss_hdlc_rx_irq(void *pdev)
printk(KERN_DEBUG "%s: hss_hdlc_rx_irq\n", dev->name);
#endif
qmgr_disable_irq(queue_ids[port->id].rx);
- netif_rx_schedule(dev, &port->napi);
+ netif_rx_schedule(&port->napi);
}
static int hss_hdlc_poll(struct napi_struct *napi, int budget)
@@ -651,7 +651,7 @@ static int hss_hdlc_poll(struct napi_struct *napi, int budget)
printk(KERN_DEBUG "%s: hss_hdlc_poll"
" netif_rx_complete\n", dev->name);
#endif
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
qmgr_enable_irq(rxq);
if (!qmgr_stat_empty(rxq) &&
netif_rx_reschedule(napi)) {
@@ -1069,7 +1069,7 @@ static int hss_hdlc_open(struct net_device *dev)
hss_start_hdlc(port);
/* we may already have RX data, enables IRQ */
- netif_rx_schedule(dev, &port->napi);
+ netif_rx_schedule(&port->napi);
return 0;
err_unlock:
diff --git a/drivers/net/wd.c b/drivers/net/wd.c
index 3c1edda..d8322d2 100644
--- a/drivers/net/wd.c
+++ b/drivers/net/wd.c
@@ -155,6 +155,7 @@ static const struct net_device_ops wd_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index ea543fc..e4f9f74 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -111,7 +111,7 @@ config WLAN_80211
lets you choose drivers.
config PCMCIA_RAYCS
- tristate "Aviator/Raytheon 2.4MHz wireless support"
+ tristate "Aviator/Raytheon 2.4GHz wireless support"
depends on PCMCIA && WLAN_80211
select WIRELESS_EXT
---help---
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index 4af2607..8ef8735 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -2644,7 +2644,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
if (skb_headroom(skb) < padsize) {
ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough"
" headroom to pad %d\n", hdrlen, padsize);
- return -1;
+ return NETDEV_TX_BUSY;
}
skb_push(skb, padsize);
memmove(skb->data, skb->data+padsize, hdrlen);
@@ -2655,7 +2655,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
ATH5K_ERR(sc, "no further txbuf available, dropping packet\n");
spin_unlock_irqrestore(&sc->txbuflock, flags);
ieee80211_stop_queue(hw, skb_get_queue_mapping(skb));
- return -1;
+ return NETDEV_TX_BUSY;
}
bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list);
list_del(&bf->list);
@@ -2673,10 +2673,10 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
sc->txbuf_len++;
spin_unlock_irqrestore(&sc->txbuflock, flags);
dev_kfree_skb_any(skb);
- return 0;
+ return NETDEV_TX_OK;
}
- return 0;
+ return NETDEV_TX_OK;
}
static int
diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath5k/pcu.c
index 0cac05c..75eb9f4 100644
--- a/drivers/net/wireless/ath5k/pcu.c
+++ b/drivers/net/wireless/ath5k/pcu.c
@@ -65,7 +65,7 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah)
if (ah->ah_version == AR5K_AR5210)
pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
else
- AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_ADHOC);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
break;
case NL80211_IFTYPE_AP:
@@ -75,7 +75,7 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah)
if (ah->ah_version == AR5K_AR5210)
pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
else
- AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_ADHOC);
+ AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
break;
case NL80211_IFTYPE_STATION:
diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h
index 91aaeaf..9189ab1 100644
--- a/drivers/net/wireless/ath5k/reg.h
+++ b/drivers/net/wireless/ath5k/reg.h
@@ -73,7 +73,7 @@
#define AR5K_CFG_SWRD 0x00000004 /* Byte-swap RX descriptor */
#define AR5K_CFG_SWRB 0x00000008 /* Byte-swap RX buffer */
#define AR5K_CFG_SWRG 0x00000010 /* Byte-swap Register access */
-#define AR5K_CFG_ADHOC 0x00000020 /* AP/Adhoc indication [5211+] */
+#define AR5K_CFG_IBSS 0x00000020 /* 0-BSS, 1-IBSS [5211+] */
#define AR5K_CFG_PHY_OK 0x00000100 /* [5211+] */
#define AR5K_CFG_EEBS 0x00000200 /* EEPROM is busy */
#define AR5K_CFG_CLKGD 0x00000400 /* Clock gated (Disable dynamic clock) */
diff --git a/drivers/net/wireless/ath9k/Kconfig b/drivers/net/wireless/ath9k/Kconfig
index c43bd32..90a8dd8 100644
--- a/drivers/net/wireless/ath9k/Kconfig
+++ b/drivers/net/wireless/ath9k/Kconfig
@@ -1,6 +1,7 @@
config ATH9K
tristate "Atheros 802.11n wireless cards support"
depends on PCI && MAC80211 && WLAN_80211
+ depends on RFKILL || RFKILL=n
select MAC80211_LEDS
select LEDS_CLASS
select NEW_LEDS
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c
index 191eec5..727f067 100644
--- a/drivers/net/wireless/ath9k/main.c
+++ b/drivers/net/wireless/ath9k/main.c
@@ -2164,13 +2164,13 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
conf->ht.channel_type);
}
+ ath_update_chainmask(sc, conf->ht.enabled);
+
if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) {
DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n");
mutex_unlock(&sc->mutex);
return -EINVAL;
}
-
- ath_update_chainmask(sc, conf->ht.enabled);
}
if (changed & IEEE80211_CONF_CHANGE_POWER)
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c
index 3bfc3b9..c92f0c6 100644
--- a/drivers/net/wireless/ath9k/xmit.c
+++ b/drivers/net/wireless/ath9k/xmit.c
@@ -126,15 +126,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
tx_info->flags |= IEEE80211_TX_STAT_ACK;
}
- tx_info->status.rates[0].count = tx_status->retries;
- if (tx_info->status.rates[0].flags & IEEE80211_TX_RC_MCS) {
- /* Change idx from internal table index to MCS index */
- int idx = tx_info->status.rates[0].idx;
- struct ath_rate_table *rate_table = sc->cur_rate_table;
- if (idx >= 0 && idx < rate_table->rate_cnt)
- tx_info->status.rates[0].idx =
- rate_table->info[idx].ratecode & 0x7f;
- }
+ tx_info->status.rates[0].count = tx_status->retries + 1;
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
padsize = hdrlen & 3;
@@ -264,25 +256,22 @@ static void assign_aggr_tid_seqno(struct sk_buff *skb,
}
/* Get seqno */
-
- if (ieee80211_is_data(fc) && !is_pae(skb)) {
- /* For HT capable stations, we save tidno for later use.
- * We also override seqno set by upper layer with the one
- * in tx aggregation state.
- *
- * If fragmentation is on, the sequence number is
- * not overridden, since it has been
- * incremented by the fragmentation routine.
- *
- * FIXME: check if the fragmentation threshold exceeds
- * IEEE80211 max.
- */
- tid = ATH_AN_2_TID(an, bf->bf_tidno);
- hdr->seq_ctrl = cpu_to_le16(tid->seq_next <<
- IEEE80211_SEQ_SEQ_SHIFT);
- bf->bf_seqno = tid->seq_next;
- INCR(tid->seq_next, IEEE80211_SEQ_MAX);
- }
+ /* For HT capable stations, we save tidno for later use.
+ * We also override seqno set by upper layer with the one
+ * in tx aggregation state.
+ *
+ * If fragmentation is on, the sequence number is
+ * not overridden, since it has been
+ * incremented by the fragmentation routine.
+ *
+ * FIXME: check if the fragmentation threshold exceeds
+ * IEEE80211 max.
+ */
+ tid = ATH_AN_2_TID(an, bf->bf_tidno);
+ hdr->seq_ctrl = cpu_to_le16(tid->seq_next <<
+ IEEE80211_SEQ_SEQ_SHIFT);
+ bf->bf_seqno = tid->seq_next;
+ INCR(tid->seq_next, IEEE80211_SEQ_MAX);
}
static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb,
@@ -1718,11 +1707,10 @@ static int ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf,
/* Assign seqno, tidno */
- if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR))
+ if (ieee80211_is_data_qos(fc) && (sc->sc_flags & SC_OP_TXAGGR))
assign_aggr_tid_seqno(skb, bf);
/* DMA setup */
-
bf->bf_mpdu = skb;
bf->bf_dmacontext = pci_map_single(sc->pdev, skb->data,
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 7b31a32..c788bad 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -3261,7 +3261,7 @@ static int b43_switch_band(struct b43_wl *wl, struct ieee80211_channel *chan)
struct b43_wldev *down_dev;
struct b43_wldev *d;
int err;
- bool gmode;
+ bool uninitialized_var(gmode);
int prev_status;
/* Find a device and PHY which supports the band. */
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index c1324e3..fb996c2 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -2465,7 +2465,7 @@ static void b43legacy_put_phy_into_reset(struct b43legacy_wldev *dev)
static int b43legacy_switch_phymode(struct b43legacy_wl *wl,
unsigned int new_mode)
{
- struct b43legacy_wldev *up_dev;
+ struct b43legacy_wldev *uninitialized_var(up_dev);
struct b43legacy_wldev *down_dev;
int err;
bool gmode = 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 8fdb342..45cfa1cf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -2219,7 +2219,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl3945_priv *priv)
/* set tx power value for all OFDM rates */
for (rate_index = 0; rate_index < IWL_OFDM_RATES;
rate_index++) {
- s32 power_idx;
+ s32 uninitialized_var(power_idx);
int rc;
/* use channel group's clip-power table,
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 52966ff..ba99720 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -255,7 +255,7 @@ struct iwl_cmd_header {
* 0x3) 54 Mbps
*
* Legacy CCK rate format for bits 7:0 (bit 8 must be "0", bit 9 "1"):
- * 3-0: 10) 1 Mbps
+ * 6-0: 10) 1 Mbps
* 20) 2 Mbps
* 55) 5.5 Mbps
* 110) 11 Mbps
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 01a2169..8c71ad4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -51,6 +51,7 @@ const char *get_cmd_string(u8 cmd)
IWL_CMD(REPLY_REMOVE_STA);
IWL_CMD(REPLY_REMOVE_ALL_STA);
IWL_CMD(REPLY_WEPKEY);
+ IWL_CMD(REPLY_3945_RX);
IWL_CMD(REPLY_TX);
IWL_CMD(REPLY_RATE_SCALE);
IWL_CMD(REPLY_LEDS_CMD);
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 3dba836..4e0007d 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -1369,7 +1369,7 @@ EXPORT_SYMBOL_GPL(lbs_start_card);
void lbs_stop_card(struct lbs_private *priv)
{
- struct net_device *dev = priv->dev;
+ struct net_device *dev;
struct cmd_ctrl_node *cmdnode;
unsigned long flags;
@@ -1377,9 +1377,10 @@ void lbs_stop_card(struct lbs_private *priv)
if (!priv)
goto out;
+ dev = priv->dev;
- netif_stop_queue(priv->dev);
- netif_carrier_off(priv->dev);
+ netif_stop_queue(dev);
+ netif_carrier_off(dev);
lbs_debugfs_remove_one(priv);
if (priv->mesh_tlv) {
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
index d1fc305..e7289e2 100644
--- a/drivers/net/wireless/libertas_tf/main.c
+++ b/drivers/net/wireless/libertas_tf/main.c
@@ -206,7 +206,7 @@ static int lbtf_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
* there are no buffered multicast frames to send
*/
ieee80211_stop_queues(priv->hw);
- return 0;
+ return NETDEV_TX_OK;
}
static void lbtf_tx_work(struct work_struct *work)
diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c
index bc84e27..c3bb85e 100644
--- a/drivers/net/wireless/orinoco/orinoco.c
+++ b/drivers/net/wireless/orinoco/orinoco.c
@@ -1610,6 +1610,16 @@ static void orinoco_rx_isr_tasklet(unsigned long data)
struct orinoco_rx_data *rx_data, *temp;
struct hermes_rx_descriptor *desc;
struct sk_buff *skb;
+ unsigned long flags;
+
+ /* orinoco_rx requires the driver lock, and we also need to
+ * protect priv->rx_list, so just hold the lock over the
+ * lot.
+ *
+ * If orinoco_lock fails, we've unplugged the card. In this
+ * case just abort. */
+ if (orinoco_lock(priv, &flags) != 0)
+ return;
/* extract desc and skb from queue */
list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) {
@@ -1622,6 +1632,8 @@ static void orinoco_rx_isr_tasklet(unsigned long data)
kfree(desc);
}
+
+ orinoco_unlock(priv, &flags);
}
/********************************************************************/
@@ -3645,12 +3657,22 @@ struct net_device
void free_orinocodev(struct net_device *dev)
{
struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_rx_data *rx_data, *temp;
- /* No need to empty priv->rx_list: if the tasklet is scheduled
- * when we call tasklet_kill it will run one final time,
- * emptying the list */
+ /* If the tasklet is scheduled when we call tasklet_kill it
+ * will run one final time. However the tasklet will only
+ * drain priv->rx_list if the hw is still available. */
tasklet_kill(&priv->rx_tasklet);
+ /* Explicitly drain priv->rx_list */
+ list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) {
+ list_del(&rx_data->list);
+
+ dev_kfree_skb(rx_data->skb);
+ kfree(rx_data->desc);
+ kfree(rx_data);
+ }
+
unregister_pm_notifier(&priv->pm_notifier);
orinoco_uncache_fw(priv);
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c
index f127602..0b32215 100644
--- a/drivers/net/wireless/orinoco/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco/orinoco_cs.c
@@ -435,6 +435,7 @@ static struct pcmcia_device_id orinoco_cs_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */
PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */
PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), /* ARtem Onair */
+ PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0003), /* ARtem Onair Comcard 11 */
PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), /* Buffalo WLI-PCM-S11 */
PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */
PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c
index 82354b9..c6a370f 100644
--- a/drivers/net/wireless/p54/p54common.c
+++ b/drivers/net/wireless/p54/p54common.c
@@ -138,6 +138,7 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
u8 *fw_version = NULL;
size_t len;
int i;
+ int maxlen;
if (priv->rx_start)
return 0;
@@ -195,6 +196,16 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
else
priv->rx_mtu = (size_t)
0x620 - priv->tx_hdr_len;
+ maxlen = priv->tx_hdr_len + /* USB devices */
+ sizeof(struct p54_rx_data) +
+ 4 + /* rx alignment */
+ IEEE80211_MAX_FRAG_THRESHOLD;
+ if (priv->rx_mtu > maxlen && PAGE_SIZE == 4096) {
+ printk(KERN_INFO "p54: rx_mtu reduced from %d "
+ "to %d\n", priv->rx_mtu,
+ maxlen);
+ priv->rx_mtu = maxlen;
+ }
break;
}
case BR_CODE_EXPOSED_IF:
@@ -575,6 +586,7 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
u16 freq = le16_to_cpu(hdr->freq);
size_t header_len = sizeof(*hdr);
u32 tsf32;
+ u8 rate = hdr->rate & 0xf;
/*
* If the device is in a unspecified state we have to
@@ -603,8 +615,11 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
rx_status.qual = (100 * hdr->rssi) / 127;
if (hdr->rate & 0x10)
rx_status.flag |= RX_FLAG_SHORTPRE;
- rx_status.rate_idx = (dev->conf.channel->band == IEEE80211_BAND_2GHZ ?
- hdr->rate : (hdr->rate - 4)) & 0xf;
+ if (dev->conf.channel->band == IEEE80211_BAND_5GHZ)
+ rx_status.rate_idx = (rate < 4) ? 0 : rate - 4;
+ else
+ rx_status.rate_idx = rate;
+
rx_status.freq = freq;
rx_status.band = dev->conf.channel->band;
rx_status.antenna = hdr->antenna;
@@ -798,6 +813,16 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
info->status.ack_signal = p54_rssi_to_dbm(dev,
(int)payload->ack_rssi);
+
+ if (entry_data->key_type == P54_CRYPTO_TKIPMICHAEL) {
+ u8 *iv = (u8 *)(entry_data->align + pad +
+ entry_data->crypt_offset);
+
+ /* Restore the original TKIP IV. */
+ iv[2] = iv[0];
+ iv[0] = iv[1];
+ iv[1] = (iv[0] | 0x20) & 0x7f; /* WEPSeed - 8.3.2.2 */
+ }
skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
ieee80211_tx_status_irqsafe(dev, entry);
goto out;
@@ -1383,7 +1408,6 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
hdr->tries = ridx;
txhdr->rts_rate_idx = 0;
if (info->control.hw_key) {
- crypt_offset += info->control.hw_key->iv_len;
txhdr->key_type = p54_convert_algo(info->control.hw_key->alg);
txhdr->key_len = min((u8)16, info->control.hw_key->keylen);
memcpy(txhdr->key, info->control.hw_key->key, txhdr->key_len);
@@ -1397,6 +1421,8 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
}
/* reserve some space for ICV */
len += info->control.hw_key->icv_len;
+ memset(skb_put(skb, info->control.hw_key->icv_len), 0,
+ info->control.hw_key->icv_len);
} else {
txhdr->key_type = 0;
txhdr->key_len = 0;
@@ -1824,7 +1850,7 @@ static void p54_remove_interface(struct ieee80211_hw *dev,
static int p54_config(struct ieee80211_hw *dev, u32 changed)
{
- int ret;
+ int ret = 0;
struct p54_common *priv = dev->priv;
struct ieee80211_conf *conf = &dev->conf;
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index c44a200..6a6a72f 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -56,6 +56,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
{USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */
{USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */
{USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */
+ {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */
{USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */
{USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */
{USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */
@@ -284,6 +285,7 @@ static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb)
usb_fill_bulk_urb(data_urb, priv->udev,
usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
skb->data, skb->len, p54u_tx_cb, skb);
+ data_urb->transfer_flags |= URB_ZERO_PACKET;
usb_anchor_urb(data_urb, &priv->submitted);
if (usb_submit_urb(data_urb, GFP_ATOMIC)) {
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 30028e2..af6b584 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -38,7 +38,7 @@
/*
* Allow hardware encryption to be disabled.
*/
-static int modparam_nohwcrypt = 1;
+static int modparam_nohwcrypt = 0;
module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
@@ -376,11 +376,11 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
/*
* The driver does not support the IV/EIV generation
- * in hardware. However it doesn't support the IV/EIV
- * inside the ieee80211 frame either, but requires it
- * to be provided seperately for the descriptor.
- * rt2x00lib will cut the IV/EIV data out of all frames
- * given to us by mac80211, but we must tell mac80211
+ * in hardware. However it demands the data to be provided
+ * both seperately as well as inside the frame.
+ * We already provided the CONFIG_CRYPTO_COPY_IV to rt2x00lib
+ * to ensure rt2x00lib will not strip the data from the
+ * frame after the copy, now we must tell mac80211
* to generate the IV/EIV data.
*/
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
@@ -1181,7 +1181,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len);
- rt2x00_set_field32(&word, TXD_W0_CIPHER, txdesc->cipher);
+ rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher);
rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx);
rt2x00_desc_write(txd, 0, word);
}
@@ -1334,14 +1334,7 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry,
/* ICV is located at the end of frame */
- /*
- * Hardware has stripped IV/EIV data from 802.11 frame during
- * decryption. It has provided the data seperately but rt2x00lib
- * should decide if it should be reinserted.
- */
- rxdesc->flags |= RX_FLAG_IV_STRIPPED;
- if (rxdesc->cipher != CIPHER_TKIP)
- rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
+ rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
rxdesc->flags |= RX_FLAG_DECRYPTED;
else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 6d92542..87c0f2c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -807,13 +807,11 @@ static void rt2x00lib_rate(struct ieee80211_rate *entry,
{
entry->flags = 0;
entry->bitrate = rate->bitrate;
- entry->hw_value = rt2x00_create_rate_hw_value(index, 0);
- entry->hw_value_short = entry->hw_value;
+ entry->hw_value =index;
+ entry->hw_value_short = index;
- if (rate->flags & DEV_RATE_SHORT_PREAMBLE) {
+ if (rate->flags & DEV_RATE_SHORT_PREAMBLE)
entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE;
- entry->hw_value_short |= rt2x00_create_rate_hw_value(index, 1);
- }
}
static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c
index 68f4e0f..a0cd35b 100644
--- a/drivers/net/wireless/rt2x00/rt2x00leds.c
+++ b/drivers/net/wireless/rt2x00/rt2x00leds.c
@@ -97,7 +97,7 @@ void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled)
void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled)
{
- if (rt2x00dev->led_radio.type == LED_TYPE_ASSOC)
+ if (rt2x00dev->led_radio.type == LED_TYPE_RADIO)
rt2x00led_led_simple(&rt2x00dev->led_radio, enabled);
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 0302432..86cd26f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -52,22 +52,11 @@ struct rt2x00_rate {
extern const struct rt2x00_rate rt2x00_supported_rates[12];
-static inline u16 rt2x00_create_rate_hw_value(const u16 index,
- const u16 short_preamble)
-{
- return (short_preamble << 8) | (index & 0xff);
-}
-
static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value)
{
return &rt2x00_supported_rates[hw_value & 0xff];
}
-static inline int rt2x00_get_rate_preamble(const u16 hw_value)
-{
- return (hw_value & 0xff00);
-}
-
/*
* Radio control handlers.
*/
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index eaec6bd..746a8f3 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -313,7 +313,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
* When preamble is enabled we should set the
* preamble bit for the signal.
*/
- if (rt2x00_get_rate_preamble(rate->hw_value))
+ if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
txdesc->signal |= 0x08;
}
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 83df312..0b29d76 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -434,11 +434,11 @@ static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev)
if (usb_endpoint_is_bulk_in(ep_desc)) {
rt2x00usb_assign_endpoint(rt2x00dev->rx, ep_desc);
- } else if (usb_endpoint_is_bulk_out(ep_desc)) {
+ } else if (usb_endpoint_is_bulk_out(ep_desc) &&
+ (queue != queue_end(rt2x00dev))) {
rt2x00usb_assign_endpoint(queue, ep_desc);
+ queue = queue_next(queue);
- if (queue != queue_end(rt2x00dev))
- queue = queue_next(queue);
tx_ep_desc = ep_desc;
}
}
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index d638a8a..96a8d69 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2321,6 +2321,7 @@ static struct usb_device_id rt73usb_device_table[] = {
/* Linksys */
{ USB_DEVICE(0x13b1, 0x0020), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x13b1, 0x0028), USB_DEVICE_DATA(&rt73usb_ops) },
/* MSI */
{ USB_DEVICE(0x0db0, 0x6877), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0db0, 0x6874), USB_DEVICE_DATA(&rt73usb_ops) },
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c
index 5f887fb..387c133 100644
--- a/drivers/net/wireless/rtl818x/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c
@@ -897,6 +897,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
IEEE80211_HW_RX_INCLUDES_FCS |
IEEE80211_HW_SIGNAL_UNSPEC;
+ dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
dev->queues = 1;
dev->max_signal = 65;
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
index 00ce3ef..6ad6bac 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -213,7 +213,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
kfree_skb(skb);
- return -ENOMEM;
+ return NETDEV_TX_OK;
}
flags = skb->len;
@@ -281,7 +281,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
}
usb_free_urb(urb);
- return rc;
+ return NETDEV_TX_OK;
}
static void rtl8187_rx_cb(struct urb *urb)
@@ -1471,6 +1471,7 @@ static void __devexit rtl8187_disconnect(struct usb_interface *intf)
ieee80211_unregister_hw(dev);
priv = dev->priv;
+ usb_reset_device(priv->udev);
usb_put_dev(interface_to_usbdev(intf));
ieee80211_free_hw(dev);
}
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index cf97129..2f1645d 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -362,6 +362,7 @@ static const struct net_device_ops netdev_ops = {
.ndo_set_multicast_list = set_rx_mode,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_do_ioctl = netdev_ioctl,
.ndo_tx_timeout = yellowfin_tx_timeout,
};
diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c
index affd904..37c84e3 100644
--- a/drivers/net/zorro8390.c
+++ b/drivers/net/zorro8390.c
@@ -147,6 +147,7 @@ static const struct net_device_ops zorro8390_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c
index e1b0ad6..fa65a2b 100644
--- a/drivers/of/of_i2c.c
+++ b/drivers/of/of_i2c.c
@@ -66,4 +66,23 @@ void of_register_i2c_devices(struct i2c_adapter *adap,
}
EXPORT_SYMBOL(of_register_i2c_devices);
+static int of_dev_node_match(struct device *dev, void *data)
+{
+ return dev_archdata_get_node(&dev->archdata) == data;
+}
+
+/* must call put_device() when done with returned i2c_client device */
+struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
+{
+ struct device *dev;
+
+ dev = bus_find_device(&i2c_bus_type, NULL, node,
+ of_dev_node_match);
+ if (!dev)
+ return NULL;
+
+ return to_i2c_client(dev);
+}
+EXPORT_SYMBOL(of_find_i2c_device_by_node);
+
MODULE_LICENSE("GPL");
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index 1e93c83..4fa3bb2 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -405,7 +405,6 @@ static void __init superio_serial_init(void)
serial_port.type = PORT_16550A;
serial_port.uartclk = 115200*16;
serial_port.fifosize = 16;
- spin_lock_init(&serial_port.lock);
/* serial port #1 */
serial_port.iobase = sio_dev.sp1_base;
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index b9a5629..c933980 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -438,7 +438,8 @@ static struct intel_iommu *device_to_iommu(u8 bus, u8 devfn)
continue;
for (i = 0; i < drhd->devices_cnt; i++)
- if (drhd->devices[i]->bus->number == bus &&
+ if (drhd->devices[i] &&
+ drhd->devices[i]->bus->number == bus &&
drhd->devices[i]->devfn == devfn)
return drhd->iommu;
diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c
index 645d7a6..ec22284 100644
--- a/drivers/pci/syscall.c
+++ b/drivers/pci/syscall.c
@@ -14,10 +14,8 @@
#include <asm/uaccess.h>
#include "pci.h"
-asmlinkage long
-sys_pciconfig_read(unsigned long bus, unsigned long dfn,
- unsigned long off, unsigned long len,
- void __user *buf)
+SYSCALL_DEFINE5(pciconfig_read, unsigned long, bus, unsigned long, dfn,
+ unsigned long, off, unsigned long, len, void __user *, buf)
{
struct pci_dev *dev;
u8 byte;
@@ -86,10 +84,8 @@ error:
return err;
}
-asmlinkage long
-sys_pciconfig_write(unsigned long bus, unsigned long dfn,
- unsigned long off, unsigned long len,
- void __user *buf)
+SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn,
+ unsigned long, off, unsigned long, len, void __user *, buf)
{
struct pci_dev *dev;
u8 byte;
diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c
index a34284b..d187ba4 100644
--- a/drivers/pcmcia/electra_cf.c
+++ b/drivers/pcmcia/electra_cf.c
@@ -297,7 +297,7 @@ static int __devinit electra_cf_probe(struct of_device *ofdev,
goto fail3;
}
- dev_info(device, "at mem 0x%lx io 0x%lx irq %d\n",
+ dev_info(device, "at mem 0x%lx io 0x%llx irq %d\n",
cf->mem_phys, io.start, cf->irq);
cf->active = 1;
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 6684724..33da112 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -82,4 +82,10 @@ config BATTERY_DA9030
Say Y here to enable support for batteries charger integrated into
DA9030 PMIC.
+config CHARGER_PCF50633
+ tristate "NXP PCF50633 MBC"
+ depends on MFD_PCF50633
+ help
+ Say Y to include support for NXP PCF50633 Main Battery Charger.
+
endif # POWER_SUPPLY
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index eebb155..2fcf41d 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -25,3 +25,4 @@ obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o
obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o
obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o
obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o
+obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o \ No newline at end of file
diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c
new file mode 100644
index 0000000..e988ec1
--- /dev/null
+++ b/drivers/power/pcf50633-charger.c
@@ -0,0 +1,358 @@
+/* NXP PCF50633 Main Battery Charger Driver
+ *
+ * (C) 2006-2008 by Openmoko, Inc.
+ * Author: Balaji Rao <balajirrao@openmoko.org>
+ * All rights reserved.
+ *
+ * Broken down from monstrous PCF50633 driver mainly by
+ * Harald Welte, Andy Green and Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/sysfs.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+
+#include <linux/mfd/pcf50633/core.h>
+#include <linux/mfd/pcf50633/mbc.h>
+
+struct pcf50633_mbc {
+ struct pcf50633 *pcf;
+
+ int adapter_active;
+ int adapter_online;
+ int usb_active;
+ int usb_online;
+
+ struct power_supply usb;
+ struct power_supply adapter;
+};
+
+int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma)
+{
+ struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev);
+ int ret = 0;
+ u8 bits;
+
+ if (ma >= 1000)
+ bits = PCF50633_MBCC7_USB_1000mA;
+ else if (ma >= 500)
+ bits = PCF50633_MBCC7_USB_500mA;
+ else if (ma >= 100)
+ bits = PCF50633_MBCC7_USB_100mA;
+ else
+ bits = PCF50633_MBCC7_USB_SUSPEND;
+
+ ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC7,
+ PCF50633_MBCC7_USB_MASK, bits);
+ if (ret)
+ dev_err(pcf->dev, "error setting usb curlim to %d mA\n", ma);
+ else
+ dev_info(pcf->dev, "usb curlim to %d mA\n", ma);
+
+ power_supply_changed(&mbc->usb);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pcf50633_mbc_usb_curlim_set);
+
+int pcf50633_mbc_get_status(struct pcf50633 *pcf)
+{
+ struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev);
+ int status = 0;
+
+ if (mbc->usb_online)
+ status |= PCF50633_MBC_USB_ONLINE;
+ if (mbc->usb_active)
+ status |= PCF50633_MBC_USB_ACTIVE;
+ if (mbc->adapter_online)
+ status |= PCF50633_MBC_ADAPTER_ONLINE;
+ if (mbc->adapter_active)
+ status |= PCF50633_MBC_ADAPTER_ACTIVE;
+
+ return status;
+}
+EXPORT_SYMBOL_GPL(pcf50633_mbc_get_status);
+
+void pcf50633_mbc_set_status(struct pcf50633 *pcf, int what, int status)
+{
+ struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev);
+
+ if (what & PCF50633_MBC_USB_ONLINE)
+ mbc->usb_online = !!status;
+ if (what & PCF50633_MBC_USB_ACTIVE)
+ mbc->usb_active = !!status;
+ if (what & PCF50633_MBC_ADAPTER_ONLINE)
+ mbc->adapter_online = !!status;
+ if (what & PCF50633_MBC_ADAPTER_ACTIVE)
+ mbc->adapter_active = !!status;
+}
+EXPORT_SYMBOL_GPL(pcf50633_mbc_set_status);
+
+static ssize_t
+show_chgmode(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct pcf50633_mbc *mbc = dev_get_drvdata(dev);
+
+ u8 mbcs2 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS2);
+ u8 chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK);
+
+ return sprintf(buf, "%d\n", chgmod);
+}
+static DEVICE_ATTR(chgmode, S_IRUGO, show_chgmode, NULL);
+
+static ssize_t
+show_usblim(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct pcf50633_mbc *mbc = dev_get_drvdata(dev);
+ u8 usblim = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC7) &
+ PCF50633_MBCC7_USB_MASK;
+ unsigned int ma;
+
+ if (usblim == PCF50633_MBCC7_USB_1000mA)
+ ma = 1000;
+ else if (usblim == PCF50633_MBCC7_USB_500mA)
+ ma = 500;
+ else if (usblim == PCF50633_MBCC7_USB_100mA)
+ ma = 100;
+ else
+ ma = 0;
+
+ return sprintf(buf, "%u\n", ma);
+}
+
+static ssize_t set_usblim(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct pcf50633_mbc *mbc = dev_get_drvdata(dev);
+ unsigned long ma;
+ int ret;
+
+ ret = strict_strtoul(buf, 10, &ma);
+ if (ret)
+ return -EINVAL;
+
+ pcf50633_mbc_usb_curlim_set(mbc->pcf, ma);
+
+ return count;
+}
+
+static DEVICE_ATTR(usb_curlim, S_IRUGO | S_IWUSR, show_usblim, set_usblim);
+
+static struct attribute *pcf50633_mbc_sysfs_entries[] = {
+ &dev_attr_chgmode.attr,
+ &dev_attr_usb_curlim.attr,
+ NULL,
+};
+
+static struct attribute_group mbc_attr_group = {
+ .name = NULL, /* put in device directory */
+ .attrs = pcf50633_mbc_sysfs_entries,
+};
+
+static void
+pcf50633_mbc_irq_handler(int irq, void *data)
+{
+ struct pcf50633_mbc *mbc = data;
+
+ /* USB */
+ if (irq == PCF50633_IRQ_USBINS) {
+ mbc->usb_online = 1;
+ } else if (irq == PCF50633_IRQ_USBREM) {
+ mbc->usb_online = 0;
+ mbc->usb_active = 0;
+ pcf50633_mbc_usb_curlim_set(mbc->pcf, 0);
+ }
+
+ /* Adapter */
+ if (irq == PCF50633_IRQ_ADPINS) {
+ mbc->adapter_online = 1;
+ mbc->adapter_active = 1;
+ } else if (irq == PCF50633_IRQ_ADPREM) {
+ mbc->adapter_online = 0;
+ mbc->adapter_active = 0;
+ }
+
+ if (irq == PCF50633_IRQ_BATFULL) {
+ mbc->usb_active = 0;
+ mbc->adapter_active = 0;
+ }
+
+ power_supply_changed(&mbc->usb);
+ power_supply_changed(&mbc->adapter);
+
+ if (mbc->pcf->pdata->mbc_event_callback)
+ mbc->pcf->pdata->mbc_event_callback(mbc->pcf, irq);
+}
+
+static int adapter_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, usb);
+ int ret = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = mbc->adapter_online;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int usb_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, usb);
+ int ret = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = mbc->usb_online;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static enum power_supply_property power_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static const u8 mbc_irq_handlers[] = {
+ PCF50633_IRQ_ADPINS,
+ PCF50633_IRQ_ADPREM,
+ PCF50633_IRQ_USBINS,
+ PCF50633_IRQ_USBREM,
+ PCF50633_IRQ_BATFULL,
+ PCF50633_IRQ_CHGHALT,
+ PCF50633_IRQ_THLIMON,
+ PCF50633_IRQ_THLIMOFF,
+ PCF50633_IRQ_USBLIMON,
+ PCF50633_IRQ_USBLIMOFF,
+ PCF50633_IRQ_LOWSYS,
+ PCF50633_IRQ_LOWBAT,
+};
+
+static int __devinit pcf50633_mbc_probe(struct platform_device *pdev)
+{
+ struct pcf50633_mbc *mbc;
+ struct pcf50633_subdev_pdata *pdata = pdev->dev.platform_data;
+ int ret;
+ int i;
+ u8 mbcs1;
+
+ mbc = kzalloc(sizeof(*mbc), GFP_KERNEL);
+ if (!mbc)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, mbc);
+ mbc->pcf = pdata->pcf;
+
+ /* Set up IRQ handlers */
+ for (i = 0; i < ARRAY_SIZE(mbc_irq_handlers); i++)
+ pcf50633_register_irq(mbc->pcf, mbc_irq_handlers[i],
+ pcf50633_mbc_irq_handler, mbc);
+
+ /* Create power supplies */
+ mbc->adapter.name = "adapter";
+ mbc->adapter.type = POWER_SUPPLY_TYPE_MAINS;
+ mbc->adapter.properties = power_props;
+ mbc->adapter.num_properties = ARRAY_SIZE(power_props);
+ mbc->adapter.get_property = &adapter_get_property;
+ mbc->adapter.supplied_to = mbc->pcf->pdata->batteries;
+ mbc->adapter.num_supplicants = mbc->pcf->pdata->num_batteries;
+
+ mbc->usb.name = "usb";
+ mbc->usb.type = POWER_SUPPLY_TYPE_USB;
+ mbc->usb.properties = power_props;
+ mbc->usb.num_properties = ARRAY_SIZE(power_props);
+ mbc->usb.get_property = usb_get_property;
+ mbc->usb.supplied_to = mbc->pcf->pdata->batteries;
+ mbc->usb.num_supplicants = mbc->pcf->pdata->num_batteries;
+
+ ret = power_supply_register(&pdev->dev, &mbc->adapter);
+ if (ret) {
+ dev_err(mbc->pcf->dev, "failed to register adapter\n");
+ kfree(mbc);
+ return ret;
+ }
+
+ ret = power_supply_register(&pdev->dev, &mbc->usb);
+ if (ret) {
+ dev_err(mbc->pcf->dev, "failed to register usb\n");
+ power_supply_unregister(&mbc->adapter);
+ kfree(mbc);
+ return ret;
+ }
+
+ ret = sysfs_create_group(&pdev->dev.kobj, &mbc_attr_group);
+ if (ret)
+ dev_err(mbc->pcf->dev, "failed to create sysfs entries\n");
+
+ mbcs1 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS1);
+ if (mbcs1 & PCF50633_MBCS1_USBPRES)
+ pcf50633_mbc_irq_handler(PCF50633_IRQ_USBINS, mbc);
+ if (mbcs1 & PCF50633_MBCS1_ADAPTPRES)
+ pcf50633_mbc_irq_handler(PCF50633_IRQ_ADPINS, mbc);
+
+ return 0;
+}
+
+static int __devexit pcf50633_mbc_remove(struct platform_device *pdev)
+{
+ struct pcf50633_mbc *mbc = platform_get_drvdata(pdev);
+ int i;
+
+ /* Remove IRQ handlers */
+ for (i = 0; i < ARRAY_SIZE(mbc_irq_handlers); i++)
+ pcf50633_free_irq(mbc->pcf, mbc_irq_handlers[i]);
+
+ power_supply_unregister(&mbc->usb);
+ power_supply_unregister(&mbc->adapter);
+
+ kfree(mbc);
+
+ return 0;
+}
+
+static struct platform_driver pcf50633_mbc_driver = {
+ .driver = {
+ .name = "pcf50633-mbc",
+ },
+ .probe = pcf50633_mbc_probe,
+ .remove = __devexit_p(pcf50633_mbc_remove),
+};
+
+static int __init pcf50633_mbc_init(void)
+{
+ return platform_driver_register(&pcf50633_mbc_driver);
+}
+module_init(pcf50633_mbc_init);
+
+static void __exit pcf50633_mbc_exit(void)
+{
+ platform_driver_unregister(&pcf50633_mbc_driver);
+}
+module_exit(pcf50633_mbc_exit);
+
+MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
+MODULE_DESCRIPTION("PCF50633 mbc driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pcf50633-mbc");
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 39360e2..e7e0cf1 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -73,4 +73,11 @@ config REGULATOR_DA903X
Say y here to support the BUCKs and LDOs regulators found on
Dialog Semiconductor DA9030/DA9034 PMIC.
+config REGULATOR_PCF50633
+ tristate "PCF50633 regulator driver"
+ depends on MFD_PCF50633
+ help
+ Say Y here to support the voltage regulators and convertors
+ on PCF50633
+
endif
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 254d40c..61b30c6 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -11,5 +11,6 @@ obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o
obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
+obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c
new file mode 100644
index 0000000..4cc85ec
--- /dev/null
+++ b/drivers/regulator/pcf50633-regulator.c
@@ -0,0 +1,329 @@
+/* NXP PCF50633 PMIC Driver
+ *
+ * (C) 2006-2008 by Openmoko, Inc.
+ * Author: Balaji Rao <balajirrao@openmoko.org>
+ * All rights reserved.
+ *
+ * Broken down from monstrous PCF50633 driver mainly by
+ * Harald Welte and Andy Green and Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+
+#include <linux/mfd/pcf50633/core.h>
+#include <linux/mfd/pcf50633/pmic.h>
+
+#define PCF50633_REGULATOR(_name, _id) \
+ { \
+ .name = _name, \
+ .id = _id, \
+ .ops = &pcf50633_regulator_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ }
+
+static const u8 pcf50633_regulator_registers[PCF50633_NUM_REGULATORS] = {
+ [PCF50633_REGULATOR_AUTO] = PCF50633_REG_AUTOOUT,
+ [PCF50633_REGULATOR_DOWN1] = PCF50633_REG_DOWN1OUT,
+ [PCF50633_REGULATOR_DOWN2] = PCF50633_REG_DOWN2OUT,
+ [PCF50633_REGULATOR_MEMLDO] = PCF50633_REG_MEMLDOOUT,
+ [PCF50633_REGULATOR_LDO1] = PCF50633_REG_LDO1OUT,
+ [PCF50633_REGULATOR_LDO2] = PCF50633_REG_LDO2OUT,
+ [PCF50633_REGULATOR_LDO3] = PCF50633_REG_LDO3OUT,
+ [PCF50633_REGULATOR_LDO4] = PCF50633_REG_LDO4OUT,
+ [PCF50633_REGULATOR_LDO5] = PCF50633_REG_LDO5OUT,
+ [PCF50633_REGULATOR_LDO6] = PCF50633_REG_LDO6OUT,
+ [PCF50633_REGULATOR_HCLDO] = PCF50633_REG_HCLDOOUT,
+};
+
+/* Bits from voltage value */
+static u8 auto_voltage_bits(unsigned int millivolts)
+{
+ if (millivolts < 1800)
+ return 0;
+ if (millivolts > 3800)
+ return 0xff;
+
+ millivolts -= 625;
+
+ return millivolts / 25;
+}
+
+static u8 down_voltage_bits(unsigned int millivolts)
+{
+ if (millivolts < 625)
+ return 0;
+ else if (millivolts > 3000)
+ return 0xff;
+
+ millivolts -= 625;
+
+ return millivolts / 25;
+}
+
+static u8 ldo_voltage_bits(unsigned int millivolts)
+{
+ if (millivolts < 900)
+ return 0;
+ else if (millivolts > 3600)
+ return 0x1f;
+
+ millivolts -= 900;
+ return millivolts / 100;
+}
+
+/* Obtain voltage value from bits */
+static unsigned int auto_voltage_value(u8 bits)
+{
+ if (bits < 0x2f)
+ return 0;
+
+ return 625 + (bits * 25);
+}
+
+
+static unsigned int down_voltage_value(u8 bits)
+{
+ return 625 + (bits * 25);
+}
+
+
+static unsigned int ldo_voltage_value(u8 bits)
+{
+ bits &= 0x1f;
+
+ return 900 + (bits * 100);
+}
+
+static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
+{
+ struct pcf50633 *pcf;
+ int regulator_id, millivolts;
+ u8 volt_bits, regnr;
+
+ pcf = rdev_get_drvdata(rdev);
+
+ regulator_id = rdev_get_id(rdev);
+ if (regulator_id >= PCF50633_NUM_REGULATORS)
+ return -EINVAL;
+
+ millivolts = min_uV / 1000;
+
+ regnr = pcf50633_regulator_registers[regulator_id];
+
+ switch (regulator_id) {
+ case PCF50633_REGULATOR_AUTO:
+ volt_bits = auto_voltage_bits(millivolts);
+ break;
+ case PCF50633_REGULATOR_DOWN1:
+ volt_bits = down_voltage_bits(millivolts);
+ break;
+ case PCF50633_REGULATOR_DOWN2:
+ volt_bits = down_voltage_bits(millivolts);
+ break;
+ case PCF50633_REGULATOR_LDO1:
+ case PCF50633_REGULATOR_LDO2:
+ case PCF50633_REGULATOR_LDO3:
+ case PCF50633_REGULATOR_LDO4:
+ case PCF50633_REGULATOR_LDO5:
+ case PCF50633_REGULATOR_LDO6:
+ case PCF50633_REGULATOR_HCLDO:
+ volt_bits = ldo_voltage_bits(millivolts);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return pcf50633_reg_write(pcf, regnr, volt_bits);
+}
+
+static int pcf50633_regulator_get_voltage(struct regulator_dev *rdev)
+{
+ struct pcf50633 *pcf;
+ int regulator_id, millivolts, volt_bits;
+ u8 regnr;
+
+ pcf = rdev_get_drvdata(rdev);;
+
+ regulator_id = rdev_get_id(rdev);
+ if (regulator_id >= PCF50633_NUM_REGULATORS)
+ return -EINVAL;
+
+ regnr = pcf50633_regulator_registers[regulator_id];
+
+ volt_bits = pcf50633_reg_read(pcf, regnr);
+ if (volt_bits < 0)
+ return -1;
+
+ switch (regulator_id) {
+ case PCF50633_REGULATOR_AUTO:
+ millivolts = auto_voltage_value(volt_bits);
+ break;
+ case PCF50633_REGULATOR_DOWN1:
+ millivolts = down_voltage_value(volt_bits);
+ break;
+ case PCF50633_REGULATOR_DOWN2:
+ millivolts = down_voltage_value(volt_bits);
+ break;
+ case PCF50633_REGULATOR_LDO1:
+ case PCF50633_REGULATOR_LDO2:
+ case PCF50633_REGULATOR_LDO3:
+ case PCF50633_REGULATOR_LDO4:
+ case PCF50633_REGULATOR_LDO5:
+ case PCF50633_REGULATOR_LDO6:
+ case PCF50633_REGULATOR_HCLDO:
+ millivolts = ldo_voltage_value(volt_bits);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return millivolts * 1000;
+}
+
+static int pcf50633_regulator_enable(struct regulator_dev *rdev)
+{
+ struct pcf50633 *pcf = rdev_get_drvdata(rdev);
+ int regulator_id;
+ u8 regnr;
+
+ regulator_id = rdev_get_id(rdev);
+ if (regulator_id >= PCF50633_NUM_REGULATORS)
+ return -EINVAL;
+
+ /* The *ENA register is always one after the *OUT register */
+ regnr = pcf50633_regulator_registers[regulator_id] + 1;
+
+ return pcf50633_reg_set_bit_mask(pcf, regnr, PCF50633_REGULATOR_ON,
+ PCF50633_REGULATOR_ON);
+}
+
+static int pcf50633_regulator_disable(struct regulator_dev *rdev)
+{
+ struct pcf50633 *pcf = rdev_get_drvdata(rdev);
+ int regulator_id;
+ u8 regnr;
+
+ regulator_id = rdev_get_id(rdev);
+ if (regulator_id >= PCF50633_NUM_REGULATORS)
+ return -EINVAL;
+
+ /* the *ENA register is always one after the *OUT register */
+ regnr = pcf50633_regulator_registers[regulator_id] + 1;
+
+ return pcf50633_reg_set_bit_mask(pcf, regnr,
+ PCF50633_REGULATOR_ON, 0);
+}
+
+static int pcf50633_regulator_is_enabled(struct regulator_dev *rdev)
+{
+ struct pcf50633 *pcf = rdev_get_drvdata(rdev);
+ int regulator_id = rdev_get_id(rdev);
+ u8 regnr;
+
+ regulator_id = rdev_get_id(rdev);
+ if (regulator_id >= PCF50633_NUM_REGULATORS)
+ return -EINVAL;
+
+ /* the *ENA register is always one after the *OUT register */
+ regnr = pcf50633_regulator_registers[regulator_id] + 1;
+
+ return pcf50633_reg_read(pcf, regnr) & PCF50633_REGULATOR_ON;
+}
+
+static struct regulator_ops pcf50633_regulator_ops = {
+ .set_voltage = pcf50633_regulator_set_voltage,
+ .get_voltage = pcf50633_regulator_get_voltage,
+ .enable = pcf50633_regulator_enable,
+ .disable = pcf50633_regulator_disable,
+ .is_enabled = pcf50633_regulator_is_enabled,
+};
+
+static struct regulator_desc regulators[] = {
+ [PCF50633_REGULATOR_AUTO] =
+ PCF50633_REGULATOR("auto", PCF50633_REGULATOR_AUTO),
+ [PCF50633_REGULATOR_DOWN1] =
+ PCF50633_REGULATOR("down1", PCF50633_REGULATOR_DOWN1),
+ [PCF50633_REGULATOR_DOWN2] =
+ PCF50633_REGULATOR("down2", PCF50633_REGULATOR_DOWN2),
+ [PCF50633_REGULATOR_LDO1] =
+ PCF50633_REGULATOR("ldo1", PCF50633_REGULATOR_LDO1),
+ [PCF50633_REGULATOR_LDO2] =
+ PCF50633_REGULATOR("ldo2", PCF50633_REGULATOR_LDO2),
+ [PCF50633_REGULATOR_LDO3] =
+ PCF50633_REGULATOR("ldo3", PCF50633_REGULATOR_LDO3),
+ [PCF50633_REGULATOR_LDO4] =
+ PCF50633_REGULATOR("ldo4", PCF50633_REGULATOR_LDO4),
+ [PCF50633_REGULATOR_LDO5] =
+ PCF50633_REGULATOR("ldo5", PCF50633_REGULATOR_LDO5),
+ [PCF50633_REGULATOR_LDO6] =
+ PCF50633_REGULATOR("ldo6", PCF50633_REGULATOR_LDO6),
+ [PCF50633_REGULATOR_HCLDO] =
+ PCF50633_REGULATOR("hcldo", PCF50633_REGULATOR_HCLDO),
+ [PCF50633_REGULATOR_MEMLDO] =
+ PCF50633_REGULATOR("memldo", PCF50633_REGULATOR_MEMLDO),
+};
+
+static int __devinit pcf50633_regulator_probe(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev;
+ struct pcf50633 *pcf;
+
+ /* Already set by core driver */
+ pcf = platform_get_drvdata(pdev);
+
+ rdev = regulator_register(&regulators[pdev->id], &pdev->dev, pcf);
+ if (IS_ERR(rdev))
+ return PTR_ERR(rdev);
+
+ if (pcf->pdata->regulator_registered)
+ pcf->pdata->regulator_registered(pcf, pdev->id);
+
+ return 0;
+}
+
+static int __devexit pcf50633_regulator_remove(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev = platform_get_drvdata(pdev);
+
+ regulator_unregister(rdev);
+
+ return 0;
+}
+
+static struct platform_driver pcf50633_regulator_driver = {
+ .driver = {
+ .name = "pcf50633-regltr",
+ },
+ .probe = pcf50633_regulator_probe,
+ .remove = __devexit_p(pcf50633_regulator_remove),
+};
+
+static int __init pcf50633_regulator_init(void)
+{
+ return platform_driver_register(&pcf50633_regulator_driver);
+}
+module_init(pcf50633_regulator_init);
+
+static void __exit pcf50633_regulator_exit(void)
+{
+ platform_driver_unregister(&pcf50633_regulator_driver);
+}
+module_exit(pcf50633_regulator_exit);
+
+MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
+MODULE_DESCRIPTION("PCF50633 regulator driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pcf50633-regulator");
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 4ad831d..cced4d1 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -502,6 +502,13 @@ config RTC_DRV_WM8350
This driver can also be built as a module. If so, the module
will be called "rtc-wm8350".
+config RTC_DRV_PCF50633
+ depends on MFD_PCF50633
+ tristate "NXP PCF50633 RTC"
+ help
+ If you say yes here you get support for the RTC subsystem of the
+ NXP PCF50633 used in embedded systems.
+
comment "on-CPU RTC drivers"
config RTC_DRV_OMAP
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 9a4340d..6e28021 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -74,3 +74,4 @@ obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o
obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o
obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
+obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o
diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c
new file mode 100644
index 0000000..f4dd87e
--- /dev/null
+++ b/drivers/rtc/rtc-pcf50633.c
@@ -0,0 +1,344 @@
+/* NXP PCF50633 RTC Driver
+ *
+ * (C) 2006-2008 by Openmoko, Inc.
+ * Author: Balaji Rao <balajirrao@openmoko.org>
+ * All rights reserved.
+ *
+ * Broken down from monstrous PCF50633 driver mainly by
+ * Harald Welte, Andy Green and Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/err.h>
+
+#include <linux/mfd/pcf50633/core.h>
+
+#define PCF50633_REG_RTCSC 0x59 /* Second */
+#define PCF50633_REG_RTCMN 0x5a /* Minute */
+#define PCF50633_REG_RTCHR 0x5b /* Hour */
+#define PCF50633_REG_RTCWD 0x5c /* Weekday */
+#define PCF50633_REG_RTCDT 0x5d /* Day */
+#define PCF50633_REG_RTCMT 0x5e /* Month */
+#define PCF50633_REG_RTCYR 0x5f /* Year */
+#define PCF50633_REG_RTCSCA 0x60 /* Alarm Second */
+#define PCF50633_REG_RTCMNA 0x61 /* Alarm Minute */
+#define PCF50633_REG_RTCHRA 0x62 /* Alarm Hour */
+#define PCF50633_REG_RTCWDA 0x63 /* Alarm Weekday */
+#define PCF50633_REG_RTCDTA 0x64 /* Alarm Day */
+#define PCF50633_REG_RTCMTA 0x65 /* Alarm Month */
+#define PCF50633_REG_RTCYRA 0x66 /* Alarm Year */
+
+enum pcf50633_time_indexes {
+ PCF50633_TI_SEC,
+ PCF50633_TI_MIN,
+ PCF50633_TI_HOUR,
+ PCF50633_TI_WKDAY,
+ PCF50633_TI_DAY,
+ PCF50633_TI_MONTH,
+ PCF50633_TI_YEAR,
+ PCF50633_TI_EXTENT /* always last */
+};
+
+struct pcf50633_time {
+ u_int8_t time[PCF50633_TI_EXTENT];
+};
+
+struct pcf50633_rtc {
+ int alarm_enabled;
+ int second_enabled;
+
+ struct pcf50633 *pcf;
+ struct rtc_device *rtc_dev;
+};
+
+static void pcf2rtc_time(struct rtc_time *rtc, struct pcf50633_time *pcf)
+{
+ rtc->tm_sec = bcd2bin(pcf->time[PCF50633_TI_SEC]);
+ rtc->tm_min = bcd2bin(pcf->time[PCF50633_TI_MIN]);
+ rtc->tm_hour = bcd2bin(pcf->time[PCF50633_TI_HOUR]);
+ rtc->tm_wday = bcd2bin(pcf->time[PCF50633_TI_WKDAY]);
+ rtc->tm_mday = bcd2bin(pcf->time[PCF50633_TI_DAY]);
+ rtc->tm_mon = bcd2bin(pcf->time[PCF50633_TI_MONTH]);
+ rtc->tm_year = bcd2bin(pcf->time[PCF50633_TI_YEAR]) + 100;
+}
+
+static void rtc2pcf_time(struct pcf50633_time *pcf, struct rtc_time *rtc)
+{
+ pcf->time[PCF50633_TI_SEC] = bin2bcd(rtc->tm_sec);
+ pcf->time[PCF50633_TI_MIN] = bin2bcd(rtc->tm_min);
+ pcf->time[PCF50633_TI_HOUR] = bin2bcd(rtc->tm_hour);
+ pcf->time[PCF50633_TI_WKDAY] = bin2bcd(rtc->tm_wday);
+ pcf->time[PCF50633_TI_DAY] = bin2bcd(rtc->tm_mday);
+ pcf->time[PCF50633_TI_MONTH] = bin2bcd(rtc->tm_mon);
+ pcf->time[PCF50633_TI_YEAR] = bin2bcd(rtc->tm_year % 100);
+}
+
+static int
+pcf50633_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ struct pcf50633_rtc *rtc = dev_get_drvdata(dev);
+ int err;
+
+ if (enabled)
+ err = pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM);
+ else
+ err = pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM);
+
+ if (err < 0)
+ return err;
+
+ rtc->alarm_enabled = enabled;
+
+ return 0;
+}
+
+static int
+pcf50633_rtc_update_irq_enable(struct device *dev, unsigned int enabled)
+{
+ struct pcf50633_rtc *rtc = dev_get_drvdata(dev);
+ int err;
+
+ if (enabled)
+ err = pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_SECOND);
+ else
+ err = pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_SECOND);
+
+ if (err < 0)
+ return err;
+
+ rtc->second_enabled = enabled;
+
+ return 0;
+}
+
+static int pcf50633_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct pcf50633_rtc *rtc;
+ struct pcf50633_time pcf_tm;
+ int ret;
+
+ rtc = dev_get_drvdata(dev);
+
+ ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSC,
+ PCF50633_TI_EXTENT,
+ &pcf_tm.time[0]);
+ if (ret != PCF50633_TI_EXTENT) {
+ dev_err(dev, "Failed to read time\n");
+ return -EIO;
+ }
+
+ dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n",
+ pcf_tm.time[PCF50633_TI_DAY],
+ pcf_tm.time[PCF50633_TI_MONTH],
+ pcf_tm.time[PCF50633_TI_YEAR],
+ pcf_tm.time[PCF50633_TI_HOUR],
+ pcf_tm.time[PCF50633_TI_MIN],
+ pcf_tm.time[PCF50633_TI_SEC]);
+
+ pcf2rtc_time(tm, &pcf_tm);
+
+ dev_dbg(dev, "RTC_TIME: %u.%u.%u %u:%u:%u\n",
+ tm->tm_mday, tm->tm_mon, tm->tm_year,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+ return rtc_valid_tm(tm);
+}
+
+static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct pcf50633_rtc *rtc;
+ struct pcf50633_time pcf_tm;
+ int second_masked, alarm_masked, ret = 0;
+
+ rtc = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "RTC_TIME: %u.%u.%u %u:%u:%u\n",
+ tm->tm_mday, tm->tm_mon, tm->tm_year,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+ rtc2pcf_time(&pcf_tm, tm);
+
+ dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n",
+ pcf_tm.time[PCF50633_TI_DAY],
+ pcf_tm.time[PCF50633_TI_MONTH],
+ pcf_tm.time[PCF50633_TI_YEAR],
+ pcf_tm.time[PCF50633_TI_HOUR],
+ pcf_tm.time[PCF50633_TI_MIN],
+ pcf_tm.time[PCF50633_TI_SEC]);
+
+
+ second_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_SECOND);
+ alarm_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_ALARM);
+
+ if (!second_masked)
+ pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_SECOND);
+ if (!alarm_masked)
+ pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM);
+
+ /* Returns 0 on success */
+ ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSC,
+ PCF50633_TI_EXTENT,
+ &pcf_tm.time[0]);
+
+ if (!second_masked)
+ pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_SECOND);
+ if (!alarm_masked)
+ pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM);
+
+ return ret;
+}
+
+static int pcf50633_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct pcf50633_rtc *rtc;
+ struct pcf50633_time pcf_tm;
+ int ret = 0;
+
+ rtc = dev_get_drvdata(dev);
+
+ alrm->enabled = rtc->alarm_enabled;
+
+ ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSCA,
+ PCF50633_TI_EXTENT, &pcf_tm.time[0]);
+ if (ret != PCF50633_TI_EXTENT) {
+ dev_err(dev, "Failed to read time\n");
+ return -EIO;
+ }
+
+ pcf2rtc_time(&alrm->time, &pcf_tm);
+
+ return rtc_valid_tm(&alrm->time);
+}
+
+static int pcf50633_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct pcf50633_rtc *rtc;
+ struct pcf50633_time pcf_tm;
+ int alarm_masked, ret = 0;
+
+ rtc = dev_get_drvdata(dev);
+
+ rtc2pcf_time(&pcf_tm, &alrm->time);
+
+ /* do like mktime does and ignore tm_wday */
+ pcf_tm.time[PCF50633_TI_WKDAY] = 7;
+
+ alarm_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_ALARM);
+
+ /* disable alarm interrupt */
+ if (!alarm_masked)
+ pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM);
+
+ /* Returns 0 on success */
+ ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSCA,
+ PCF50633_TI_EXTENT, &pcf_tm.time[0]);
+
+ if (!alarm_masked)
+ pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM);
+
+ return ret;
+}
+
+static struct rtc_class_ops pcf50633_rtc_ops = {
+ .read_time = pcf50633_rtc_read_time,
+ .set_time = pcf50633_rtc_set_time,
+ .read_alarm = pcf50633_rtc_read_alarm,
+ .set_alarm = pcf50633_rtc_set_alarm,
+ .alarm_irq_enable = pcf50633_rtc_alarm_irq_enable,
+ .update_irq_enable = pcf50633_rtc_update_irq_enable,
+};
+
+static void pcf50633_rtc_irq(int irq, void *data)
+{
+ struct pcf50633_rtc *rtc = data;
+
+ switch (irq) {
+ case PCF50633_IRQ_ALARM:
+ rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
+ break;
+ case PCF50633_IRQ_SECOND:
+ rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF);
+ break;
+ }
+}
+
+static int __devinit pcf50633_rtc_probe(struct platform_device *pdev)
+{
+ struct pcf50633_subdev_pdata *pdata;
+ struct pcf50633_rtc *rtc;
+
+
+ rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
+ if (!rtc)
+ return -ENOMEM;
+
+ pdata = pdev->dev.platform_data;
+ rtc->pcf = pdata->pcf;
+ platform_set_drvdata(pdev, rtc);
+ rtc->rtc_dev = rtc_device_register("pcf50633-rtc", &pdev->dev,
+ &pcf50633_rtc_ops, THIS_MODULE);
+
+ if (IS_ERR(rtc->rtc_dev)) {
+ kfree(rtc);
+ return PTR_ERR(rtc->rtc_dev);
+ }
+
+ pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_ALARM,
+ pcf50633_rtc_irq, rtc);
+ pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_SECOND,
+ pcf50633_rtc_irq, rtc);
+
+ return 0;
+}
+
+static int __devexit pcf50633_rtc_remove(struct platform_device *pdev)
+{
+ struct pcf50633_rtc *rtc;
+
+ rtc = platform_get_drvdata(pdev);
+
+ pcf50633_free_irq(rtc->pcf, PCF50633_IRQ_ALARM);
+ pcf50633_free_irq(rtc->pcf, PCF50633_IRQ_SECOND);
+
+ rtc_device_unregister(rtc->rtc_dev);
+ kfree(rtc);
+
+ return 0;
+}
+
+static struct platform_driver pcf50633_rtc_driver = {
+ .driver = {
+ .name = "pcf50633-rtc",
+ },
+ .probe = pcf50633_rtc_probe,
+ .remove = __devexit_p(pcf50633_rtc_remove),
+};
+
+static int __init pcf50633_rtc_init(void)
+{
+ return platform_driver_register(&pcf50633_rtc_driver);
+}
+module_init(pcf50633_rtc_init);
+
+static void __exit pcf50633_rtc_exit(void)
+{
+ platform_driver_unregister(&pcf50633_rtc_driver);
+}
+module_exit(pcf50633_rtc_exit);
+
+MODULE_DESCRIPTION("PCF50633 RTC driver");
+MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c
index cc7eb87..bd56a03 100644
--- a/drivers/rtc/rtc-pxa.c
+++ b/drivers/rtc/rtc-pxa.c
@@ -27,6 +27,8 @@
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <mach/hardware.h>
+
#define TIMER_FREQ CLOCK_TICK_RATE
#define RTC_DEF_DIVIDER (32768 - 1)
#define RTC_DEF_TRIM 0
diff --git a/drivers/rtc/rtc-twl4030.c b/drivers/rtc/rtc-twl4030.c
index 8ce5f74..ad35f76 100644
--- a/drivers/rtc/rtc-twl4030.c
+++ b/drivers/rtc/rtc-twl4030.c
@@ -120,7 +120,7 @@ static int twl4030_rtc_write_u8(u8 data, u8 reg)
static unsigned char rtc_irq_bits;
/*
- * Enable timer and/or alarm interrupts.
+ * Enable 1/second update and/or alarm interrupts.
*/
static int set_rtc_irq_bit(unsigned char bit)
{
@@ -128,6 +128,7 @@ static int set_rtc_irq_bit(unsigned char bit)
int ret;
val = rtc_irq_bits | bit;
+ val &= ~BIT_RTC_INTERRUPTS_REG_EVERY_M;
ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG);
if (ret == 0)
rtc_irq_bits = val;
@@ -136,7 +137,7 @@ static int set_rtc_irq_bit(unsigned char bit)
}
/*
- * Disable timer and/or alarm interrupts.
+ * Disable update and/or alarm interrupts.
*/
static int mask_rtc_irq_bit(unsigned char bit)
{
@@ -151,7 +152,7 @@ static int mask_rtc_irq_bit(unsigned char bit)
return ret;
}
-static inline int twl4030_rtc_alarm_irq_set_state(int enabled)
+static int twl4030_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
{
int ret;
@@ -163,7 +164,7 @@ static inline int twl4030_rtc_alarm_irq_set_state(int enabled)
return ret;
}
-static inline int twl4030_rtc_irq_set_state(int enabled)
+static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled)
{
int ret;
@@ -292,7 +293,7 @@ static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
unsigned char alarm_data[ALL_TIME_REGS + 1];
int ret;
- ret = twl4030_rtc_alarm_irq_set_state(0);
+ ret = twl4030_rtc_alarm_irq_enable(dev, 0);
if (ret)
goto out;
@@ -312,35 +313,11 @@ static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
}
if (alm->enabled)
- ret = twl4030_rtc_alarm_irq_set_state(1);
+ ret = twl4030_rtc_alarm_irq_enable(dev, 1);
out:
return ret;
}
-#ifdef CONFIG_RTC_INTF_DEV
-
-static int twl4030_rtc_ioctl(struct device *dev, unsigned int cmd,
- unsigned long arg)
-{
- switch (cmd) {
- case RTC_AIE_OFF:
- return twl4030_rtc_alarm_irq_set_state(0);
- case RTC_AIE_ON:
- return twl4030_rtc_alarm_irq_set_state(1);
- case RTC_UIE_OFF:
- return twl4030_rtc_irq_set_state(0);
- case RTC_UIE_ON:
- return twl4030_rtc_irq_set_state(1);
-
- default:
- return -ENOIOCTLCMD;
- }
-}
-
-#else
-#define twl4030_rtc_ioctl NULL
-#endif
-
static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc)
{
unsigned long events = 0;
@@ -400,11 +377,12 @@ out:
}
static struct rtc_class_ops twl4030_rtc_ops = {
- .ioctl = twl4030_rtc_ioctl,
.read_time = twl4030_rtc_read_time,
.set_time = twl4030_rtc_set_time,
.read_alarm = twl4030_rtc_read_alarm,
.set_alarm = twl4030_rtc_set_alarm,
+ .alarm_irq_enable = twl4030_rtc_alarm_irq_enable,
+ .update_irq_enable = twl4030_rtc_update_irq_enable,
};
/*----------------------------------------------------------------------*/
@@ -422,7 +400,7 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev)
rtc = rtc_device_register(pdev->name,
&pdev->dev, &twl4030_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc)) {
- ret = -EINVAL;
+ ret = PTR_ERR(rtc);
dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
PTR_ERR(rtc));
goto out0;
@@ -432,7 +410,6 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rtc);
ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);
-
if (ret < 0)
goto out1;
@@ -475,7 +452,6 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev)
return ret;
-
out2:
free_irq(irq, rtc);
out1:
@@ -506,8 +482,9 @@ static int __devexit twl4030_rtc_remove(struct platform_device *pdev)
static void twl4030_rtc_shutdown(struct platform_device *pdev)
{
- mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M |
- BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
+ /* mask timer interrupts, but leave alarm interrupts on to enable
+ power-on when alarm is triggered */
+ mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
}
#ifdef CONFIG_PM
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index c4f1b04..07ab8a5 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -916,7 +916,7 @@ static struct ethtool_ops qeth_l2_osn_ops = {
.get_drvinfo = qeth_core_get_drvinfo,
};
-static struct net_device_ops qeth_l2_netdev_ops = {
+static const struct net_device_ops qeth_l2_netdev_ops = {
.ndo_open = qeth_l2_open,
.ndo_stop = qeth_l2_stop,
.ndo_get_stats = qeth_get_stats,
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 68d623a..3d04920 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -2894,7 +2894,7 @@ qeth_l3_neigh_setup(struct net_device *dev, struct neigh_parms *np)
return 0;
}
-static struct net_device_ops qeth_l3_netdev_ops = {
+static const struct net_device_ops qeth_l3_netdev_ops = {
.ndo_open = qeth_l3_open,
.ndo_stop = qeth_l3_stop,
.ndo_get_stats = qeth_get_stats,
@@ -2909,6 +2909,22 @@ static struct net_device_ops qeth_l3_netdev_ops = {
.ndo_tx_timeout = qeth_tx_timeout,
};
+static const struct net_device_ops qeth_l3_osa_netdev_ops = {
+ .ndo_open = qeth_l3_open,
+ .ndo_stop = qeth_l3_stop,
+ .ndo_get_stats = qeth_get_stats,
+ .ndo_start_xmit = qeth_l3_hard_start_xmit,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_multicast_list = qeth_l3_set_multicast_list,
+ .ndo_do_ioctl = qeth_l3_do_ioctl,
+ .ndo_change_mtu = qeth_change_mtu,
+ .ndo_vlan_rx_register = qeth_l3_vlan_rx_register,
+ .ndo_vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid,
+ .ndo_tx_timeout = qeth_tx_timeout,
+ .ndo_neigh_setup = qeth_l3_neigh_setup,
+};
+
static int qeth_l3_setup_netdev(struct qeth_card *card)
{
if (card->info.type == QETH_CARD_TYPE_OSAE) {
@@ -2919,12 +2935,12 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
#endif
if (!card->dev)
return -ENODEV;
+ card->dev->netdev_ops = &qeth_l3_netdev_ops;
} else {
card->dev = alloc_etherdev(0);
if (!card->dev)
return -ENODEV;
- qeth_l3_netdev_ops.ndo_neigh_setup =
- qeth_l3_neigh_setup;
+ card->dev->netdev_ops = &qeth_l3_osa_netdev_ops;
/*IPv6 address autoconfiguration stuff*/
qeth_l3_get_unique_id(card);
@@ -2937,6 +2953,7 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
if (!card->dev)
return -ENODEV;
card->dev->flags |= IFF_NOARP;
+ card->dev->netdev_ops = &qeth_l3_netdev_ops;
qeth_l3_iqd_read_initial_mac(card);
} else
return -ENODEV;
@@ -2944,7 +2961,6 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
card->dev->ml_priv = card;
card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
card->dev->mtu = card->info.initial_mtu;
- card->dev->netdev_ops = &qeth_l3_netdev_ops;
SET_ETHTOOL_OPS(card->dev, &qeth_l3_ethtool_ops);
card->dev->features |= NETIF_F_HW_VLAN_TX |
NETIF_F_HW_VLAN_RX |
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 5c541f7..74d07d1 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -1061,7 +1061,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
}
sdev_printk(KERN_INFO, cmd->device,
- "aborting command. lun 0x%lx, tag 0x%lx\n",
+ "aborting command. lun 0x%llx, tag 0x%llx\n",
(((u64) lun) << 48), (u64) found_evt);
wait_for_completion(&evt->comp);
@@ -1082,7 +1082,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
if (rsp_rc) {
if (printk_ratelimit())
sdev_printk(KERN_WARNING, cmd->device,
- "abort code %d for task tag 0x%lx\n",
+ "abort code %d for task tag 0x%llx\n",
rsp_rc, tsk_mgmt->task_tag);
return FAILED;
}
@@ -1102,12 +1102,12 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
if (found_evt == NULL) {
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
- sdev_printk(KERN_INFO, cmd->device, "aborted task tag 0x%lx completed\n",
+ sdev_printk(KERN_INFO, cmd->device, "aborted task tag 0x%llx completed\n",
tsk_mgmt->task_tag);
return SUCCESS;
}
- sdev_printk(KERN_INFO, cmd->device, "successfully aborted task tag 0x%lx\n",
+ sdev_printk(KERN_INFO, cmd->device, "successfully aborted task tag 0x%llx\n",
tsk_mgmt->task_tag);
cmd->result = (DID_ABORT << 16);
@@ -1182,7 +1182,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
return FAILED;
}
- sdev_printk(KERN_INFO, cmd->device, "resetting device. lun 0x%lx\n",
+ sdev_printk(KERN_INFO, cmd->device, "resetting device. lun 0x%llx\n",
(((u64) lun) << 48));
wait_for_completion(&evt->comp);
@@ -1203,7 +1203,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
if (rsp_rc) {
if (printk_ratelimit())
sdev_printk(KERN_WARNING, cmd->device,
- "reset code %d for task tag 0x%lx\n",
+ "reset code %d for task tag 0x%llx\n",
rsp_rc, tsk_mgmt->task_tag);
return FAILED;
}
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 1889a63..0d934bf 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2839,6 +2839,8 @@ int __init early_serial_setup(struct uart_port *port)
p->flags = port->flags;
p->mapbase = port->mapbase;
p->private_data = port->private_data;
+ p->type = port->type;
+ p->line = port->line;
set_io_from_upio(p);
if (port->serial_in)
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index c088146..2a36712 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -602,6 +602,10 @@ static int pci_netmos_init(struct pci_dev *dev)
/* subdevice 0x00PS means <P> parallel, <S> serial */
unsigned int num_serial = dev->subsystem_device & 0xf;
+ if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
+ dev->subsystem_device == 0x0299)
+ return 0;
+
if (num_serial == 0)
return -ENODEV;
return num_serial;
@@ -3096,6 +3100,10 @@ static struct pci_device_id serial_pci_tbl[] = {
0,
pbn_b0_8_115200 },
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
+ PCI_VENDOR_ID_IBM, 0x0299,
+ 0, 0, pbn_b0_bt_2_115200 },
+
/*
* These entries match devices with class COMMUNICATION_SERIAL,
* COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c
index fde7f9c..bbcfc26 100644
--- a/drivers/serial/8250_pnp.c
+++ b/drivers/serial/8250_pnp.c
@@ -270,6 +270,8 @@ static const struct pnp_device_id pnp_dev_table[] = {
{ "RSS0250", 0 },
/* SupraExpress 28.8 Data/Fax PnP modem */
{ "SUP1310", 0 },
+ /* SupraExpress 336i PnP Voice Modem */
+ { "SUP1381", 0 },
/* SupraExpress 33.6 Data/Fax PnP modem */
{ "SUP1421", 0 },
/* SupraExpress 33.6 Data/Fax PnP modem */
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index d5efd6c..89362d7 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -579,7 +579,7 @@ static void atmel_tx_dma(struct uart_port *port)
/* disable PDC transmit */
UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
- if (!uart_circ_empty(xmit)) {
+ if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) {
dma_sync_single_for_device(port->dev,
pdc->dma_addr,
pdc->dma_size,
diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c
index b7584ca..e6390d0 100644
--- a/drivers/serial/jsm/jsm_neo.c
+++ b/drivers/serial/jsm/jsm_neo.c
@@ -577,9 +577,6 @@ static void neo_parse_modem(struct jsm_channel *ch, u8 signals)
jsm_printk(MSIGS, INFO, &ch->ch_bd->pci_dev,
"neo_parse_modem: port: %d msignals: %x\n", ch->ch_portnum, msignals);
- if (!ch)
- return;
-
/* Scrub off lower bits. They signify delta's, which I don't care about */
/* Keep DDCD and DDSR though */
msignals &= 0xf8;
diff --git a/drivers/serial/pnx8xxx_uart.c b/drivers/serial/pnx8xxx_uart.c
index 22e30d2..1bb8f1b 100644
--- a/drivers/serial/pnx8xxx_uart.c
+++ b/drivers/serial/pnx8xxx_uart.c
@@ -187,7 +187,7 @@ static void pnx8xxx_rx_chars(struct pnx8xxx_port *sport)
status = FIFO_TO_SM(serial_in(sport, PNX8XXX_FIFO)) |
ISTAT_TO_SM(serial_in(sport, PNX8XXX_ISTAT));
while (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFIFO)) {
- ch = serial_in(sport, PNX8XXX_FIFO);
+ ch = serial_in(sport, PNX8XXX_FIFO) & 0xff;
sport->port.icount.rx++;
@@ -198,9 +198,16 @@ static void pnx8xxx_rx_chars(struct pnx8xxx_port *sport)
* out of the main execution path
*/
if (status & (FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE |
- PNX8XXX_UART_FIFO_RXPAR) |
+ PNX8XXX_UART_FIFO_RXPAR |
+ PNX8XXX_UART_FIFO_RXBRK) |
ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN))) {
- if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR))
+ if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXBRK)) {
+ status &= ~(FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE) |
+ FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR));
+ sport->port.icount.brk++;
+ if (uart_handle_break(&sport->port))
+ goto ignore_char;
+ } else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR))
sport->port.icount.parity++;
else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE))
sport->port.icount.frame++;
@@ -284,14 +291,8 @@ static irqreturn_t pnx8xxx_int(int irq, void *dev_id)
/* Get the interrupts */
status = serial_in(sport, PNX8XXX_ISTAT) & serial_in(sport, PNX8XXX_IEN);
- /* Break signal received */
- if (status & PNX8XXX_UART_INT_BREAK) {
- sport->port.icount.brk++;
- uart_handle_break(&sport->port);
- }
-
- /* Byte received */
- if (status & PNX8XXX_UART_INT_RX)
+ /* Byte or break signal received */
+ if (status & (PNX8XXX_UART_INT_RX | PNX8XXX_UART_INT_BREAK))
pnx8xxx_rx_chars(sport);
/* TX holding register empty - transmit a byte */
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index 5e39bac..56ff3e6 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -670,8 +670,7 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
dev_dbg(controller, "new message %p submitted for %s\n",
msg, spi->dev.bus_id);
- if (unlikely(list_empty(&msg->transfers)
- || !spi->max_speed_hz))
+ if (unlikely(list_empty(&msg->transfers)))
return -EINVAL;
if (as->stopping)
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
index 68d6f49..fe7e5f3 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/xilinx_spi.c
@@ -15,12 +15,15 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
+
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/of_spi.h>
+
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/io.h>
-#include <syslib/virtex_devices.h>
-
#define XILINX_SPI_NAME "xilinx_spi"
/* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e)
@@ -144,23 +147,14 @@ static int xilinx_spi_setup_transfer(struct spi_device *spi,
struct spi_transfer *t)
{
u8 bits_per_word;
- u32 hz;
- struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
- hz = (t) ? t->speed_hz : spi->max_speed_hz;
if (bits_per_word != 8) {
dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
__func__, bits_per_word);
return -EINVAL;
}
- if (hz && xspi->speed_hz > hz) {
- dev_err(&spi->dev, "%s, unsupported clock rate %uHz\n",
- __func__, hz);
- return -EINVAL;
- }
-
return 0;
}
@@ -304,32 +298,38 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int __init xilinx_spi_probe(struct platform_device *dev)
+static int __init xilinx_spi_of_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
{
- int ret = 0;
struct spi_master *master;
struct xilinx_spi *xspi;
- struct xspi_platform_data *pdata;
- struct resource *r;
+ struct resource r_irq_struct;
+ struct resource r_mem_struct;
+
+ struct resource *r_irq = &r_irq_struct;
+ struct resource *r_mem = &r_mem_struct;
+ int rc = 0;
+ const u32 *prop;
+ int len;
/* Get resources(memory, IRQ) associated with the device */
- master = spi_alloc_master(&dev->dev, sizeof(struct xilinx_spi));
+ master = spi_alloc_master(&ofdev->dev, sizeof(struct xilinx_spi));
if (master == NULL) {
return -ENOMEM;
}
- platform_set_drvdata(dev, master);
- pdata = dev->dev.platform_data;
+ dev_set_drvdata(&ofdev->dev, master);
- if (pdata == NULL) {
- ret = -ENODEV;
+ rc = of_address_to_resource(ofdev->node, 0, r_mem);
+ if (rc) {
+ dev_warn(&ofdev->dev, "invalid address\n");
goto put_master;
}
- r = platform_get_resource(dev, IORESOURCE_MEM, 0);
- if (r == NULL) {
- ret = -ENODEV;
+ rc = of_irq_to_resource(ofdev->node, 0, r_irq);
+ if (rc == NO_IRQ) {
+ dev_warn(&ofdev->dev, "no IRQ found\n");
goto put_master;
}
@@ -341,47 +341,57 @@ static int __init xilinx_spi_probe(struct platform_device *dev)
xspi->bitbang.master->setup = xilinx_spi_setup;
init_completion(&xspi->done);
- if (!request_mem_region(r->start,
- r->end - r->start + 1, XILINX_SPI_NAME)) {
- ret = -ENXIO;
+ xspi->irq = r_irq->start;
+
+ if (!request_mem_region(r_mem->start,
+ r_mem->end - r_mem->start + 1, XILINX_SPI_NAME)) {
+ rc = -ENXIO;
+ dev_warn(&ofdev->dev, "memory request failure\n");
goto put_master;
}
- xspi->regs = ioremap(r->start, r->end - r->start + 1);
+ xspi->regs = ioremap(r_mem->start, r_mem->end - r_mem->start + 1);
if (xspi->regs == NULL) {
- ret = -ENOMEM;
+ rc = -ENOMEM;
+ dev_warn(&ofdev->dev, "ioremap failure\n");
goto put_master;
}
+ xspi->irq = r_irq->start;
- ret = platform_get_irq(dev, 0);
- if (ret < 0) {
- ret = -ENXIO;
- goto unmap_io;
- }
- xspi->irq = ret;
+ /* dynamic bus assignment */
+ master->bus_num = -1;
- master->bus_num = pdata->bus_num;
- master->num_chipselect = pdata->num_chipselect;
- xspi->speed_hz = pdata->speed_hz;
+ /* number of slave select bits is required */
+ prop = of_get_property(ofdev->node, "xlnx,num-ss-bits", &len);
+ if (!prop || len < sizeof(*prop)) {
+ dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n");
+ goto put_master;
+ }
+ master->num_chipselect = *prop;
/* SPI controller initializations */
xspi_init_hw(xspi->regs);
/* Register for SPI Interrupt */
- ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi);
- if (ret != 0)
+ rc = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi);
+ if (rc != 0) {
+ dev_warn(&ofdev->dev, "irq request failure: %d\n", xspi->irq);
goto unmap_io;
+ }
- ret = spi_bitbang_start(&xspi->bitbang);
- if (ret != 0) {
- dev_err(&dev->dev, "spi_bitbang_start FAILED\n");
+ rc = spi_bitbang_start(&xspi->bitbang);
+ if (rc != 0) {
+ dev_err(&ofdev->dev, "spi_bitbang_start FAILED\n");
goto free_irq;
}
- dev_info(&dev->dev, "at 0x%08X mapped to 0x%08X, irq=%d\n",
- r->start, (u32)xspi->regs, xspi->irq);
+ dev_info(&ofdev->dev, "at 0x%08X mapped to 0x%08X, irq=%d\n",
+ (unsigned int)r_mem->start, (u32)xspi->regs, xspi->irq);
- return ret;
+ /* Add any subnodes on the SPI bus */
+ of_register_spi_devices(master, ofdev->node);
+
+ return rc;
free_irq:
free_irq(xspi->irq, xspi);
@@ -389,21 +399,21 @@ unmap_io:
iounmap(xspi->regs);
put_master:
spi_master_put(master);
- return ret;
+ return rc;
}
-static int __devexit xilinx_spi_remove(struct platform_device *dev)
+static int __devexit xilinx_spi_remove(struct of_device *ofdev)
{
struct xilinx_spi *xspi;
struct spi_master *master;
- master = platform_get_drvdata(dev);
+ master = platform_get_drvdata(ofdev);
xspi = spi_master_get_devdata(master);
spi_bitbang_stop(&xspi->bitbang);
free_irq(xspi->irq, xspi);
iounmap(xspi->regs);
- platform_set_drvdata(dev, 0);
+ dev_set_drvdata(&ofdev->dev, 0);
spi_master_put(xspi->bitbang.master);
return 0;
@@ -412,27 +422,42 @@ static int __devexit xilinx_spi_remove(struct platform_device *dev)
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:" XILINX_SPI_NAME);
-static struct platform_driver xilinx_spi_driver = {
- .probe = xilinx_spi_probe,
- .remove = __devexit_p(xilinx_spi_remove),
+static int __exit xilinx_spi_of_remove(struct of_device *op)
+{
+ return xilinx_spi_remove(op);
+}
+
+static struct of_device_id xilinx_spi_of_match[] = {
+ { .compatible = "xlnx,xps-spi-2.00.a", },
+ { .compatible = "xlnx,xps-spi-2.00.b", },
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
+
+static struct of_platform_driver xilinx_spi_of_driver = {
+ .owner = THIS_MODULE,
+ .name = "xilinx-xps-spi",
+ .match_table = xilinx_spi_of_match,
+ .probe = xilinx_spi_of_probe,
+ .remove = __exit_p(xilinx_spi_of_remove),
.driver = {
- .name = XILINX_SPI_NAME,
+ .name = "xilinx-xps-spi",
.owner = THIS_MODULE,
},
};
static int __init xilinx_spi_init(void)
{
- return platform_driver_register(&xilinx_spi_driver);
+ return of_register_platform_driver(&xilinx_spi_of_driver);
}
module_init(xilinx_spi_init);
static void __exit xilinx_spi_exit(void)
{
- platform_driver_unregister(&xilinx_spi_driver);
+ of_unregister_platform_driver(&xilinx_spi_of_driver);
}
module_exit(xilinx_spi_exit);
-
MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
MODULE_DESCRIPTION("Xilinx SPI driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index d5d0e40..94d5ee2 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1554,7 +1554,7 @@ static int usb_configure_device_otg(struct usb_device *udev)
* (Includes HNP test device.)
*/
if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
- err = usb_port_suspend(udev);
+ err = usb_port_suspend(udev, PMSG_SUSPEND);
if (err < 0)
dev_dbg(&udev->dev, "HNP fail, %d\n", err);
}
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index ef6cfa5..c70a8f6 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -2030,7 +2030,7 @@ static void ftdi_process_read(struct work_struct *work)
spin_unlock_irqrestore(&priv->rx_lock, flags);
dbg("%s - deferring remainder until unthrottled",
__func__);
- return;
+ goto out;
}
spin_unlock_irqrestore(&priv->rx_lock, flags);
/* if the port is closed stop trying to read */
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 01d0c70..3cf41df 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -145,7 +145,7 @@ static int ti_command_in_sync(struct ti_device *tdev, __u8 command,
static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
__u8 mask, __u8 byte);
-static int ti_download_firmware(struct ti_device *tdev, int type);
+static int ti_download_firmware(struct ti_device *tdev);
/* circular buffer */
static struct circ_buf *ti_buf_alloc(void);
@@ -176,9 +176,14 @@ static unsigned int product_5052_count;
/* the array dimension is the number of default entries plus */
/* TI_EXTRA_VID_PID_COUNT user defined entries plus 1 terminating */
/* null entry */
-static struct usb_device_id ti_id_table_3410[1+TI_EXTRA_VID_PID_COUNT+1] = {
+static struct usb_device_id ti_id_table_3410[7+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
+ { USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) },
+ { USB_DEVICE(MTS_VENDOR_ID, MTS_CDMA_NO_FW_PRODUCT_ID) },
+ { USB_DEVICE(MTS_VENDOR_ID, MTS_CDMA_PRODUCT_ID) },
+ { USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_PRODUCT_ID) },
+ { USB_DEVICE(MTS_VENDOR_ID, MTS_EDGE_PRODUCT_ID) },
};
static struct usb_device_id ti_id_table_5052[4+TI_EXTRA_VID_PID_COUNT+1] = {
@@ -188,9 +193,14 @@ static struct usb_device_id ti_id_table_5052[4+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) },
};
-static struct usb_device_id ti_id_table_combined[] = {
+static struct usb_device_id ti_id_table_combined[6+2*TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
+ { USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) },
+ { USB_DEVICE(MTS_VENDOR_ID, MTS_CDMA_NO_FW_PRODUCT_ID) },
+ { USB_DEVICE(MTS_VENDOR_ID, MTS_CDMA_PRODUCT_ID) },
+ { USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_PRODUCT_ID) },
+ { USB_DEVICE(MTS_VENDOR_ID, MTS_EDGE_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_BOOT_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) },
@@ -272,6 +282,9 @@ MODULE_LICENSE("GPL");
MODULE_FIRMWARE("ti_3410.fw");
MODULE_FIRMWARE("ti_5052.fw");
+MODULE_FIRMWARE("mts_cdma.fw");
+MODULE_FIRMWARE("mts_gsm.fw");
+MODULE_FIRMWARE("mts_edge.fw");
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Enable debugging, 0=no, 1=yes");
@@ -304,21 +317,28 @@ MODULE_DEVICE_TABLE(usb, ti_id_table_combined);
static int __init ti_init(void)
{
- int i, j;
+ int i, j, c;
int ret;
/* insert extra vendor and product ids */
+ c = ARRAY_SIZE(ti_id_table_combined) - 2 * TI_EXTRA_VID_PID_COUNT - 1;
j = ARRAY_SIZE(ti_id_table_3410) - TI_EXTRA_VID_PID_COUNT - 1;
- for (i = 0; i < min(vendor_3410_count, product_3410_count); i++, j++) {
+ for (i = 0; i < min(vendor_3410_count, product_3410_count); i++, j++, c++) {
ti_id_table_3410[j].idVendor = vendor_3410[i];
ti_id_table_3410[j].idProduct = product_3410[i];
ti_id_table_3410[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
+ ti_id_table_combined[c].idVendor = vendor_3410[i];
+ ti_id_table_combined[c].idProduct = product_3410[i];
+ ti_id_table_combined[c].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
}
j = ARRAY_SIZE(ti_id_table_5052) - TI_EXTRA_VID_PID_COUNT - 1;
- for (i = 0; i < min(vendor_5052_count, product_5052_count); i++, j++) {
+ for (i = 0; i < min(vendor_5052_count, product_5052_count); i++, j++, c++) {
ti_id_table_5052[j].idVendor = vendor_5052[i];
ti_id_table_5052[j].idProduct = product_5052[i];
ti_id_table_5052[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
+ ti_id_table_combined[c].idVendor = vendor_5052[i];
+ ti_id_table_combined[c].idProduct = product_5052[i];
+ ti_id_table_combined[c].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
}
ret = usb_serial_register(&ti_1port_device);
@@ -390,11 +410,7 @@ static int ti_startup(struct usb_serial *serial)
/* if we have only 1 configuration, download firmware */
if (dev->descriptor.bNumConfigurations == 1) {
- if (tdev->td_is_3410)
- status = ti_download_firmware(tdev, 3410);
- else
- status = ti_download_firmware(tdev, 5052);
- if (status)
+ if ((status = ti_download_firmware(tdev)) != 0)
goto free_tdev;
/* 3410 must be reset, 5052 resets itself */
@@ -1671,9 +1687,9 @@ static int ti_do_download(struct usb_device *dev, int pipe,
return status;
}
-static int ti_download_firmware(struct ti_device *tdev, int type)
+static int ti_download_firmware(struct ti_device *tdev)
{
- int status = -ENOMEM;
+ int status;
int buffer_size;
__u8 *buffer;
struct usb_device *dev = tdev->td_serial->dev;
@@ -1681,9 +1697,34 @@ static int ti_download_firmware(struct ti_device *tdev, int type)
tdev->td_serial->port[0]->bulk_out_endpointAddress);
const struct firmware *fw_p;
char buf[32];
- sprintf(buf, "ti_usb-%d.bin", type);
- if (request_firmware(&fw_p, buf, &dev->dev)) {
+ /* try ID specific firmware first, then try generic firmware */
+ sprintf(buf, "ti_usb-v%04x-p%04x.fw", dev->descriptor.idVendor,
+ dev->descriptor.idProduct);
+ if ((status = request_firmware(&fw_p, buf, &dev->dev)) != 0) {
+ buf[0] = '\0';
+ if (dev->descriptor.idVendor == MTS_VENDOR_ID) {
+ switch (dev->descriptor.idProduct) {
+ case MTS_CDMA_PRODUCT_ID:
+ strcpy(buf, "mts_cdma.fw");
+ break;
+ case MTS_GSM_PRODUCT_ID:
+ strcpy(buf, "mts_gsm.fw");
+ break;
+ case MTS_EDGE_PRODUCT_ID:
+ strcpy(buf, "mts_edge.fw");
+ break;
+ }
+ }
+ if (buf[0] == '\0') {
+ if (tdev->td_is_3410)
+ strcpy(buf, "ti_3410.fw");
+ else
+ strcpy(buf, "ti_5052.fw");
+ }
+ status = request_firmware(&fw_p, buf, &dev->dev);
+ }
+ if (status) {
dev_err(&dev->dev, "%s - firmware not found\n", __func__);
return -ENOENT;
}
@@ -1699,6 +1740,8 @@ static int ti_download_firmware(struct ti_device *tdev, int type)
memset(buffer + fw_p->size, 0xff, buffer_size - fw_p->size);
status = ti_do_download(dev, pipe, buffer, fw_p->size);
kfree(buffer);
+ } else {
+ status = -ENOMEM;
}
release_firmware(fw_p);
if (status) {
diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h
index b5541bf..7e4752f 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.h
+++ b/drivers/usb/serial/ti_usb_3410_5052.h
@@ -34,6 +34,14 @@
#define TI_5052_EEPROM_PRODUCT_ID 0x505A /* EEPROM, no firmware */
#define TI_5052_FIRMWARE_PRODUCT_ID 0x505F /* firmware is running */
+/* Multi-Tech vendor and product ids */
+#define MTS_VENDOR_ID 0x06E0
+#define MTS_GSM_NO_FW_PRODUCT_ID 0xF108
+#define MTS_CDMA_NO_FW_PRODUCT_ID 0xF109
+#define MTS_CDMA_PRODUCT_ID 0xF110
+#define MTS_GSM_PRODUCT_ID 0xF111
+#define MTS_EDGE_PRODUCT_ID 0xF112
+
/* Commands */
#define TI_GET_VERSION 0x01
#define TI_GET_PORT_STATUS 0x02
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 080ade2..cfcfd5a 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -511,9 +511,6 @@ static void usb_serial_port_work(struct work_struct *work)
dbg("%s - port %d", __func__, port->number);
- if (!port)
- return;
-
tty = tty_port_tty_get(&port->port);
if (!tty)
return;
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index e39e33e..be2b657 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -28,7 +28,7 @@ obj-$(CONFIG_FB_DDC) += fb_ddc.o
obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o
# Hardware specific drivers go first
-obj-$(CONFIG_FB_AMIGA) += amifb.o c2p.o
+obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o
obj-$(CONFIG_FB_ARC) += arcfb.o
obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o
obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
@@ -72,7 +72,7 @@ obj-$(CONFIG_FB_TCX) += tcx.o sbuslib.o
obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o
obj-$(CONFIG_FB_SGIVW) += sgivwfb.o
obj-$(CONFIG_FB_ACORN) += acornfb.o
-obj-$(CONFIG_FB_ATARI) += atafb.o c2p.o atafb_mfb.o \
+obj-$(CONFIG_FB_ATARI) += atafb.o c2p_iplan2.o atafb_mfb.o \
atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o
obj-$(CONFIG_FB_MAC) += macfb.o
obj-$(CONFIG_FB_HECUBA) += hecubafb.o
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index b8e9a86..100f236 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -2159,9 +2159,9 @@ static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
src += pitch;
}
} else {
- c2p(info->screen_base, image->data, dx, dy, width, height,
- par->next_line, par->next_plane, image->width,
- info->var.bits_per_pixel);
+ c2p_planar(info->screen_base, image->data, dx, dy, width,
+ height, par->next_line, par->next_plane,
+ image->width, info->var.bits_per_pixel);
}
}
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index 77eb8b3..8058572 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -122,7 +122,6 @@ static struct atafb_par {
void *screen_base;
int yres_virtual;
u_long next_line;
- u_long next_plane;
#if defined ATAFB_TT || defined ATAFB_STE
union {
struct {
@@ -149,6 +148,7 @@ static struct atafb_par {
short mono;
short ste_mode;
short bpp;
+ u32 pseudo_palette[16];
} falcon;
#endif
/* Nothing needed for external mode */
@@ -614,7 +614,7 @@ static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
fix->xpanstep = 0;
fix->ypanstep = 1;
fix->ywrapstep = 0;
- fix->line_length = 0;
+ fix->line_length = par->next_line;
fix->accel = FB_ACCEL_ATARIBLITT;
return 0;
}
@@ -691,6 +691,7 @@ static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
return -EINVAL;
par->yres_virtual = yres_virtual;
par->screen_base = screen_base + var->yoffset * linelen;
+ par->next_line = linelen;
return 0;
}
@@ -884,10 +885,6 @@ static int vdl_prescale[4][3] = {
/* Default hsync timing [mon_type] in picoseconds */
static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 };
-#ifdef FBCON_HAS_CFB16
-static u16 fbcon_cfb16_cmap[16];
-#endif
-
static inline int hxx_prescale(struct falcon_hw *hw)
{
return hw->ste_mode ? 16
@@ -918,7 +915,7 @@ static int falcon_encode_fix(struct fb_fix_screeninfo *fix,
fix->visual = FB_VISUAL_TRUECOLOR;
fix->xpanstep = 2;
}
- fix->line_length = 0;
+ fix->line_length = par->next_line;
fix->accel = FB_ACCEL_ATARIBLITT;
return 0;
}
@@ -1394,14 +1391,7 @@ set_screen_base:
par->screen_base = screen_base + var->yoffset * linelen;
par->hw.falcon.xoffset = 0;
- // FIXME!!! sort of works, no crash
- //par->next_line = linelen;
- //par->next_plane = yres_virtual * linelen;
par->next_line = linelen;
- par->next_plane = 2;
- // crashes
- //par->next_plane = linelen;
- //par->next_line = yres_virtual * linelen;
return 0;
}
@@ -1735,10 +1725,10 @@ static int falcon_setcolreg(unsigned int regno, unsigned int red,
(((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
(((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
-#ifdef FBCON_HAS_CFB16
- fbcon_cfb16_cmap[regno] = ((red & 0xf800) |
- ((green & 0xfc00) >> 5) |
- ((blue & 0xf800) >> 11));
+#ifdef ATAFB_FALCON
+ ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) |
+ ((green & 0xfc00) >> 5) |
+ ((blue & 0xf800) >> 11));
#endif
}
return 0;
@@ -1852,7 +1842,7 @@ static int stste_encode_fix(struct fb_fix_screeninfo *fix,
fix->ypanstep = 0;
}
fix->ywrapstep = 0;
- fix->line_length = 0;
+ fix->line_length = par->next_line;
fix->accel = FB_ACCEL_ATARIBLITT;
return 0;
}
@@ -1910,6 +1900,7 @@ static int stste_decode_var(struct fb_var_screeninfo *var,
return -EINVAL;
par->yres_virtual = yres_virtual;
par->screen_base = screen_base + var->yoffset * linelen;
+ par->next_line = linelen;
return 0;
}
@@ -2169,7 +2160,7 @@ static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
fix->xpanstep = 0;
fix->ypanstep = 0;
fix->ywrapstep = 0;
- fix->line_length = 0;
+ fix->line_length = par->next_line;
return 0;
}
@@ -2184,6 +2175,8 @@ static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
var->xoffset > 0 ||
var->yoffset > 0)
return -EINVAL;
+
+ par->next_line = external_xres_virtual * external_depth / 8;
return 0;
}
@@ -2443,42 +2436,6 @@ static void atafb_set_disp(struct fb_info *info)
atafb_get_fix(&info->fix, info);
info->screen_base = (void *)info->fix.smem_start;
-
- switch (info->fix.type) {
- case FB_TYPE_INTERLEAVED_PLANES:
- switch (info->var.bits_per_pixel) {
- case 2:
- // display->dispsw = &fbcon_iplan2p2;
- break;
- case 4:
- // display->dispsw = &fbcon_iplan2p4;
- break;
- case 8:
- // display->dispsw = &fbcon_iplan2p8;
- break;
- }
- break;
- case FB_TYPE_PACKED_PIXELS:
- switch (info->var.bits_per_pixel) {
-#ifdef FBCON_HAS_MFB
- case 1:
- // display->dispsw = &fbcon_mfb;
- break;
-#endif
-#ifdef FBCON_HAS_CFB8
- case 8:
- // display->dispsw = &fbcon_cfb8;
- break;
-#endif
-#ifdef FBCON_HAS_CFB16
- case 16:
- // display->dispsw = &fbcon_cfb16;
- // display->dispsw_data = fbcon_cfb16_cmap;
- break;
-#endif
- }
- break;
- }
}
static int atafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
@@ -2549,6 +2506,13 @@ static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
if (!rect->width || !rect->height)
return;
+#ifdef ATAFB_FALCON
+ if (info->var.bits_per_pixel == 16) {
+ cfb_fillrect(info, rect);
+ return;
+ }
+#endif
+
/*
* We could use hardware clipping but on many cards you get around
* hardware clipping by writing to framebuffer directly.
@@ -2583,6 +2547,13 @@ static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
u32 dx, dy, sx, sy, width, height;
int rev_copy = 0;
+#ifdef ATAFB_FALCON
+ if (info->var.bits_per_pixel == 16) {
+ cfb_copyarea(info, area);
+ return;
+ }
+#endif
+
/* clip the destination */
x2 = area->dx + area->width;
y2 = area->dy + area->height;
@@ -2632,6 +2603,13 @@ static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
const char *src;
u32 dx, dy, width, height, pitch;
+#ifdef ATAFB_FALCON
+ if (info->var.bits_per_pixel == 16) {
+ cfb_imageblit(info, image);
+ return;
+ }
+#endif
+
/*
* We could use hardware clipping but on many cards you get around
* hardware clipping by writing to framebuffer directly like we are
@@ -2676,10 +2654,9 @@ static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
src += pitch;
}
} else {
- // only used for logo; broken
- c2p(info->screen_base, image->data, dx, dy, width, height,
- par->next_line, par->next_plane, image->width,
- info->var.bits_per_pixel);
+ c2p_iplan2(info->screen_base, image->data, dx, dy, width,
+ height, par->next_line, image->width,
+ info->var.bits_per_pixel);
}
}
@@ -3098,8 +3075,7 @@ int __init atafb_setup(char *options)
int __init atafb_init(void)
{
- int pad;
- int detected_mode;
+ int pad, detected_mode, error;
unsigned int defmode = 0;
unsigned long mem_req;
@@ -3139,8 +3115,12 @@ int __init atafb_init(void)
printk("atafb_init: initializing Falcon hw\n");
fbhw = &falcon_switch;
atafb_ops.fb_setcolreg = &falcon_setcolreg;
- request_irq(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO,
- "framebuffer/modeswitch", falcon_vbl_switcher);
+ error = request_irq(IRQ_AUTO_4, falcon_vbl_switcher,
+ IRQ_TYPE_PRIO,
+ "framebuffer/modeswitch",
+ falcon_vbl_switcher);
+ if (error)
+ return error;
defmode = DEFMODE_F30;
break;
}
@@ -3225,6 +3205,10 @@ int __init atafb_init(void)
// tries to read from HW which may not be initialized yet
// so set sane var first, then call atafb_set_par
atafb_get_var(&fb_info.var, &fb_info);
+
+#ifdef ATAFB_FALCON
+ fb_info.pseudo_palette = current_par.hw.falcon.pseudo_palette;
+#endif
fb_info.flags = FBINFO_FLAG_DEFAULT;
if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb,
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
index 7644ed2..37e60b1 100644
--- a/drivers/video/bf54x-lq043fb.c
+++ b/drivers/video/bf54x-lq043fb.c
@@ -335,7 +335,20 @@ static int bfin_bf54x_fb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- if (var->bits_per_pixel != LCD_BPP) {
+ switch (var->bits_per_pixel) {
+ case 24:/* TRUECOLOUR, 16m */
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length = 8;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ var->transp.msb_right = 0;
+ var->red.msb_right = 0;
+ var->green.msb_right = 0;
+ var->blue.msb_right = 0;
+ break;
+ default:
pr_debug("%s: depth not supported: %u BPP\n", __func__,
var->bits_per_pixel);
return -EINVAL;
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c
index a9b3ada..2a423d3 100644
--- a/drivers/video/bfin-t350mcqb-fb.c
+++ b/drivers/video/bfin-t350mcqb-fb.c
@@ -254,7 +254,20 @@ static int bfin_t350mcqb_fb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- if (var->bits_per_pixel != LCD_BPP) {
+ switch (var->bits_per_pixel) {
+ case 24:/* TRUECOLOUR, 16m */
+ var->red.offset = 0;
+ var->green.offset = 8;
+ var->blue.offset = 16;
+ var->red.length = var->green.length = var->blue.length = 8;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ var->transp.msb_right = 0;
+ var->red.msb_right = 0;
+ var->green.msb_right = 0;
+ var->blue.msb_right = 0;
+ break;
+ default:
pr_debug("%s: depth not supported: %u BPP\n", __func__,
var->bits_per_pixel);
return -EINVAL;
diff --git a/drivers/video/c2p.c b/drivers/video/c2p.c
deleted file mode 100644
index 376bc07..0000000
--- a/drivers/video/c2p.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Fast C2P (Chunky-to-Planar) Conversion
- *
- * Copyright (C) 2003 Geert Uytterhoeven
- *
- * NOTES:
- * - This code was inspired by Scout's C2P tutorial
- * - It assumes to run on a big endian system
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include "c2p.h"
-
-
- /*
- * Basic transpose step
- */
-
-#define _transp(d, i1, i2, shift, mask) \
- do { \
- u32 t = (d[i1] ^ (d[i2] >> shift)) & mask; \
- d[i1] ^= t; \
- d[i2] ^= t << shift; \
- } while (0)
-
-static inline u32 get_mask(int n)
-{
- switch (n) {
- case 1:
- return 0x55555555;
- break;
-
- case 2:
- return 0x33333333;
- break;
-
- case 4:
- return 0x0f0f0f0f;
- break;
-
- case 8:
- return 0x00ff00ff;
- break;
-
- case 16:
- return 0x0000ffff;
- break;
- }
- return 0;
-}
-
-#define transp_nx1(d, n) \
- do { \
- u32 mask = get_mask(n); \
- /* First block */ \
- _transp(d, 0, 1, n, mask); \
- /* Second block */ \
- _transp(d, 2, 3, n, mask); \
- /* Third block */ \
- _transp(d, 4, 5, n, mask); \
- /* Fourth block */ \
- _transp(d, 6, 7, n, mask); \
- } while (0)
-
-#define transp_nx2(d, n) \
- do { \
- u32 mask = get_mask(n); \
- /* First block */ \
- _transp(d, 0, 2, n, mask); \
- _transp(d, 1, 3, n, mask); \
- /* Second block */ \
- _transp(d, 4, 6, n, mask); \
- _transp(d, 5, 7, n, mask); \
- } while (0)
-
-#define transp_nx4(d, n) \
- do { \
- u32 mask = get_mask(n); \
- _transp(d, 0, 4, n, mask); \
- _transp(d, 1, 5, n, mask); \
- _transp(d, 2, 6, n, mask); \
- _transp(d, 3, 7, n, mask); \
- } while (0)
-
-#define transp(d, n, m) transp_nx ## m(d, n)
-
-
- /*
- * Perform a full C2P step on 32 8-bit pixels, stored in 8 32-bit words
- * containing
- * - 32 8-bit chunky pixels on input
- * - permuted planar data on output
- */
-
-static void c2p_8bpp(u32 d[8])
-{
- transp(d, 16, 4);
- transp(d, 8, 2);
- transp(d, 4, 1);
- transp(d, 2, 4);
- transp(d, 1, 2);
-}
-
-
- /*
- * Array containing the permution indices of the planar data after c2p
- */
-
-static const int perm_c2p_8bpp[8] = { 7, 5, 3, 1, 6, 4, 2, 0 };
-
-
- /*
- * Compose two values, using a bitmask as decision value
- * This is equivalent to (a & mask) | (b & ~mask)
- */
-
-static inline unsigned long comp(unsigned long a, unsigned long b,
- unsigned long mask)
-{
- return ((a ^ b) & mask) ^ b;
-}
-
-
- /*
- * Store a full block of planar data after c2p conversion
- */
-
-static inline void store_planar(char *dst, u32 dst_inc, u32 bpp, u32 d[8])
-{
- int i;
-
- for (i = 0; i < bpp; i++, dst += dst_inc)
- *(u32 *)dst = d[perm_c2p_8bpp[i]];
-}
-
-
- /*
- * Store a partial block of planar data after c2p conversion
- */
-
-static inline void store_planar_masked(char *dst, u32 dst_inc, u32 bpp,
- u32 d[8], u32 mask)
-{
- int i;
-
- for (i = 0; i < bpp; i++, dst += dst_inc)
- *(u32 *)dst = comp(d[perm_c2p_8bpp[i]], *(u32 *)dst, mask);
-}
-
-
- /*
- * c2p - Copy 8-bit chunky image data to a planar frame buffer
- * @dst: Starting address of the planar frame buffer
- * @dx: Horizontal destination offset (in pixels)
- * @dy: Vertical destination offset (in pixels)
- * @width: Image width (in pixels)
- * @height: Image height (in pixels)
- * @dst_nextline: Frame buffer offset to the next line (in bytes)
- * @dst_nextplane: Frame buffer offset to the next plane (in bytes)
- * @src_nextline: Image offset to the next line (in bytes)
- * @bpp: Bits per pixel of the planar frame buffer (1-8)
- */
-
-void c2p(u8 *dst, const u8 *src, u32 dx, u32 dy, u32 width, u32 height,
- u32 dst_nextline, u32 dst_nextplane, u32 src_nextline, u32 bpp)
-{
- int dst_idx;
- u32 d[8], first, last, w;
- const u8 *c;
- u8 *p;
-
- dst += dy*dst_nextline+(dx & ~31);
- dst_idx = dx % 32;
- first = ~0UL >> dst_idx;
- last = ~(~0UL >> ((dst_idx+width) % 32));
- while (height--) {
- c = src;
- p = dst;
- w = width;
- if (dst_idx+width <= 32) {
- /* Single destination word */
- first &= last;
- memset(d, 0, sizeof(d));
- memcpy((u8 *)d+dst_idx, c, width);
- c += width;
- c2p_8bpp(d);
- store_planar_masked(p, dst_nextplane, bpp, d, first);
- p += 4;
- } else {
- /* Multiple destination words */
- w = width;
- /* Leading bits */
- if (dst_idx) {
- w = 32 - dst_idx;
- memset(d, 0, dst_idx);
- memcpy((u8 *)d+dst_idx, c, w);
- c += w;
- c2p_8bpp(d);
- store_planar_masked(p, dst_nextplane, bpp, d, first);
- p += 4;
- w = width-w;
- }
- /* Main chunk */
- while (w >= 32) {
- memcpy(d, c, 32);
- c += 32;
- c2p_8bpp(d);
- store_planar(p, dst_nextplane, bpp, d);
- p += 4;
- w -= 32;
- }
- /* Trailing bits */
- w %= 32;
- if (w > 0) {
- memcpy(d, c, w);
- memset((u8 *)d+w, 0, 32-w);
- c2p_8bpp(d);
- store_planar_masked(p, dst_nextplane, bpp, d, last);
- }
- }
- src += src_nextline;
- dst += dst_nextline;
- }
-}
-EXPORT_SYMBOL_GPL(c2p);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/c2p.h b/drivers/video/c2p.h
index c77cbf1..6c38d40 100644
--- a/drivers/video/c2p.h
+++ b/drivers/video/c2p.h
@@ -1,7 +1,7 @@
/*
* Fast C2P (Chunky-to-Planar) Conversion
*
- * Copyright (C) 2003 Geert Uytterhoeven
+ * Copyright (C) 2003-2008 Geert Uytterhoeven
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
@@ -10,7 +10,10 @@
#include <linux/types.h>
-extern void c2p(u8 *dst, const u8 *src, u32 dx, u32 dy, u32 width, u32 height,
- u32 dst_nextline, u32 dst_nextplane, u32 src_nextline,
- u32 bpp);
+extern void c2p_planar(void *dst, const void *src, u32 dx, u32 dy, u32 width,
+ u32 height, u32 dst_nextline, u32 dst_nextplane,
+ u32 src_nextline, u32 bpp);
+extern void c2p_iplan2(void *dst, const void *src, u32 dx, u32 dy, u32 width,
+ u32 height, u32 dst_nextline, u32 src_nextline,
+ u32 bpp);
diff --git a/drivers/video/c2p_core.h b/drivers/video/c2p_core.h
new file mode 100644
index 0000000..e1035a8
--- /dev/null
+++ b/drivers/video/c2p_core.h
@@ -0,0 +1,153 @@
+/*
+ * Fast C2P (Chunky-to-Planar) Conversion
+ *
+ * Copyright (C) 2003-2008 Geert Uytterhoeven
+ *
+ * NOTES:
+ * - This code was inspired by Scout's C2P tutorial
+ * - It assumes to run on a big endian system
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+
+ /*
+ * Basic transpose step
+ */
+
+static inline void _transp(u32 d[], unsigned int i1, unsigned int i2,
+ unsigned int shift, u32 mask)
+{
+ u32 t = (d[i1] ^ (d[i2] >> shift)) & mask;
+
+ d[i1] ^= t;
+ d[i2] ^= t << shift;
+}
+
+
+extern void c2p_unsupported(void);
+
+static inline u32 get_mask(unsigned int n)
+{
+ switch (n) {
+ case 1:
+ return 0x55555555;
+
+ case 2:
+ return 0x33333333;
+
+ case 4:
+ return 0x0f0f0f0f;
+
+ case 8:
+ return 0x00ff00ff;
+
+ case 16:
+ return 0x0000ffff;
+ }
+
+ c2p_unsupported();
+ return 0;
+}
+
+
+ /*
+ * Transpose operations on 8 32-bit words
+ */
+
+static inline void transp8(u32 d[], unsigned int n, unsigned int m)
+{
+ u32 mask = get_mask(n);
+
+ switch (m) {
+ case 1:
+ /* First n x 1 block */
+ _transp(d, 0, 1, n, mask);
+ /* Second n x 1 block */
+ _transp(d, 2, 3, n, mask);
+ /* Third n x 1 block */
+ _transp(d, 4, 5, n, mask);
+ /* Fourth n x 1 block */
+ _transp(d, 6, 7, n, mask);
+ return;
+
+ case 2:
+ /* First n x 2 block */
+ _transp(d, 0, 2, n, mask);
+ _transp(d, 1, 3, n, mask);
+ /* Second n x 2 block */
+ _transp(d, 4, 6, n, mask);
+ _transp(d, 5, 7, n, mask);
+ return;
+
+ case 4:
+ /* Single n x 4 block */
+ _transp(d, 0, 4, n, mask);
+ _transp(d, 1, 5, n, mask);
+ _transp(d, 2, 6, n, mask);
+ _transp(d, 3, 7, n, mask);
+ return;
+ }
+
+ c2p_unsupported();
+}
+
+
+ /*
+ * Transpose operations on 4 32-bit words
+ */
+
+static inline void transp4(u32 d[], unsigned int n, unsigned int m)
+{
+ u32 mask = get_mask(n);
+
+ switch (m) {
+ case 1:
+ /* First n x 1 block */
+ _transp(d, 0, 1, n, mask);
+ /* Second n x 1 block */
+ _transp(d, 2, 3, n, mask);
+ return;
+
+ case 2:
+ /* Single n x 2 block */
+ _transp(d, 0, 2, n, mask);
+ _transp(d, 1, 3, n, mask);
+ return;
+ }
+
+ c2p_unsupported();
+}
+
+
+ /*
+ * Transpose operations on 4 32-bit words (reverse order)
+ */
+
+static inline void transp4x(u32 d[], unsigned int n, unsigned int m)
+{
+ u32 mask = get_mask(n);
+
+ switch (m) {
+ case 2:
+ /* Single n x 2 block */
+ _transp(d, 2, 0, n, mask);
+ _transp(d, 3, 1, n, mask);
+ return;
+ }
+
+ c2p_unsupported();
+}
+
+
+ /*
+ * Compose two values, using a bitmask as decision value
+ * This is equivalent to (a & mask) | (b & ~mask)
+ */
+
+static inline u32 comp(u32 a, u32 b, u32 mask)
+{
+ return ((a ^ b) & mask) ^ b;
+}
diff --git a/drivers/video/c2p_iplan2.c b/drivers/video/c2p_iplan2.c
new file mode 100644
index 0000000..19156dc
--- /dev/null
+++ b/drivers/video/c2p_iplan2.c
@@ -0,0 +1,153 @@
+/*
+ * Fast C2P (Chunky-to-Planar) Conversion
+ *
+ * Copyright (C) 2003-2008 Geert Uytterhoeven
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <asm/unaligned.h>
+
+#include "c2p.h"
+#include "c2p_core.h"
+
+
+ /*
+ * Perform a full C2P step on 16 8-bit pixels, stored in 4 32-bit words
+ * containing
+ * - 16 8-bit chunky pixels on input
+ * - permutated planar data (2 planes per 32-bit word) on output
+ */
+
+static void c2p_16x8(u32 d[4])
+{
+ transp4(d, 8, 2);
+ transp4(d, 1, 2);
+ transp4x(d, 16, 2);
+ transp4x(d, 2, 2);
+ transp4(d, 4, 1);
+}
+
+
+ /*
+ * Array containing the permutation indices of the planar data after c2p
+ */
+
+static const int perm_c2p_16x8[4] = { 1, 3, 0, 2 };
+
+
+ /*
+ * Store a full block of iplan2 data after c2p conversion
+ */
+
+static inline void store_iplan2(void *dst, u32 bpp, u32 d[4])
+{
+ int i;
+
+ for (i = 0; i < bpp/2; i++, dst += 4)
+ put_unaligned_be32(d[perm_c2p_16x8[i]], dst);
+}
+
+
+ /*
+ * Store a partial block of iplan2 data after c2p conversion
+ */
+
+static inline void store_iplan2_masked(void *dst, u32 bpp, u32 d[4], u32 mask)
+{
+ int i;
+
+ for (i = 0; i < bpp/2; i++, dst += 4)
+ put_unaligned_be32(comp(d[perm_c2p_16x8[i]],
+ get_unaligned_be32(dst), mask),
+ dst);
+}
+
+
+ /*
+ * c2p_iplan2 - Copy 8-bit chunky image data to an interleaved planar
+ * frame buffer with 2 bytes of interleave
+ * @dst: Starting address of the planar frame buffer
+ * @dx: Horizontal destination offset (in pixels)
+ * @dy: Vertical destination offset (in pixels)
+ * @width: Image width (in pixels)
+ * @height: Image height (in pixels)
+ * @dst_nextline: Frame buffer offset to the next line (in bytes)
+ * @src_nextline: Image offset to the next line (in bytes)
+ * @bpp: Bits per pixel of the planar frame buffer (2, 4, or 8)
+ */
+
+void c2p_iplan2(void *dst, const void *src, u32 dx, u32 dy, u32 width,
+ u32 height, u32 dst_nextline, u32 src_nextline, u32 bpp)
+{
+ union {
+ u8 pixels[16];
+ u32 words[4];
+ } d;
+ u32 dst_idx, first, last, w;
+ const u8 *c;
+ void *p;
+
+ dst += dy*dst_nextline+(dx & ~15)*bpp;
+ dst_idx = dx % 16;
+ first = 0xffffU >> dst_idx;
+ first |= first << 16;
+ last = 0xffffU ^ (0xffffU >> ((dst_idx+width) % 16));
+ last |= last << 16;
+ while (height--) {
+ c = src;
+ p = dst;
+ w = width;
+ if (dst_idx+width <= 16) {
+ /* Single destination word */
+ first &= last;
+ memset(d.pixels, 0, sizeof(d));
+ memcpy(d.pixels+dst_idx, c, width);
+ c += width;
+ c2p_16x8(d.words);
+ store_iplan2_masked(p, bpp, d.words, first);
+ p += bpp*2;
+ } else {
+ /* Multiple destination words */
+ w = width;
+ /* Leading bits */
+ if (dst_idx) {
+ w = 16 - dst_idx;
+ memset(d.pixels, 0, dst_idx);
+ memcpy(d.pixels+dst_idx, c, w);
+ c += w;
+ c2p_16x8(d.words);
+ store_iplan2_masked(p, bpp, d.words, first);
+ p += bpp*2;
+ w = width-w;
+ }
+ /* Main chunk */
+ while (w >= 16) {
+ memcpy(d.pixels, c, 16);
+ c += 16;
+ c2p_16x8(d.words);
+ store_iplan2(p, bpp, d.words);
+ p += bpp*2;
+ w -= 16;
+ }
+ /* Trailing bits */
+ w %= 16;
+ if (w > 0) {
+ memcpy(d.pixels, c, w);
+ memset(d.pixels+w, 0, 16-w);
+ c2p_16x8(d.words);
+ store_iplan2_masked(p, bpp, d.words, last);
+ }
+ }
+ src += src_nextline;
+ dst += dst_nextline;
+ }
+}
+EXPORT_SYMBOL_GPL(c2p_iplan2);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/c2p_planar.c b/drivers/video/c2p_planar.c
new file mode 100644
index 0000000..ec7ac85
--- /dev/null
+++ b/drivers/video/c2p_planar.c
@@ -0,0 +1,156 @@
+/*
+ * Fast C2P (Chunky-to-Planar) Conversion
+ *
+ * Copyright (C) 2003-2008 Geert Uytterhoeven
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <asm/unaligned.h>
+
+#include "c2p.h"
+#include "c2p_core.h"
+
+
+ /*
+ * Perform a full C2P step on 32 8-bit pixels, stored in 8 32-bit words
+ * containing
+ * - 32 8-bit chunky pixels on input
+ * - permutated planar data (1 plane per 32-bit word) on output
+ */
+
+static void c2p_32x8(u32 d[8])
+{
+ transp8(d, 16, 4);
+ transp8(d, 8, 2);
+ transp8(d, 4, 1);
+ transp8(d, 2, 4);
+ transp8(d, 1, 2);
+}
+
+
+ /*
+ * Array containing the permutation indices of the planar data after c2p
+ */
+
+static const int perm_c2p_32x8[8] = { 7, 5, 3, 1, 6, 4, 2, 0 };
+
+
+ /*
+ * Store a full block of planar data after c2p conversion
+ */
+
+static inline void store_planar(void *dst, u32 dst_inc, u32 bpp, u32 d[8])
+{
+ int i;
+
+ for (i = 0; i < bpp; i++, dst += dst_inc)
+ put_unaligned_be32(d[perm_c2p_32x8[i]], dst);
+}
+
+
+ /*
+ * Store a partial block of planar data after c2p conversion
+ */
+
+static inline void store_planar_masked(void *dst, u32 dst_inc, u32 bpp,
+ u32 d[8], u32 mask)
+{
+ int i;
+
+ for (i = 0; i < bpp; i++, dst += dst_inc)
+ put_unaligned_be32(comp(d[perm_c2p_32x8[i]],
+ get_unaligned_be32(dst), mask),
+ dst);
+}
+
+
+ /*
+ * c2p_planar - Copy 8-bit chunky image data to a planar frame buffer
+ * @dst: Starting address of the planar frame buffer
+ * @dx: Horizontal destination offset (in pixels)
+ * @dy: Vertical destination offset (in pixels)
+ * @width: Image width (in pixels)
+ * @height: Image height (in pixels)
+ * @dst_nextline: Frame buffer offset to the next line (in bytes)
+ * @dst_nextplane: Frame buffer offset to the next plane (in bytes)
+ * @src_nextline: Image offset to the next line (in bytes)
+ * @bpp: Bits per pixel of the planar frame buffer (1-8)
+ */
+
+void c2p_planar(void *dst, const void *src, u32 dx, u32 dy, u32 width,
+ u32 height, u32 dst_nextline, u32 dst_nextplane,
+ u32 src_nextline, u32 bpp)
+{
+ union {
+ u8 pixels[32];
+ u32 words[8];
+ } d;
+ u32 dst_idx, first, last, w;
+ const u8 *c;
+ void *p;
+
+ dst += dy*dst_nextline+(dx & ~31);
+ dst_idx = dx % 32;
+ first = 0xffffffffU >> dst_idx;
+ last = ~(0xffffffffU >> ((dst_idx+width) % 32));
+ while (height--) {
+ c = src;
+ p = dst;
+ w = width;
+ if (dst_idx+width <= 32) {
+ /* Single destination word */
+ first &= last;
+ memset(d.pixels, 0, sizeof(d));
+ memcpy(d.pixels+dst_idx, c, width);
+ c += width;
+ c2p_32x8(d.words);
+ store_planar_masked(p, dst_nextplane, bpp, d.words,
+ first);
+ p += 4;
+ } else {
+ /* Multiple destination words */
+ w = width;
+ /* Leading bits */
+ if (dst_idx) {
+ w = 32 - dst_idx;
+ memset(d.pixels, 0, dst_idx);
+ memcpy(d.pixels+dst_idx, c, w);
+ c += w;
+ c2p_32x8(d.words);
+ store_planar_masked(p, dst_nextplane, bpp,
+ d.words, first);
+ p += 4;
+ w = width-w;
+ }
+ /* Main chunk */
+ while (w >= 32) {
+ memcpy(d.pixels, c, 32);
+ c += 32;
+ c2p_32x8(d.words);
+ store_planar(p, dst_nextplane, bpp, d.words);
+ p += 4;
+ w -= 32;
+ }
+ /* Trailing bits */
+ w %= 32;
+ if (w > 0) {
+ memcpy(d.pixels, c, w);
+ memset(d.pixels+w, 0, 32-w);
+ c2p_32x8(d.words);
+ store_planar_masked(p, dst_nextplane, bpp,
+ d.words, last);
+ }
+ }
+ src += src_nextline;
+ dst += dst_nextline;
+ }
+}
+EXPORT_SYMBOL_GPL(c2p_planar);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 4bcff81..1657b96 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -78,13 +78,6 @@
#include <asm/fb.h>
#include <asm/irq.h>
#include <asm/system.h>
-#ifdef CONFIG_ATARI
-#include <asm/atariints.h>
-#endif
-#if defined(__mc68000__)
-#include <asm/machdep.h>
-#include <asm/setup.h>
-#endif
#include "fbcon.h"
@@ -155,9 +148,6 @@ static int fbcon_set_origin(struct vc_data *);
#define CURSOR_DRAW_DELAY (1)
-/* # VBL ints between cursor state changes */
-#define ATARI_CURSOR_BLINK_RATE (42)
-
static int vbl_cursor_cnt;
static int fbcon_cursor_noblink;
@@ -403,20 +393,6 @@ static void fb_flashcursor(struct work_struct *work)
release_console_sem();
}
-#ifdef CONFIG_ATARI
-static int cursor_blink_rate;
-static irqreturn_t fb_vbl_handler(int irq, void *dev_id)
-{
- struct fb_info *info = dev_id;
-
- if (vbl_cursor_cnt && --vbl_cursor_cnt == 0) {
- schedule_work(&info->queue);
- vbl_cursor_cnt = cursor_blink_rate;
- }
- return IRQ_HANDLED;
-}
-#endif
-
static void cursor_timer_handler(unsigned long dev_addr)
{
struct fb_info *info = (struct fb_info *) dev_addr;
@@ -1017,15 +993,6 @@ static const char *fbcon_startup(void)
info->var.yres,
info->var.bits_per_pixel);
-#ifdef CONFIG_ATARI
- if (MACH_IS_ATARI) {
- cursor_blink_rate = ATARI_CURSOR_BLINK_RATE;
- (void)request_irq(IRQ_AUTO_4, fb_vbl_handler,
- IRQ_TYPE_PRIO, "framebuffer vbl",
- info);
- }
-#endif /* CONFIG_ATARI */
-
fbcon_add_cursor_timer(info);
fbcon_has_exited = 0;
return display_desc;
@@ -3454,11 +3421,6 @@ static void fbcon_exit(void)
if (fbcon_has_exited)
return;
-#ifdef CONFIG_ATARI
- if (MACH_IS_ATARI)
- free_irq(IRQ_AUTO_4, fb_vbl_handler);
-#endif
-
kfree((void *)softback_buf);
softback_buf = 0UL;
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index ec68c74..3efa12f 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -770,6 +770,12 @@ config TXX9_WDT
# POWERPC Architecture
+config GEF_WDT
+ tristate "GE Fanuc Watchdog Timer"
+ depends on GEF_SBC610
+ ---help---
+ Watchdog timer found in a number of GE Fanuc single board computers.
+
config MPC5200_WDT
tristate "MPC5200 Watchdog Timer"
depends on PPC_MPC52xx
@@ -790,6 +796,14 @@ config MV64X60_WDT
tristate "MV64X60 (Marvell Discovery) Watchdog Timer"
depends on MV64X60
+config PIKA_WDT
+ tristate "PIKA FPGA Watchdog"
+ depends on WARP
+ default y
+ help
+ This enables the watchdog in the PIKA FPGA. Currently used on
+ the Warp platform.
+
config BOOKE_WDT
bool "PowerPC Book-E Watchdog Timer"
depends on BOOKE || 4xx
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index c19b866..806b3eb 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -111,9 +111,11 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
# PARISC Architecture
# POWERPC Architecture
+obj-$(CONFIG_GEF_WDT) += gef_wdt.o
obj-$(CONFIG_MPC5200_WDT) += mpc5200_wdt.o
obj-$(CONFIG_8xxx_WDT) += mpc8xxx_wdt.o
obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o
+obj-$(CONFIG_PIKA_WDT) += pika_wdt.o
obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
# PPC64 Architecture
diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c
new file mode 100644
index 0000000..f0c2b7a
--- /dev/null
+++ b/drivers/watchdog/gef_wdt.c
@@ -0,0 +1,330 @@
+/*
+ * GE Fanuc watchdog userspace interface
+ *
+ * Author: Martyn Welch <martyn.welch@gefanuc.com>
+ *
+ * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Based on: mv64x60_wdt.c (MV64X60 watchdog userspace interface)
+ * Author: James Chapman <jchapman@katalix.com>
+ */
+
+/* TODO:
+ * This driver does not provide support for the hardwares capability of sending
+ * an interrupt at a programmable threshold.
+ *
+ * This driver currently can only support 1 watchdog - there are 2 in the
+ * hardware that this driver supports. Thus one could be configured as a
+ * process-based watchdog (via /dev/watchdog), the second (using the interrupt
+ * capabilities) a kernel-based watchdog.
+ */
+
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include <sysdev/fsl_soc.h>
+
+/*
+ * The watchdog configuration register contains a pair of 2-bit fields,
+ * 1. a reload field, bits 27-26, which triggers a reload of
+ * the countdown register, and
+ * 2. an enable field, bits 25-24, which toggles between
+ * enabling and disabling the watchdog timer.
+ * Bit 31 is a read-only field which indicates whether the
+ * watchdog timer is currently enabled.
+ *
+ * The low 24 bits contain the timer reload value.
+ */
+#define GEF_WDC_ENABLE_SHIFT 24
+#define GEF_WDC_SERVICE_SHIFT 26
+#define GEF_WDC_ENABLED_SHIFT 31
+
+#define GEF_WDC_ENABLED_TRUE 1
+#define GEF_WDC_ENABLED_FALSE 0
+
+/* Flags bits */
+#define GEF_WDOG_FLAG_OPENED 0
+
+static unsigned long wdt_flags;
+static int wdt_status;
+static void __iomem *gef_wdt_regs;
+static int gef_wdt_timeout;
+static int gef_wdt_count;
+static unsigned int bus_clk;
+static char expect_close;
+static DEFINE_SPINLOCK(gef_wdt_spinlock);
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+
+static int gef_wdt_toggle_wdc(int enabled_predicate, int field_shift)
+{
+ u32 data;
+ u32 enabled;
+ int ret = 0;
+
+ spin_lock(&gef_wdt_spinlock);
+ data = ioread32be(gef_wdt_regs);
+ enabled = (data >> GEF_WDC_ENABLED_SHIFT) & 1;
+
+ /* only toggle the requested field if enabled state matches predicate */
+ if ((enabled ^ enabled_predicate) == 0) {
+ /* We write a 1, then a 2 -- to the appropriate field */
+ data = (1 << field_shift) | gef_wdt_count;
+ iowrite32be(data, gef_wdt_regs);
+
+ data = (2 << field_shift) | gef_wdt_count;
+ iowrite32be(data, gef_wdt_regs);
+ ret = 1;
+ }
+ spin_unlock(&gef_wdt_spinlock);
+
+ return ret;
+}
+
+static void gef_wdt_service(void)
+{
+ gef_wdt_toggle_wdc(GEF_WDC_ENABLED_TRUE,
+ GEF_WDC_SERVICE_SHIFT);
+}
+
+static void gef_wdt_handler_enable(void)
+{
+ if (gef_wdt_toggle_wdc(GEF_WDC_ENABLED_FALSE,
+ GEF_WDC_ENABLE_SHIFT)) {
+ gef_wdt_service();
+ printk(KERN_NOTICE "gef_wdt: watchdog activated\n");
+ }
+}
+
+static void gef_wdt_handler_disable(void)
+{
+ if (gef_wdt_toggle_wdc(GEF_WDC_ENABLED_TRUE,
+ GEF_WDC_ENABLE_SHIFT))
+ printk(KERN_NOTICE "gef_wdt: watchdog deactivated\n");
+}
+
+static void gef_wdt_set_timeout(unsigned int timeout)
+{
+ /* maximum bus cycle count is 0xFFFFFFFF */
+ if (timeout > 0xFFFFFFFF / bus_clk)
+ timeout = 0xFFFFFFFF / bus_clk;
+
+ /* Register only holds upper 24 bits, bit shifted into lower 24 */
+ gef_wdt_count = (timeout * bus_clk) >> 8;
+ gef_wdt_timeout = timeout;
+}
+
+
+static ssize_t gef_wdt_write(struct file *file, const char __user *data,
+ size_t len, loff_t *ppos)
+{
+ if (len) {
+ if (!nowayout) {
+ size_t i;
+
+ expect_close = 0;
+
+ for (i = 0; i != len; i++) {
+ char c;
+ if (get_user(c, data + i))
+ return -EFAULT;
+ if (c == 'V')
+ expect_close = 42;
+ }
+ }
+ gef_wdt_service();
+ }
+
+ return len;
+}
+
+static long gef_wdt_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int timeout;
+ int options;
+ void __user *argp = (void __user *)arg;
+ static struct watchdog_info info = {
+ .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE |
+ WDIOF_KEEPALIVEPING,
+ .firmware_version = 0,
+ .identity = "GE Fanuc watchdog",
+ };
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ if (copy_to_user(argp, &info, sizeof(info)))
+ return -EFAULT;
+ break;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ if (put_user(wdt_status, (int __user *)argp))
+ return -EFAULT;
+ wdt_status &= ~WDIOF_KEEPALIVEPING;
+ break;
+
+ case WDIOC_SETOPTIONS:
+ if (get_user(options, (int __user *)argp))
+ return -EFAULT;
+
+ if (options & WDIOS_DISABLECARD)
+ gef_wdt_handler_disable();
+
+ if (options & WDIOS_ENABLECARD)
+ gef_wdt_handler_enable();
+ break;
+
+ case WDIOC_KEEPALIVE:
+ gef_wdt_service();
+ wdt_status |= WDIOF_KEEPALIVEPING;
+ break;
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(timeout, (int __user *)argp))
+ return -EFAULT;
+ gef_wdt_set_timeout(timeout);
+ /* Fall through */
+
+ case WDIOC_GETTIMEOUT:
+ if (put_user(gef_wdt_timeout, (int __user *)argp))
+ return -EFAULT;
+ break;
+
+ default:
+ return -ENOTTY;
+ }
+
+ return 0;
+}
+
+static int gef_wdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(GEF_WDOG_FLAG_OPENED, &wdt_flags))
+ return -EBUSY;
+
+ if (nowayout)
+ __module_get(THIS_MODULE);
+
+ gef_wdt_handler_enable();
+
+ return nonseekable_open(inode, file);
+}
+
+static int gef_wdt_release(struct inode *inode, struct file *file)
+{
+ if (expect_close == 42)
+ gef_wdt_handler_disable();
+ else {
+ printk(KERN_CRIT
+ "gef_wdt: unexpected close, not stopping timer!\n");
+ gef_wdt_service();
+ }
+ expect_close = 0;
+
+ clear_bit(GEF_WDOG_FLAG_OPENED, &wdt_flags);
+
+ return 0;
+}
+
+static const struct file_operations gef_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = gef_wdt_write,
+ .unlocked_ioctl = gef_wdt_ioctl,
+ .open = gef_wdt_open,
+ .release = gef_wdt_release,
+};
+
+static struct miscdevice gef_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &gef_wdt_fops,
+};
+
+
+static int __devinit gef_wdt_probe(struct of_device *dev,
+ const struct of_device_id *match)
+{
+ int timeout = 10;
+ u32 freq;
+
+ bus_clk = 133; /* in MHz */
+
+ freq = fsl_get_sys_freq();
+ if (freq > 0)
+ bus_clk = freq;
+
+ /* Map devices registers into memory */
+ gef_wdt_regs = of_iomap(dev->node, 0);
+ if (gef_wdt_regs == NULL)
+ return -ENOMEM;
+
+ gef_wdt_set_timeout(timeout);
+
+ gef_wdt_handler_disable(); /* in case timer was already running */
+
+ return misc_register(&gef_wdt_miscdev);
+}
+
+static int __devexit gef_wdt_remove(struct platform_device *dev)
+{
+ misc_deregister(&gef_wdt_miscdev);
+
+ gef_wdt_handler_disable();
+
+ iounmap(gef_wdt_regs);
+
+ return 0;
+}
+
+static const struct of_device_id gef_wdt_ids[] = {
+ {
+ .compatible = "gef,fpga-wdt",
+ },
+ {},
+};
+
+static struct of_platform_driver gef_wdt_driver = {
+ .owner = THIS_MODULE,
+ .name = "gef_wdt",
+ .match_table = gef_wdt_ids,
+ .probe = gef_wdt_probe,
+};
+
+static int __init gef_wdt_init(void)
+{
+ printk(KERN_INFO "GE Fanuc watchdog driver\n");
+ return of_register_platform_driver(&gef_wdt_driver);
+}
+
+static void __exit gef_wdt_exit(void)
+{
+ of_unregister_platform_driver(&gef_wdt_driver);
+}
+
+module_init(gef_wdt_init);
+module_exit(gef_wdt_exit);
+
+MODULE_AUTHOR("Martyn Welch <martyn.welch@gefanuc.com>");
+MODULE_DESCRIPTION("GE Fanuc watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_ALIAS("platform: gef_wdt");
diff --git a/drivers/watchdog/pika_wdt.c b/drivers/watchdog/pika_wdt.c
new file mode 100644
index 0000000..2d22e99
--- /dev/null
+++ b/drivers/watchdog/pika_wdt.c
@@ -0,0 +1,301 @@
+/*
+ * PIKA FPGA based Watchdog Timer
+ *
+ * Copyright (c) 2008 PIKA Technologies
+ * Sean MacLennan <smaclennan@pikatech.com>
+ */
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+#include <linux/bitops.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+
+#define DRV_NAME "PIKA-WDT"
+#define PFX DRV_NAME ": "
+
+/* Hardware timeout in seconds */
+#define WDT_HW_TIMEOUT 2
+
+/* Timer heartbeat (500ms) */
+#define WDT_TIMEOUT (HZ/2)
+
+/* User land timeout */
+#define WDT_HEARTBEAT 15
+static int heartbeat = WDT_HEARTBEAT;
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds. "
+ "(default = " __MODULE_STRING(WDT_HEARTBEAT) ")");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
+ "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static struct {
+ void __iomem *fpga;
+ unsigned long next_heartbeat; /* the next_heartbeat for the timer */
+ unsigned long open;
+ char expect_close;
+ int bootstatus;
+ struct timer_list timer; /* The timer that pings the watchdog */
+} pikawdt_private;
+
+static struct watchdog_info ident = {
+ .identity = DRV_NAME,
+ .options = WDIOF_CARDRESET |
+ WDIOF_SETTIMEOUT |
+ WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE,
+};
+
+/*
+ * Reload the watchdog timer. (ie, pat the watchdog)
+ */
+static inline void pikawdt_reset(void)
+{
+ /* -- FPGA: Reset Control Register (32bit R/W) (Offset: 0x14) --
+ * Bit 7, WTCHDG_EN: When set to 1, the watchdog timer is enabled.
+ * Once enabled, it cannot be disabled. The watchdog can be
+ * kicked by performing any write access to the reset
+ * control register (this register).
+ * Bit 8-11, WTCHDG_TIMEOUT_SEC: Sets the watchdog timeout value in
+ * seconds. Valid ranges are 1 to 15 seconds. The value can
+ * be modified dynamically.
+ */
+ unsigned reset = in_be32(pikawdt_private.fpga + 0x14);
+ /* enable with max timeout - 15 seconds */
+ reset |= (1 << 7) + (WDT_HW_TIMEOUT << 8);
+ out_be32(pikawdt_private.fpga + 0x14, reset);
+}
+
+/*
+ * Timer tick
+ */
+static void pikawdt_ping(unsigned long data)
+{
+ if (time_before(jiffies, pikawdt_private.next_heartbeat) ||
+ (!nowayout && !pikawdt_private.open)) {
+ pikawdt_reset();
+ mod_timer(&pikawdt_private.timer, jiffies + WDT_TIMEOUT);
+ } else
+ printk(KERN_CRIT PFX "I will reset your machine !\n");
+}
+
+
+static void pikawdt_keepalive(void)
+{
+ pikawdt_private.next_heartbeat = jiffies + heartbeat * HZ;
+}
+
+static void pikawdt_start(void)
+{
+ pikawdt_keepalive();
+ mod_timer(&pikawdt_private.timer, jiffies + WDT_TIMEOUT);
+}
+
+/*
+ * Watchdog device is opened, and watchdog starts running.
+ */
+static int pikawdt_open(struct inode *inode, struct file *file)
+{
+ /* /dev/watchdog can only be opened once */
+ if (test_and_set_bit(0, &pikawdt_private.open))
+ return -EBUSY;
+
+ pikawdt_start();
+
+ return nonseekable_open(inode, file);
+}
+
+/*
+ * Close the watchdog device.
+ */
+static int pikawdt_release(struct inode *inode, struct file *file)
+{
+ /* stop internal ping */
+ if (!pikawdt_private.expect_close)
+ del_timer(&pikawdt_private.timer);
+
+ clear_bit(0, &pikawdt_private.open);
+ pikawdt_private.expect_close = 0;
+ return 0;
+}
+
+/*
+ * Pat the watchdog whenever device is written to.
+ */
+static ssize_t pikawdt_write(struct file *file, const char __user *data,
+ size_t len, loff_t *ppos)
+{
+ if (!len)
+ return 0;
+
+ /* Scan for magic character */
+ if (!nowayout) {
+ size_t i;
+
+ pikawdt_private.expect_close = 0;
+
+ for (i = 0; i < len; i++) {
+ char c;
+ if (get_user(c, data + i))
+ return -EFAULT;
+ if (c == 'V') {
+ pikawdt_private.expect_close = 42;
+ break;
+ }
+ }
+ }
+
+ pikawdt_keepalive();
+
+ return len;
+}
+
+/*
+ * Handle commands from user-space.
+ */
+static long pikawdt_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ int new_value;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
+
+ case WDIOC_GETSTATUS:
+ return put_user(0, p);
+
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(pikawdt_private.bootstatus, p);
+
+ case WDIOC_KEEPALIVE:
+ pikawdt_keepalive();
+ return 0;
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(new_value, p))
+ return -EFAULT;
+
+ heartbeat = new_value;
+ pikawdt_keepalive();
+
+ return put_user(new_value, p); /* return current value */
+
+ case WDIOC_GETTIMEOUT:
+ return put_user(heartbeat, p);
+ }
+ return -ENOTTY;
+}
+
+
+static const struct file_operations pikawdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = pikawdt_open,
+ .release = pikawdt_release,
+ .write = pikawdt_write,
+ .unlocked_ioctl = pikawdt_ioctl,
+};
+
+static struct miscdevice pikawdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &pikawdt_fops,
+};
+
+static int __init pikawdt_init(void)
+{
+ struct device_node *np;
+ void __iomem *fpga;
+ static u32 post1;
+ int ret;
+
+ np = of_find_compatible_node(NULL, NULL, "pika,fpga");
+ if (np == NULL) {
+ printk(KERN_ERR PFX "Unable to find fpga.\n");
+ return -ENOENT;
+ }
+
+ pikawdt_private.fpga = of_iomap(np, 0);
+ of_node_put(np);
+ if (pikawdt_private.fpga == NULL) {
+ printk(KERN_ERR PFX "Unable to map fpga.\n");
+ return -ENOMEM;
+ }
+
+ ident.firmware_version = in_be32(pikawdt_private.fpga + 0x1c) & 0xffff;
+
+ /* POST information is in the sd area. */
+ np = of_find_compatible_node(NULL, NULL, "pika,fpga-sd");
+ if (np == NULL) {
+ printk(KERN_ERR PFX "Unable to find fpga-sd.\n");
+ ret = -ENOENT;
+ goto out;
+ }
+
+ fpga = of_iomap(np, 0);
+ of_node_put(np);
+ if (fpga == NULL) {
+ printk(KERN_ERR PFX "Unable to map fpga-sd.\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* -- FPGA: POST Test Results Register 1 (32bit R/W) (Offset: 0x4040) --
+ * Bit 31, WDOG: Set to 1 when the last reset was caused by a watchdog
+ * timeout.
+ */
+ post1 = in_be32(fpga + 0x40);
+ if (post1 & 0x80000000)
+ pikawdt_private.bootstatus = WDIOF_CARDRESET;
+
+ iounmap(fpga);
+
+ setup_timer(&pikawdt_private.timer, pikawdt_ping, 0);
+
+ ret = misc_register(&pikawdt_miscdev);
+ if (ret) {
+ printk(KERN_ERR PFX "Unable to register miscdev.\n");
+ goto out;
+ }
+
+ printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
+ heartbeat, nowayout);
+ return 0;
+
+out:
+ iounmap(pikawdt_private.fpga);
+ return ret;
+}
+
+static void __exit pikawdt_exit(void)
+{
+ misc_deregister(&pikawdt_miscdev);
+
+ iounmap(pikawdt_private.fpga);
+}
+
+module_init(pikawdt_init);
+module_exit(pikawdt_exit);
+
+MODULE_AUTHOR("Sean MacLennan <smaclennan@pikatech.com>");
+MODULE_DESCRIPTION("PIKA FPGA based Watchdog Timer");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
diff --git a/drivers/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c
index 2bc0d4d..a2d2e8e 100644
--- a/drivers/watchdog/wm8350_wdt.c
+++ b/drivers/watchdog/wm8350_wdt.c
@@ -279,7 +279,7 @@ static struct miscdevice wm8350_wdt_miscdev = {
.fops = &wm8350_wdt_fops,
};
-static int wm8350_wdt_probe(struct platform_device *pdev)
+static int __devinit wm8350_wdt_probe(struct platform_device *pdev)
{
struct wm8350 *wm8350 = platform_get_drvdata(pdev);
@@ -296,7 +296,7 @@ static int wm8350_wdt_probe(struct platform_device *pdev)
return misc_register(&wm8350_wdt_miscdev);
}
-static int __exit wm8350_wdt_remove(struct platform_device *pdev)
+static int __devexit wm8350_wdt_remove(struct platform_device *pdev)
{
misc_deregister(&wm8350_wdt_miscdev);
@@ -305,7 +305,7 @@ static int __exit wm8350_wdt_remove(struct platform_device *pdev)
static struct platform_driver wm8350_wdt_driver = {
.probe = wm8350_wdt_probe,
- .remove = wm8350_wdt_remove,
+ .remove = __devexit_p(wm8350_wdt_remove),
.driver = {
.name = "wm8350-wdt",
},
diff --git a/drivers/zorro/.gitignore b/drivers/zorro/.gitignore
new file mode 100644
index 0000000..34f980b
--- /dev/null
+++ b/drivers/zorro/.gitignore
@@ -0,0 +1,2 @@
+devlist.h
+gen-devlist
diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c
index 5290552..1d2a772e 100644
--- a/drivers/zorro/zorro-sysfs.c
+++ b/drivers/zorro/zorro-sysfs.c
@@ -77,17 +77,21 @@ static struct bin_attribute zorro_config_attr = {
.read = zorro_read_config,
};
-void zorro_create_sysfs_dev_files(struct zorro_dev *z)
+int zorro_create_sysfs_dev_files(struct zorro_dev *z)
{
struct device *dev = &z->dev;
+ int error;
/* current configuration's attributes */
- device_create_file(dev, &dev_attr_id);
- device_create_file(dev, &dev_attr_type);
- device_create_file(dev, &dev_attr_serial);
- device_create_file(dev, &dev_attr_slotaddr);
- device_create_file(dev, &dev_attr_slotsize);
- device_create_file(dev, &dev_attr_resource);
- sysfs_create_bin_file(&dev->kobj, &zorro_config_attr);
+ if ((error = device_create_file(dev, &dev_attr_id)) ||
+ (error = device_create_file(dev, &dev_attr_type)) ||
+ (error = device_create_file(dev, &dev_attr_serial)) ||
+ (error = device_create_file(dev, &dev_attr_slotaddr)) ||
+ (error = device_create_file(dev, &dev_attr_slotsize)) ||
+ (error = device_create_file(dev, &dev_attr_resource)) ||
+ (error = sysfs_create_bin_file(&dev->kobj, &zorro_config_attr)))
+ return error;
+
+ return 0;
}
diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c
index dff16d9..a1585d6 100644
--- a/drivers/zorro/zorro.c
+++ b/drivers/zorro/zorro.c
@@ -130,6 +130,7 @@ static int __init zorro_init(void)
{
struct zorro_dev *z;
unsigned int i;
+ int error;
if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO))
return 0;
@@ -140,7 +141,11 @@ static int __init zorro_init(void)
/* Initialize the Zorro bus */
INIT_LIST_HEAD(&zorro_bus.devices);
strcpy(zorro_bus.dev.bus_id, "zorro");
- device_register(&zorro_bus.dev);
+ error = device_register(&zorro_bus.dev);
+ if (error) {
+ pr_err("Zorro: Error registering zorro_bus\n");
+ return error;
+ }
/* Request the resources */
zorro_bus.num_resources = AMIGAHW_PRESENT(ZORRO3) ? 4 : 2;
@@ -160,15 +165,19 @@ static int __init zorro_init(void)
zorro_name_device(z);
z->resource.name = z->name;
if (request_resource(zorro_find_parent_resource(z), &z->resource))
- printk(KERN_ERR "Zorro: Address space collision on device %s "
- "[%lx:%lx]\n",
- z->name, (unsigned long)zorro_resource_start(z),
- (unsigned long)zorro_resource_end(z));
+ pr_err("Zorro: Address space collision on device %s %pR\n",
+ z->name, &z->resource);
sprintf(z->dev.bus_id, "%02x", i);
z->dev.parent = &zorro_bus.dev;
z->dev.bus = &zorro_bus_type;
- device_register(&z->dev);
- zorro_create_sysfs_dev_files(z);
+ error = device_register(&z->dev);
+ if (error) {
+ pr_err("Zorro: Error registering device %s\n", z->name);
+ continue;
+ }
+ error = zorro_create_sysfs_dev_files(z);
+ if (error)
+ dev_err(&z->dev, "Error creating sysfs files\n");
}
/* Mark all available Zorro II memory */
diff --git a/drivers/zorro/zorro.h b/drivers/zorro/zorro.h
index 5c91ada..b682d5c 100644
--- a/drivers/zorro/zorro.h
+++ b/drivers/zorro/zorro.h
@@ -1,4 +1,4 @@
extern void zorro_name_device(struct zorro_dev *z);
-extern void zorro_create_sysfs_dev_files(struct zorro_dev *z);
+extern int zorro_create_sysfs_dev_files(struct zorro_dev *z);