aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/video.c2
-rw-r--r--drivers/atm/ambassador.c8
-rw-r--r--drivers/atm/eni.c2
-rw-r--r--drivers/atm/firestream.c2
-rw-r--r--drivers/atm/fore200e.c2
-rw-r--r--drivers/atm/horizon.c2
-rw-r--r--drivers/atm/iphase.c2
-rw-r--r--drivers/atm/zatm.c2
-rw-r--r--drivers/block/cciss.c2
-rw-r--r--drivers/char/apm-emulation.c2
-rw-r--r--drivers/char/bfin-otp.c2
-rw-r--r--drivers/char/cyclades.c2
-rw-r--r--drivers/char/serial167.c7
-rw-r--r--drivers/char/tty_ldisc.c7
-rw-r--r--drivers/char/vt_ioctl.c6
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.c2
-rw-r--r--drivers/connector/cn_queue.c12
-rw-r--r--drivers/connector/connector.c22
-rw-r--r--drivers/gpio/gpiolib.c2
-rw-r--r--drivers/hwmon/fschmd.c2
-rw-r--r--drivers/input/input.c2
-rw-r--r--drivers/isdn/mISDN/socket.c2
-rw-r--r--drivers/lguest/lguest_user.c2
-rw-r--r--drivers/md/dm-log-userspace-transfer.c6
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c2
-rw-r--r--drivers/media/dvb/firewire/firedtv-ci.c2
-rw-r--r--drivers/misc/phantom.c2
-rw-r--r--drivers/misc/sgi-gru/grufile.c3
-rw-r--r--drivers/mmc/core/debugfs.c2
-rw-r--r--drivers/mmc/core/sdio_cis.c65
-rw-r--r--drivers/mmc/host/Kconfig41
-rw-r--r--drivers/mmc/host/mmci.c2
-rw-r--r--drivers/mmc/host/s3cmci.c608
-rw-r--r--drivers/mmc/host/s3cmci.h14
-rw-r--r--drivers/net/3c59x.c77
-rw-r--r--drivers/net/Kconfig7
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/bcm63xx_enet.c2
-rw-r--r--drivers/net/benet/be.h1
-rw-r--r--drivers/net/benet/be_cmds.c3
-rw-r--r--drivers/net/benet/be_cmds.h3
-rw-r--r--drivers/net/benet/be_main.c23
-rw-r--r--drivers/net/bonding/bond_sysfs.c1
-rw-r--r--drivers/net/cnic.c3
-rw-r--r--drivers/net/cnic_if.h4
-rw-r--r--drivers/net/e1000e/netdev.c13
-rw-r--r--drivers/net/hamradio/mkiss.c4
-rw-r--r--drivers/net/igb/igb_main.c13
-rw-r--r--drivers/net/iseries_veth.c2
-rw-r--r--drivers/net/ixgbe/ixgbe_82598.c2
-rw-r--r--drivers/net/ixgbe/ixgbe_common.c232
-rw-r--r--drivers/net/ixgbe/ixgbe_ethtool.c4
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c52
-rw-r--r--drivers/net/ixgbe/ixgbe_type.h9
-rw-r--r--drivers/net/ks8851_mll.c1697
-rw-r--r--drivers/net/meth.c2
-rw-r--r--drivers/net/pppol2tp.c2
-rw-r--r--drivers/net/qlge/qlge.h18
-rw-r--r--drivers/net/qlge/qlge_main.c26
-rw-r--r--drivers/net/sgiseeq.c2
-rw-r--r--drivers/net/skge.c16
-rw-r--r--drivers/net/skge.h2
-rw-r--r--drivers/net/sky2.c7
-rw-r--r--drivers/net/sky2.h2
-rw-r--r--drivers/net/tg3.h1
-rw-r--r--drivers/net/virtio_net.c2
-rw-r--r--drivers/net/wireless/Kconfig13
-rw-r--r--drivers/net/wireless/ath/ar9170/phy.c6
-rw-r--r--drivers/net/wireless/b43/pio.c60
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c3
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c1
-rw-r--r--drivers/pcmcia/sa1100_assabet.c2
-rw-r--r--drivers/pcmcia/sa1100_neponset.c2
-rw-r--r--drivers/s390/cio/qdio_debug.c2
-rw-r--r--drivers/s390/cio/qdio_perf.c2
-rw-r--r--drivers/scsi/sg.c43
-rw-r--r--drivers/serial/8250.c7
-rw-r--r--drivers/serial/Kconfig2
-rw-r--r--drivers/serial/icom.c54
-rw-r--r--drivers/serial/sa1100.c2
-rw-r--r--drivers/serial/serial_txx9.c39
-rw-r--r--drivers/spi/Makefile2
-rw-r--r--drivers/spi/spi_imx.c (renamed from drivers/spi/mxc_spi.c)383
-rw-r--r--drivers/spi/spidev.c2
-rw-r--r--drivers/staging/dst/dcore.c7
-rw-r--r--drivers/staging/pohmelfs/config.c5
-rw-r--r--drivers/usb/class/usbtmc.c2
-rw-r--r--drivers/usb/gadget/printer.c2
-rw-r--r--drivers/usb/host/whci/debug.c6
-rw-r--r--drivers/usb/misc/rio500.c3
-rw-r--r--drivers/uwb/uwb-debug.c6
-rw-r--r--drivers/video/uvesafb.c5
-rw-r--r--drivers/w1/w1_netlink.c2
93 files changed, 3036 insertions, 703 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index a4fddb24476..f6e54bf8dd9 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -285,7 +285,7 @@ static int acpi_video_device_brightness_open_fs(struct inode *inode,
struct file *file);
static ssize_t acpi_video_device_write_brightness(struct file *file,
const char __user *buffer, size_t count, loff_t *data);
-static struct file_operations acpi_video_device_brightness_fops = {
+static const struct file_operations acpi_video_device_brightness_fops = {
.owner = THIS_MODULE,
.open = acpi_video_device_brightness_open_fs,
.read = seq_read,
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
index 703364b5217..66e181345b3 100644
--- a/drivers/atm/ambassador.c
+++ b/drivers/atm/ambassador.c
@@ -1306,14 +1306,6 @@ static void amb_close (struct atm_vcc * atm_vcc) {
return;
}
-/********** Set socket options for a VC **********/
-
-// int amb_getsockopt (struct atm_vcc * atm_vcc, int level, int optname, void * optval, int optlen);
-
-/********** Set socket options for a VC **********/
-
-// int amb_setsockopt (struct atm_vcc * atm_vcc, int level, int optname, void * optval, int optlen);
-
/********** Send **********/
static int amb_send (struct atm_vcc * atm_vcc, struct sk_buff * skb) {
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index 5503bfc8e13..0c302614544 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -2031,7 +2031,7 @@ static int eni_getsockopt(struct atm_vcc *vcc,int level,int optname,
static int eni_setsockopt(struct atm_vcc *vcc,int level,int optname,
- void __user *optval,int optlen)
+ void __user *optval,unsigned int optlen)
{
return -EINVAL;
}
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
index b119640e1ee..cd5049af47a 100644
--- a/drivers/atm/firestream.c
+++ b/drivers/atm/firestream.c
@@ -1244,7 +1244,7 @@ static int fs_getsockopt(struct atm_vcc *vcc,int level,int optname,
static int fs_setsockopt(struct atm_vcc *vcc,int level,int optname,
- void __user *optval,int optlen)
+ void __user *optval,unsigned int optlen)
{
func_enter ();
func_exit ();
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index 10f000dbe44..f766cc46b4c 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -1795,7 +1795,7 @@ fore200e_getsockopt(struct atm_vcc* vcc, int level, int optname, void __user *op
static int
-fore200e_setsockopt(struct atm_vcc* vcc, int level, int optname, void __user *optval, int optlen)
+fore200e_setsockopt(struct atm_vcc* vcc, int level, int optname, void __user *optval, unsigned int optlen)
{
/* struct fore200e* fore200e = FORE200E_DEV(vcc->dev); */
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
index 01ce241dbea..4e49021e67e 100644
--- a/drivers/atm/horizon.c
+++ b/drivers/atm/horizon.c
@@ -2590,7 +2590,7 @@ static int hrz_getsockopt (struct atm_vcc * atm_vcc, int level, int optname,
}
static int hrz_setsockopt (struct atm_vcc * atm_vcc, int level, int optname,
- void *optval, int optlen) {
+ void *optval, unsigned int optlen) {
hrz_dev * dev = HRZ_DEV(atm_vcc->dev);
PRINTD (DBG_FLOW|DBG_VCC, "hrz_setsockopt");
switch (level) {
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index 78c9736c357..b2c1b37ab2e 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -2862,7 +2862,7 @@ static int ia_getsockopt(struct atm_vcc *vcc, int level, int optname,
}
static int ia_setsockopt(struct atm_vcc *vcc, int level, int optname,
- void __user *optval, int optlen)
+ void __user *optval, unsigned int optlen)
{
IF_EVENT(printk(">ia_setsockopt\n");)
return -EINVAL;
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c
index 752b1ba81f7..2e9635be048 100644
--- a/drivers/atm/zatm.c
+++ b/drivers/atm/zatm.c
@@ -1517,7 +1517,7 @@ static int zatm_getsockopt(struct atm_vcc *vcc,int level,int optname,
static int zatm_setsockopt(struct atm_vcc *vcc,int level,int optname,
- void __user *optval,int optlen)
+ void __user *optval,unsigned int optlen)
{
return -EINVAL;
}
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 24c3e21ab26..1ece0b47b58 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -426,7 +426,7 @@ out:
return err;
}
-static struct file_operations cciss_proc_fops = {
+static const struct file_operations cciss_proc_fops = {
.owner = THIS_MODULE,
.open = cciss_seq_open,
.read = seq_read,
diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c
index aaca40283be..4f568cb9af3 100644
--- a/drivers/char/apm-emulation.c
+++ b/drivers/char/apm-emulation.c
@@ -393,7 +393,7 @@ static int apm_open(struct inode * inode, struct file * filp)
return as ? 0 : -ENOMEM;
}
-static struct file_operations apm_bios_fops = {
+static const struct file_operations apm_bios_fops = {
.owner = THIS_MODULE,
.read = apm_read,
.poll = apm_poll,
diff --git a/drivers/char/bfin-otp.c b/drivers/char/bfin-otp.c
index e3dd24bff51..836d4f0a876 100644
--- a/drivers/char/bfin-otp.c
+++ b/drivers/char/bfin-otp.c
@@ -217,7 +217,7 @@ static long bfin_otp_ioctl(struct file *filp, unsigned cmd, unsigned long arg)
# define bfin_otp_ioctl NULL
#endif
-static struct file_operations bfin_otp_fops = {
+static const struct file_operations bfin_otp_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = bfin_otp_ioctl,
.read = bfin_otp_read,
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index df5038bbcbc..4254457d391 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -3354,7 +3354,7 @@ static int __init cy_detect_isa(void)
continue;
}
#ifdef MODULE
- if (isparam && irq[i])
+ if (isparam && i < NR_CARDS && irq[i])
cy_isa_irq = irq[i];
else
#endif
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
index 5942a9d674c..452370af95d 100644
--- a/drivers/char/serial167.c
+++ b/drivers/char/serial167.c
@@ -220,8 +220,7 @@ static inline int serial_paranoia_check(struct cyclades_port *info, char *name,
return 1;
}
- if ((long)info < (long)(&cy_port[0])
- || (long)(&cy_port[NR_PORTS]) < (long)info) {
+ if (info < &cy_port[0] || info >= &cy_port[NR_PORTS]) {
printk("Warning: cyclades_port out of range for (%s) in %s\n",
name, routine);
return 1;
@@ -520,15 +519,13 @@ static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id)
panic("TxInt on debug port!!!");
}
#endif
-
- info = &cy_port[channel];
-
/* validate the port number (as configured and open) */
if ((channel < 0) || (NR_PORTS <= channel)) {
base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
base_addr[CyTEOIR] = CyNOTRANS;
return IRQ_HANDLED;
}
+ info = &cy_port[channel];
info->last_active = jiffies;
if (info->tty == 0) {
base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c
index aafdbaebc16..feb55075819 100644
--- a/drivers/char/tty_ldisc.c
+++ b/drivers/char/tty_ldisc.c
@@ -518,7 +518,7 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
static int tty_ldisc_halt(struct tty_struct *tty)
{
clear_bit(TTY_LDISC, &tty->flags);
- return cancel_delayed_work(&tty->buf.work);
+ return cancel_delayed_work_sync(&tty->buf.work);
}
/**
@@ -756,12 +756,9 @@ void tty_ldisc_hangup(struct tty_struct *tty)
* N_TTY.
*/
if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
- /* Make sure the old ldisc is quiescent */
- tty_ldisc_halt(tty);
- flush_scheduled_work();
-
/* Avoid racing set_ldisc or tty_ldisc_release */
mutex_lock(&tty->ldisc_mutex);
+ tty_ldisc_halt(tty);
if (tty->ldisc) { /* Not yet closed */
/* Switch back to N_TTY */
tty_ldisc_reinit(tty);
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 29c651ab0d7..6b36ee56e6f 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -981,8 +981,10 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
goto eperm;
if (copy_from_user(&vsa, (struct vt_setactivate __user *)arg,
- sizeof(struct vt_setactivate)))
- return -EFAULT;
+ sizeof(struct vt_setactivate))) {
+ ret = -EFAULT;
+ goto out;
+ }
if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES)
ret = -ENXIO;
else {
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index f40ab699860..4846d50199f 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -559,7 +559,7 @@ static int hwicap_release(struct inode *inode, struct file *file)
return status;
}
-static struct file_operations hwicap_fops = {
+static const struct file_operations hwicap_fops = {
.owner = THIS_MODULE,
.write = hwicap_write,
.read = hwicap_read,
diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c
index 4a1dfe1f4ba..210338ea222 100644
--- a/drivers/connector/cn_queue.c
+++ b/drivers/connector/cn_queue.c
@@ -78,18 +78,20 @@ void cn_queue_wrapper(struct work_struct *work)
struct cn_callback_entry *cbq =
container_of(work, struct cn_callback_entry, work);
struct cn_callback_data *d = &cbq->data;
+ struct cn_msg *msg = NLMSG_DATA(nlmsg_hdr(d->skb));
+ struct netlink_skb_parms *nsp = &NETLINK_CB(d->skb);
- d->callback(d->callback_priv);
+ d->callback(msg, nsp);
- d->destruct_data(d->ddata);
- d->ddata = NULL;
+ kfree_skb(d->skb);
+ d->skb = NULL;
kfree(d->free);
}
static struct cn_callback_entry *
cn_queue_alloc_callback_entry(char *name, struct cb_id *id,
- void (*callback)(struct cn_msg *))
+ void (*callback)(struct cn_msg *, struct netlink_skb_parms *))
{
struct cn_callback_entry *cbq;
@@ -123,7 +125,7 @@ int cn_cb_equal(struct cb_id *i1, struct cb_id *i2)
}
int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id,
- void (*callback)(struct cn_msg *))
+ void (*callback)(struct cn_msg *, struct netlink_skb_parms *))
{
struct cn_callback_entry *cbq, *__cbq;
int found = 0;
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index 74f52af7956..f06024668f9 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -129,21 +129,19 @@ EXPORT_SYMBOL_GPL(cn_netlink_send);
/*
* Callback helper - queues work and setup destructor for given data.
*/
-static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), void *data)
+static int cn_call_callback(struct sk_buff *skb)
{
struct cn_callback_entry *__cbq, *__new_cbq;
struct cn_dev *dev = &cdev;
+ struct cn_msg *msg = NLMSG_DATA(nlmsg_hdr(skb));
int err = -ENODEV;
spin_lock_bh(&dev->cbdev->queue_lock);
list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) {
if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
if (likely(!work_pending(&__cbq->work) &&
- __cbq->data.ddata == NULL)) {
- __cbq->data.callback_priv = msg;
-
- __cbq->data.ddata = data;
- __cbq->data.destruct_data = destruct_data;
+ __cbq->data.skb == NULL)) {
+ __cbq->data.skb = skb;
if (queue_cn_work(__cbq, &__cbq->work))
err = 0;
@@ -156,10 +154,8 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v
__new_cbq = kzalloc(sizeof(struct cn_callback_entry), GFP_ATOMIC);
if (__new_cbq) {
d = &__new_cbq->data;
- d->callback_priv = msg;
+ d->skb = skb;
d->callback = __cbq->data.callback;
- d->ddata = data;
- d->destruct_data = destruct_data;
d->free = __new_cbq;
__new_cbq->pdev = __cbq->pdev;
@@ -191,7 +187,6 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v
*/
static void cn_rx_skb(struct sk_buff *__skb)
{
- struct cn_msg *msg;
struct nlmsghdr *nlh;
int err;
struct sk_buff *skb;
@@ -208,8 +203,7 @@ static void cn_rx_skb(struct sk_buff *__skb)
return;
}
- msg = NLMSG_DATA(nlh);
- err = cn_call_callback(msg, (void (*)(void *))kfree_skb, skb);
+ err = cn_call_callback(skb);
if (err < 0)
kfree_skb(skb);
}
@@ -270,7 +264,7 @@ static void cn_notify(struct cb_id *id, u32 notify_event)
* May sleep.
*/
int cn_add_callback(struct cb_id *id, char *name,
- void (*callback)(struct cn_msg *))
+ void (*callback)(struct cn_msg *, struct netlink_skb_parms *))
{
int err;
struct cn_dev *dev = &cdev;
@@ -352,7 +346,7 @@ static int cn_ctl_msg_equals(struct cn_ctl_msg *m1, struct cn_ctl_msg *m2)
*
* Used for notification of a request's processing.
*/
-static void cn_callback(struct cn_msg *msg)
+static void cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
{
struct cn_ctl_msg *ctl;
struct cn_ctl_entry *ent;
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index bb11a429394..662ed923d9e 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1487,7 +1487,7 @@ static int gpiolib_open(struct inode *inode, struct file *file)
return single_open(file, gpiolib_show, NULL);
}
-static struct file_operations gpiolib_operations = {
+static const struct file_operations gpiolib_operations = {
.open = gpiolib_open,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c
index ea955edde87..2a7a85a6dc3 100644
--- a/drivers/hwmon/fschmd.c
+++ b/drivers/hwmon/fschmd.c
@@ -915,7 +915,7 @@ static int watchdog_ioctl(struct inode *inode, struct file *filp,
return ret;
}
-static struct file_operations watchdog_fops = {
+static const struct file_operations watchdog_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.open = watchdog_open,
diff --git a/drivers/input/input.c b/drivers/input/input.c
index e828aab7dac..16ec33f27c5 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -1273,6 +1273,7 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env)
} \
} while (0)
+#ifdef CONFIG_PM
static void input_dev_reset(struct input_dev *dev, bool activate)
{
if (!dev->event)
@@ -1287,7 +1288,6 @@ static void input_dev_reset(struct input_dev *dev, bool activate)
}
}
-#ifdef CONFIG_PM
static int input_dev_suspend(struct device *dev)
{
struct input_dev *input_dev = to_input_dev(dev);
diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
index c36f5213745..feb0fa45b66 100644
--- a/drivers/isdn/mISDN/socket.c
+++ b/drivers/isdn/mISDN/socket.c
@@ -415,7 +415,7 @@ data_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
}
static int data_sock_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int len)
+ char __user *optval, unsigned int len)
{
struct sock *sk = sock->sk;
int err = 0, opt = 0;
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c
index b4d3f7ca554..bd1632388e4 100644
--- a/drivers/lguest/lguest_user.c
+++ b/drivers/lguest/lguest_user.c
@@ -508,7 +508,7 @@ static int close(struct inode *inode, struct file *file)
* uses: reading and writing a character device called /dev/lguest. All the
* work happens in the read(), write() and close() routines:
*/
-static struct file_operations lguest_fops = {
+static const struct file_operations lguest_fops = {
.owner = THIS_MODULE,
.release = close,
.write = write,
diff --git a/drivers/md/dm-log-userspace-transfer.c b/drivers/md/dm-log-userspace-transfer.c
index ba0edad2d04..54abf9e303b 100644
--- a/drivers/md/dm-log-userspace-transfer.c
+++ b/drivers/md/dm-log-userspace-transfer.c
@@ -129,11 +129,13 @@ static int fill_pkg(struct cn_msg *msg, struct dm_ulog_request *tfr)
* This is the connector callback that delivers data
* that was sent from userspace.
*/
-static void cn_ulog_callback(void *data)
+static void cn_ulog_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
{
- struct cn_msg *msg = (struct cn_msg *)data;
struct dm_ulog_request *tfr = (struct dm_ulog_request *)(msg + 1);
+ if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN))
+ return;
+
spin_lock(&receiving_list_lock);
if (msg->len == 0)
fill_pkg(msg, NULL);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 3750ff48cba..51641498359 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -1203,7 +1203,7 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
return mask;
}
-static struct file_operations dvb_dvr_fops = {
+static const struct file_operations dvb_dvr_fops = {
.owner = THIS_MODULE,
.read = dvb_dvr_read,
.write = dvb_dvr_write,
diff --git a/drivers/media/dvb/firewire/firedtv-ci.c b/drivers/media/dvb/firewire/firedtv-ci.c
index eeb80d0ea3f..853e04b7cb3 100644
--- a/drivers/media/dvb/firewire/firedtv-ci.c
+++ b/drivers/media/dvb/firewire/firedtv-ci.c
@@ -215,7 +215,7 @@ static unsigned int fdtv_ca_io_poll(struct file *file, poll_table *wait)
return POLLIN;
}
-static struct file_operations fdtv_ca_fops = {
+static const struct file_operations fdtv_ca_fops = {
.owner = THIS_MODULE,
.ioctl = dvb_generic_ioctl,
.open = dvb_generic_open,
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
index fa57b67593a..90a95ce8dc3 100644
--- a/drivers/misc/phantom.c
+++ b/drivers/misc/phantom.c
@@ -271,7 +271,7 @@ static unsigned int phantom_poll(struct file *file, poll_table *wait)
return mask;
}
-static struct file_operations phantom_file_ops = {
+static const struct file_operations phantom_file_ops = {
.open = phantom_open,
.release = phantom_release,
.unlocked_ioctl = phantom_ioctl,
diff --git a/drivers/misc/sgi-gru/grufile.c b/drivers/misc/sgi-gru/grufile.c
index 300e7ba391a..41c8fe2a928 100644
--- a/drivers/misc/sgi-gru/grufile.c
+++ b/drivers/misc/sgi-gru/grufile.c
@@ -53,7 +53,6 @@ struct gru_stats_s gru_stats;
/* Guaranteed user available resources on each node */
static int max_user_cbrs, max_user_dsr_bytes;
-static struct file_operations gru_fops;
static struct miscdevice gru_miscdev;
@@ -426,7 +425,7 @@ static void __exit gru_exit(void)
gru_proc_exit();
}
-static struct file_operations gru_fops = {
+static const struct file_operations gru_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = gru_file_unlocked_ioctl,
.mmap = gru_file_mmap,
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 610dbd1fcc8..96d10f40fb2 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -240,7 +240,7 @@ static int mmc_ext_csd_release(struct inode *inode, struct file *file)
return 0;
}
-static struct file_operations mmc_dbg_ext_csd_fops = {
+static const struct file_operations mmc_dbg_ext_csd_fops = {
.open = mmc_ext_csd_open,
.read = mmc_ext_csd_read,
.release = mmc_ext_csd_release,
diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c
index 6636354b48c..e1035c89580 100644
--- a/drivers/mmc/core/sdio_cis.c
+++ b/drivers/mmc/core/sdio_cis.c
@@ -98,6 +98,22 @@ static const unsigned char speed_val[16] =
static const unsigned int speed_unit[8] =
{ 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 };
+/* FUNCE tuples with these types get passed to SDIO drivers */
+static const unsigned char funce_type_whitelist[] = {
+ 4 /* CISTPL_FUNCE_LAN_NODE_ID used in Broadcom cards */
+};
+
+static int cistpl_funce_whitelisted(unsigned char type)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(funce_type_whitelist); i++) {
+ if (funce_type_whitelist[i] == type)
+ return 1;
+ }
+ return 0;
+}
+
static int cistpl_funce_common(struct mmc_card *card,
const unsigned char *buf, unsigned size)
{
@@ -120,6 +136,10 @@ static int cistpl_funce_func(struct sdio_func *func,
unsigned vsn;
unsigned min_size;
+ /* let SDIO drivers take care of whitelisted FUNCE tuples */
+ if (cistpl_funce_whitelisted(buf[0]))
+ return -EILSEQ;
+
vsn = func->card->cccr.sdio_vsn;
min_size = (vsn == SDIO_SDIO_REV_1_00) ? 28 : 42;
@@ -154,13 +174,12 @@ static int cistpl_funce(struct mmc_card *card, struct sdio_func *func,
else
ret = cistpl_funce_common(card, buf, size);
- if (ret) {
+ if (ret && ret != -EILSEQ) {
printk(KERN_ERR "%s: bad CISTPL_FUNCE size %u "
"type %u\n", mmc_hostname(card->host), size, buf[0]);
- return ret;
}
- return 0;
+ return ret;
}
typedef int (tpl_parse_t)(struct mmc_card *, struct sdio_func *,
@@ -253,21 +272,12 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func)
for (i = 0; i < ARRAY_SIZE(cis_tpl_list); i++)
if (cis_tpl_list[i].code == tpl_code)
break;
- if (i >= ARRAY_SIZE(cis_tpl_list)) {
- /* this tuple is unknown to the core */
- this->next = NULL;
- this->code = tpl_code;
- this->size = tpl_link;
- *prev = this;
- prev = &this->next;
- printk(KERN_DEBUG
- "%s: queuing CIS tuple 0x%02x length %u\n",
- mmc_hostname(card->host), tpl_code, tpl_link);
- } else {
+ if (i < ARRAY_SIZE(cis_tpl_list)) {
const struct cis_tpl *tpl = cis_tpl_list + i;
if (tpl_link < tpl->min_size) {
printk(KERN_ERR
- "%s: bad CIS tuple 0x%02x (length = %u, expected >= %u)\n",
+ "%s: bad CIS tuple 0x%02x"
+ " (length = %u, expected >= %u)\n",
mmc_hostname(card->host),
tpl_code, tpl_link, tpl->min_size);
ret = -EINVAL;
@@ -275,7 +285,30 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func)
ret = tpl->parse(card, func,
this->data, tpl_link);
}
- kfree(this);
+ /*
+ * We don't need the tuple anymore if it was
+ * successfully parsed by the SDIO core or if it is
+ * not going to be parsed by SDIO drivers.
+ */
+ if (!ret || ret != -EILSEQ)
+ kfree(this);
+ } else {
+ /* unknown tuple */
+ ret = -EILSEQ;
+ }
+
+ if (ret == -EILSEQ) {
+ /* this tuple is unknown to the core or whitelisted */
+ this->next = NULL;
+ this->code = tpl_code;
+ this->size = tpl_link;
+ *prev = this;
+ prev = &this->next;
+ printk(KERN_DEBUG
+ "%s: queuing CIS tuple 0x%02x length %u\n",
+ mmc_hostname(card->host), tpl_code, tpl_link);
+ /* keep on analyzing tuples */
+ ret = 0;
}
ptr += tpl_link;
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 7cb057f3f88..432ae8358c8 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -276,6 +276,47 @@ config MMC_S3C
If unsure, say N.
+config MMC_S3C_HW_SDIO_IRQ
+ bool "Hardware support for SDIO IRQ"
+ depends on MMC_S3C
+ help
+ Enable the hardware support for SDIO interrupts instead of using
+ the generic polling code.
+
+choice
+ prompt "Samsung S3C SD/MMC transfer code"
+ depends on MMC_S3C
+
+config MMC_S3C_PIO
+ bool "Use PIO transfers only"
+ help
+ Use PIO to transfer data between memory and the hardware.
+
+ PIO is slower than DMA as it requires CPU instructions to
+ move the data. This has been the traditional default for
+ the S3C MCI driver.
+
+config MMC_S3C_DMA
+ bool "Use DMA transfers only (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ help
+ Use DMA to transfer data between memory and the hardare.
+
+ Currently, the DMA support in this driver seems to not be
+ working properly and needs to be debugged before this
+ option is useful.
+
+config MMC_S3C_PIODMA
+ bool "Support for both PIO and DMA (EXPERIMENTAL)"
+ help
+ Compile both the PIO and DMA transfer routines into the
+ driver and let the platform select at run-time which one
+ is best.
+
+ See notes for the DMA option.
+
+endchoice
+
config MMC_SDRICOH_CS
tristate "MMC/SD driver for Ricoh Bay1Controllers (EXPERIMENTAL)"
depends on EXPERIMENTAL && PCI && PCMCIA
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 3d1e5329da1..705a5894a6b 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -678,7 +678,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
writel(0, host->base + MMCIMASK1);
writel(0xfff, host->base + MMCICLEAR);
-#ifdef CONFIG_GPIOLIB
if (gpio_is_valid(plat->gpio_cd)) {
ret = gpio_request(plat->gpio_cd, DRIVER_NAME " (cd)");
if (ret == 0)
@@ -697,7 +696,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
else if (ret != -ENOSYS)
goto err_gpio_wp;
}
-#endif
ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host);
if (ret)
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index 8c08cd7efa7..99b74a35102 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -17,6 +17,8 @@
#include <linux/mmc/host.h>
#include <linux/platform_device.h>
#include <linux/cpufreq.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/io.h>
@@ -58,8 +60,6 @@ static const int dbgmap_debug = dbg_err | dbg_debug;
dev_dbg(&host->pdev->dev, args); \
} while (0)
-#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
-
static struct s3c2410_dma_client s3cmci_dma_client = {
.name = "s3c-mci",
};
@@ -164,6 +164,40 @@ static void dbg_dumpregs(struct s3cmci_host *host, char *prefix) { }
#endif /* CONFIG_MMC_DEBUG */
+/**
+ * s3cmci_host_usedma - return whether the host is using dma or pio
+ * @host: The host state
+ *
+ * Return true if the host is using DMA to transfer data, else false
+ * to use PIO mode. Will return static data depending on the driver
+ * configuration.
+ */
+static inline bool s3cmci_host_usedma(struct s3cmci_host *host)
+{
+#ifdef CONFIG_MMC_S3C_PIO
+ return false;
+#elif defined(CONFIG_MMC_S3C_DMA)
+ return true;
+#else
+ return host->dodma;
+#endif
+}
+
+/**
+ * s3cmci_host_canpio - return true if host has pio code available
+ *
+ * Return true if the driver has been compiled with the PIO support code
+ * available.
+ */
+static inline bool s3cmci_host_canpio(void)
+{
+#ifdef CONFIG_MMC_S3C_PIO
+ return true;
+#else
+ return false;
+#endif
+}
+
static inline u32 enable_imask(struct s3cmci_host *host, u32 imask)
{
u32 newmask;
@@ -190,7 +224,33 @@ static inline u32 disable_imask(struct s3cmci_host *host, u32 imask)
static inline void clear_imask(struct s3cmci_host *host)
{
- writel(0, host->base + host->sdiimsk);
+ u32 mask = readl(host->base + host->sdiimsk);
+
+ /* preserve the SDIO IRQ mask state */
+ mask &= S3C2410_SDIIMSK_SDIOIRQ;
+ writel(mask, host->base + host->sdiimsk);
+}
+
+/**
+ * s3cmci_check_sdio_irq - test whether the SDIO IRQ is being signalled
+ * @host: The host to check.
+ *
+ * Test to see if the SDIO interrupt is being signalled in case the
+ * controller has failed to re-detect a card interrupt. Read GPE8 and
+ * see if it is low and if so, signal a SDIO interrupt.
+ *
+ * This is currently called if a request is finished (we assume that the
+ * bus is now idle) and when the SDIO IRQ is enabled in case the IRQ is
+ * already being indicated.
+*/
+static void s3cmci_check_sdio_irq(struct s3cmci_host *host)
+{
+ if (host->sdio_irqen) {
+ if (gpio_get_value(S3C2410_GPE(8)) == 0) {
+ printk(KERN_DEBUG "%s: signalling irq\n", __func__);
+ mmc_signal_sdio_irq(host->mmc);
+ }
+ }
}
static inline int get_data_buffer(struct s3cmci_host *host,
@@ -238,6 +298,64 @@ static inline u32 fifo_free(struct s3cmci_host *host)
return 63 - fifostat;
}
+/**
+ * s3cmci_enable_irq - enable IRQ, after having disabled it.
+ * @host: The device state.
+ * @more: True if more IRQs are expected from transfer.
+ *
+ * Enable the main IRQ if needed after it has been disabled.
+ *
+ * The IRQ can be one of the following states:
+ * - disabled during IDLE
+ * - disabled whilst processing data
+ * - enabled during transfer
+ * - enabled whilst awaiting SDIO interrupt detection
+ */
+static void s3cmci_enable_irq(struct s3cmci_host *host, bool more)
+{
+ unsigned long flags;
+ bool enable = false;
+
+ local_irq_save(flags);
+
+ host->irq_enabled = more;
+ host->irq_disabled = false;
+
+ enable = more | host->sdio_irqen;
+
+ if (host->irq_state != enable) {
+ host->irq_state = enable;
+
+ if (enable)
+ enable_irq(host->irq);
+ else
+ disable_irq(host->irq);
+ }
+
+ local_irq_restore(flags);
+}
+
+/**
+ *
+ */
+static void s3cmci_disable_irq(struct s3cmci_host *host, bool transfer)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ //printk(KERN_DEBUG "%s: transfer %d\n", __func__, transfer);
+
+ host->irq_disabled = transfer;
+
+ if (transfer && host->irq_state) {
+ host->irq_state = false;
+ disable_irq(host->irq);
+ }
+
+ local_irq_restore(flags);
+}
+
static void do_pio_read(struct s3cmci_host *host)
{
int res;
@@ -374,8 +492,7 @@ static void pio_tasklet(unsigned long data)
{
struct s3cmci_host *host = (struct s3cmci_host *) data;
-
- disable_irq(host->irq);
+ s3cmci_disable_irq(host, true);
if (host->pio_active == XFER_WRITE)
do_pio_write(host);
@@ -395,9 +512,10 @@ static void pio_tasklet(unsigned long data)
host->mrq->data->error = -EINVAL;
}
+ s3cmci_enable_irq(host, false);
finalize_request(host);
} else
- enable_irq(host->irq);
+ s3cmci_enable_irq(host, true);
}
/*
@@ -432,17 +550,27 @@ static irqreturn_t s3cmci_irq(int irq, void *dev_id)
struct s3cmci_host *host = dev_id;
struct mmc_command *cmd;
u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt, mci_imsk;
- u32 mci_cclear, mci_dclear;
+ u32 mci_cclear = 0, mci_dclear;
unsigned long iflags;
+ mci_dsta = readl(host->base + S3C2410_SDIDSTA);
+ mci_imsk = readl(host->base + host->sdiimsk);
+
+ if (mci_dsta & S3C2410_SDIDSTA_SDIOIRQDETECT) {
+ if (mci_imsk & S3C2410_SDIIMSK_SDIOIRQ) {
+ mci_dclear = S3C2410_SDIDSTA_SDIOIRQDETECT;
+ writel(mci_dclear, host->base + S3C2410_SDIDSTA);
+
+ mmc_signal_sdio_irq(host->mmc);
+ return IRQ_HANDLED;
+ }
+ }
+
spin_lock_irqsave(&host->complete_lock, iflags);
mci_csta = readl(host->base + S3C2410_SDICMDSTAT);
- mci_dsta = readl(host->base + S3C2410_SDIDSTA);
mci_dcnt = readl(host->base + S3C2410_SDIDCNT);
mci_fsta = readl(host->base + S3C2410_SDIFSTA);
- mci_imsk = readl(host->base + host->sdiimsk);
- mci_cclear = 0;
mci_dclear = 0;
if ((host->complete_what == COMPLETION_NONE) ||
@@ -466,7 +594,7 @@ static irqreturn_t s3cmci_irq(int irq, void *dev_id)
goto irq_out;
}
- if (!host->dodma) {
+ if (!s3cmci_host_usedma(host)) {
if ((host->pio_active == XFER_WRITE) &&
(mci_fsta & S3C2410_SDIFSTA_TFDET)) {
@@ -673,6 +801,7 @@ static void s3cmci_dma_done_callback(struct s3c2410_dma_chan *dma_ch,
dbg(host, dbg_dma, "DMA FINISHED Size:%i DSTA:%08x DCNT:%08x\n",
size, mci_dsta, mci_dcnt);
+ host->dma_complete = 1;
host->complete_what = COMPLETION_FINALIZE;
out:
@@ -683,9 +812,9 @@ out:
fail_request:
host->mrq->data->error = -EINVAL;
host->complete_what = COMPLETION_FINALIZE;
- writel(0, host->base + host->sdiimsk);
- goto out;
+ clear_imask(host);
+ goto out;
}
static void finalize_request(struct s3cmci_host *host)
@@ -702,8 +831,9 @@ static void finalize_request(struct s3cmci_host *host)
if (cmd->data && (cmd->error == 0) &&
(cmd->data->error == 0)) {
- if (host->dodma && (!host->dma_complete)) {
- dbg(host, dbg_dma, "DMA Missing!\n");
+ if (s3cmci_host_usedma(host) && (!host->dma_complete)) {
+ dbg(host, dbg_dma, "DMA Missing (%d)!\n",
+ host->dma_complete);
return;
}
}
@@ -728,7 +858,7 @@ static void finalize_request(struct s3cmci_host *host)
writel(0, host->base + S3C2410_SDICMDARG);
writel(S3C2410_SDIDCON_STOP, host->base + S3C2410_SDIDCON);
writel(0, host->base + S3C2410_SDICMDCON);
- writel(0, host->base + host->sdiimsk);
+ clear_imask(host);
if (cmd->data && cmd->error)
cmd->data->error = cmd->error;
@@ -754,7 +884,7 @@ static void finalize_request(struct s3cmci_host *host)
/* If we had an error while transfering data we flush the
* DMA channel and the fifo to clear out any garbage. */
if (mrq->data->error != 0) {
- if (host->dodma)
+ if (s3cmci_host_usedma(host))
s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
if (host->is2440) {
@@ -776,6 +906,8 @@ static void finalize_request(struct s3cmci_host *host)
request_done:
host->complete_what = COMPLETION_NONE;
host->mrq = NULL;
+
+ s3cmci_check_sdio_irq(host);
mmc_request_done(host->mmc, mrq);
}
@@ -872,7 +1004,7 @@ static int s3cmci_setup_data(struct s3cmci_host *host, struct mmc_data *data)
dcon = data->blocks & S3C2410_SDIDCON_BLKNUM_MASK;
- if (host->dodma)
+ if (s3cmci_host_usedma(host))
dcon |= S3C2410_SDIDCON_DMAEN;
if (host->bus_width == MMC_BUS_WIDTH_4)
@@ -950,7 +1082,7 @@ static int s3cmci_prepare_pio(struct s3cmci_host *host, struct mmc_data *data)
static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)
{
int dma_len, i;
- int rw = (data->flags & MMC_DATA_WRITE) ? 1 : 0;
+ int rw = data->flags & MMC_DATA_WRITE;
BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
@@ -958,7 +1090,7 @@ static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)
s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
- (rw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+ rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
if (dma_len == 0)
return -ENOMEM;
@@ -969,11 +1101,11 @@ static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)
for (i = 0; i < dma_len; i++) {
int res;
- dbg(host, dbg_dma, "enqueue %i:%u@%u\n", i,
- sg_dma_address(&data->sg[i]),
- sg_dma_len(&data->sg[i]));
+ dbg(host, dbg_dma, "enqueue %i: %08x@%u\n", i,
+ sg_dma_address(&data->sg[i]),
+ sg_dma_len(&data->sg[i]));
- res = s3c2410_dma_enqueue(host->dma, (void *) host,
+ res = s3c2410_dma_enqueue(host->dma, host,
sg_dma_address(&data->sg[i]),
sg_dma_len(&data->sg[i]));
@@ -1018,7 +1150,7 @@ static void s3cmci_send_request(struct mmc_host *mmc)
return;
}
- if (host->dodma)
+ if (s3cmci_host_usedma(host))
res = s3cmci_prepare_dma(host, cmd->data);
else
res = s3cmci_prepare_pio(host, cmd->data);
@@ -1037,7 +1169,7 @@ static void s3cmci_send_request(struct mmc_host *mmc)
s3cmci_send_command(host, cmd);
/* Enable Interrupt */
- enable_irq(host->irq);
+ s3cmci_enable_irq(host, true);
}
static int s3cmci_card_present(struct mmc_host *mmc)
@@ -1049,7 +1181,7 @@ static int s3cmci_card_present(struct mmc_host *mmc)
if (pdata->gpio_detect == 0)
return -ENOSYS;
- ret = s3c2410_gpio_getpin(pdata->gpio_detect) ? 0 : 1;
+ ret = gpio_get_value(pdata->gpio_detect) ? 0 : 1;
return ret ^ pdata->detect_invert;
}
@@ -1104,12 +1236,12 @@ static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
switch (ios->power_mode) {
case MMC_POWER_ON:
case MMC_POWER_UP:
- s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_SDCLK);
- s3c2410_gpio_cfgpin(S3C2410_GPE6, S3C2410_GPE6_SDCMD);
- s3c2410_gpio_cfgpin(S3C2410_GPE7, S3C2410_GPE7_SDDAT0);
- s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);
- s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2);
- s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3);
+ s3c2410_gpio_cfgpin(S3C2410_GPE(5), S3C2410_GPE5_SDCLK);
+ s3c2410_gpio_cfgpin(S3C2410_GPE(6), S3C2410_GPE6_SDCMD);
+ s3c2410_gpio_cfgpin(S3C2410_GPE(7), S3C2410_GPE7_SDDAT0);
+ s3c2410_gpio_cfgpin(S3C2410_GPE(8), S3C2410_GPE8_SDDAT1);
+ s3c2410_gpio_cfgpin(S3C2410_GPE(9), S3C2410_GPE9_SDDAT2);
+ s3c2410_gpio_cfgpin(S3C2410_GPE(10), S3C2410_GPE10_SDDAT3);
if (host->pdata->set_power)
host->pdata->set_power(ios->power_mode, ios->vdd);
@@ -1121,8 +1253,7 @@ static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
case MMC_POWER_OFF:
default:
- s3c2410_gpio_setpin(S3C2410_GPE5, 0);
- s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPIO_OUTPUT);
+ gpio_direction_output(S3C2410_GPE(5), 0);
if (host->is2440)
mci_con |= S3C2440_SDICON_SDRESET;
@@ -1168,7 +1299,7 @@ static int s3cmci_get_ro(struct mmc_host *mmc)
struct s3c24xx_mci_pdata *pdata = host->pdata;
int ret;
- if (pdata->gpio_wprotect == 0)
+ if (pdata->no_wprotect)
return 0;
ret = s3c2410_gpio_getpin(pdata->gpio_wprotect);
@@ -1179,11 +1310,52 @@ static int s3cmci_get_ro(struct mmc_host *mmc)
return ret;
}
+static void s3cmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+ struct s3cmci_host *host = mmc_priv(mmc);
+ unsigned long flags;
+ u32 con;
+
+ local_irq_save(flags);
+
+ con = readl(host->base + S3C2410_SDICON);
+ host->sdio_irqen = enable;
+
+ if (enable == host->sdio_irqen)
+ goto same_state;
+
+ if (enable) {
+ con |= S3C2410_SDICON_SDIOIRQ;
+ enable_imask(host, S3C2410_SDIIMSK_SDIOIRQ);
+
+ if (!host->irq_state && !host->irq_disabled) {
+ host->irq_state = true;
+ enable_irq(host->irq);
+ }
+ } else {
+ disable_imask(host, S3C2410_SDIIMSK_SDIOIRQ);
+ con &= ~S3C2410_SDICON_SDIOIRQ;
+
+ if (!host->irq_enabled && host->irq_state) {
+ disable_irq_nosync(host->irq);
+ host->irq_state = false;
+ }
+ }
+
+ writel(con, host->base + S3C2410_SDICON);
+
+ same_state:
+ local_irq_restore(flags);
+
+ s3cmci_check_sdio_irq(host);
+}
+
static struct mmc_host_ops s3cmci_ops = {
.request = s3cmci_request,
.set_ios = s3cmci_set_ios,
.get_ro = s3cmci_get_ro,
.get_cd = s3cmci_card_present,
+ .enable_sdio_irq = s3cmci_enable_sdio_irq,
};
static struct s3c24xx_mci_pdata s3cmci_def_pdata = {
@@ -1246,11 +1418,140 @@ static inline void s3cmci_cpufreq_deregister(struct s3cmci_host *host)
}
#endif
-static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
+
+#ifdef CONFIG_DEBUG_FS
+
+static int s3cmci_state_show(struct seq_file *seq, void *v)
+{
+ struct s3cmci_host *host = seq->private;
+
+ seq_printf(seq, "Register base = 0x%08x\n", (u32)host->base);
+ seq_printf(seq, "Clock rate = %ld\n", host->clk_rate);
+ seq_printf(seq, "Prescale = %d\n", host->prescaler);
+ seq_printf(seq, "is2440 = %d\n", host->is2440);
+ seq_printf(seq, "IRQ = %d\n", host->irq);
+ seq_printf(seq, "IRQ enabled = %d\n", host->irq_enabled);
+ seq_printf(seq, "IRQ disabled = %d\n", host->irq_disabled);
+ seq_printf(seq, "IRQ state = %d\n", host->irq_state);
+ seq_printf(seq, "CD IRQ = %d\n", host->irq_cd);
+ seq_printf(seq, "Do DMA = %d\n", s3cmci_host_usedma(host));
+ seq_printf(seq, "SDIIMSK at %d\n", host->sdiimsk);
+ seq_printf(seq, "SDIDATA at %d\n", host->sdidata);
+
+ return 0;
+}
+
+static int s3cmci_state_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, s3cmci_state_show, inode->i_private);
+}
+
+static const struct file_operations s3cmci_fops_state = {
+ .owner = THIS_MODULE,
+ .open = s3cmci_state_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+#define DBG_REG(_r) { .addr = S3C2410_SDI##_r, .name = #_r }
+
+struct s3cmci_reg {
+ unsigned short addr;
+ unsigned char *name;
+} debug_regs[] = {
+ DBG_REG(CON),
+ DBG_REG(PRE),
+ DBG_REG(CMDARG),
+ DBG_REG(CMDCON),
+ DBG_REG(CMDSTAT),
+ DBG_REG(RSP0),
+ DBG_REG(RSP1),
+ DBG_REG(RSP2),
+ DBG_REG(RSP3),
+ DBG_REG(TIMER),
+ DBG_REG(BSIZE),
+ DBG_REG(DCON),
+ DBG_REG(DCNT),
+ DBG_REG(DSTA),
+ DBG_REG(FSTA),
+ {}
+};
+
+static int s3cmci_regs_show(struct seq_file *seq, void *v)
+{
+ struct s3cmci_host *host = seq->private;
+ struct s3cmci_reg *rptr = debug_regs;
+
+ for (; rptr->name; rptr++)
+ seq_printf(seq, "SDI%s\t=0x%08x\n", rptr->name,
+ readl(host->base + rptr->addr));
+
+ seq_printf(seq, "SDIIMSK\t=0x%08x\n", readl(host->base + host->sdiimsk));
+
+ return 0;
+}
+
+static int s3cmci_regs_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, s3cmci_regs_show, inode->i_private);
+}
+
+static const struct file_operations s3cmci_fops_regs = {
+ .owner = THIS_MODULE,
+ .open = s3cmci_regs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static void s3cmci_debugfs_attach(struct s3cmci_host *host)
+{
+ struct device *dev = &host->pdev->dev;
+
+ host->debug_root = debugfs_create_dir(dev_name(dev), NULL);
+ if (IS_ERR(host->debug_root)) {
+ dev_err(dev, "failed to create debugfs root\n");
+ return;
+ }
+
+ host->debug_state = debugfs_create_file("state", 0444,
+ host->debug_root, host,
+ &s3cmci_fops_state);
+
+ if (IS_ERR(host->debug_state))
+ dev_err(dev, "failed to create debug state file\n");
+
+ host->debug_regs = debugfs_create_file("regs", 0444,
+ host->debug_root, host,
+ &s3cmci_fops_regs);
+
+ if (IS_ERR(host->debug_regs))
+ dev_err(dev, "failed to create debug regs file\n");
+}
+
+static void s3cmci_debugfs_remove(struct s3cmci_host *host)
+{
+ debugfs_remove(host->debug_regs);
+ debugfs_remove(host->debug_state);
+ debugfs_remove(host->debug_root);
+}
+
+#else
+static inline void s3cmci_debugfs_attach(struct s3cmci_host *host) { }
+static inline void s3cmci_debugfs_remove(struct s3cmci_host *host) { }
+
+#endif /* CONFIG_DEBUG_FS */
+
+static int __devinit s3cmci_probe(struct platform_device *pdev)
{
struct s3cmci_host *host;
struct mmc_host *mmc;
int ret;
+ int is2440;
+ int i;
+
+ is2440 = platform_get_device_id(pdev)->driver_data;
mmc = mmc_alloc_host(sizeof(struct s3cmci_host), &pdev->dev);
if (!mmc) {
@@ -1258,6 +1559,18 @@ static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
goto probe_out;
}
+ for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++) {
+ ret = gpio_request(i, dev_name(&pdev->dev));
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get gpio %d\n", i);
+
+ for (i--; i >= S3C2410_GPE(5); i--)
+ gpio_free(i);
+
+ goto probe_free_host;
+ }
+ }
+
host = mmc_priv(mmc);
host->mmc = mmc;
host->pdev = pdev;
@@ -1282,11 +1595,12 @@ static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
host->clk_div = 2;
}
- host->dodma = 0;
host->complete_what = COMPLETION_NONE;
host->pio_active = XFER_NONE;
- host->dma = S3CMCI_DMA;
+#ifdef CONFIG_MMC_S3C_PIODMA
+ host->dodma = host->pdata->dma;
+#endif
host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!host->mem) {
@@ -1294,19 +1608,19 @@ static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
"failed to get io memory region resouce.\n");
ret = -ENOENT;
- goto probe_free_host;
+ goto probe_free_gpio;
}
host->mem = request_mem_region(host->mem->start,
- RESSIZE(host->mem), pdev->name);
+ resource_size(host->mem), pdev->name);
if (!host->mem) {
dev_err(&pdev->dev, "failed to request io memory region.\n");
ret = -ENOENT;
- goto probe_free_host;
+ goto probe_free_gpio;
}
- host->base = ioremap(host->mem->start, RESSIZE(host->mem));
+ host->base = ioremap(host->mem->start, resource_size(host->mem));
if (!host->base) {
dev_err(&pdev->dev, "failed to ioremap() io memory region.\n");
ret = -EINVAL;
@@ -1331,31 +1645,60 @@ static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
* ensure we don't lock the system with un-serviceable requests. */
disable_irq(host->irq);
+ host->irq_state = false;
- host->irq_cd = s3c2410_gpio_getirq(host->pdata->gpio_detect);
-
- if (host->irq_cd >= 0) {
- if (request_irq(host->irq_cd, s3cmci_irq_cd,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- DRIVER_NAME, host)) {
- dev_err(&pdev->dev, "can't get card detect irq.\n");
- ret = -ENOENT;
+ if (!host->pdata->no_detect) {
+ ret = gpio_request(host->pdata->gpio_detect, "s3cmci detect");
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get detect gpio\n");
goto probe_free_irq;
}
- } else {
- dev_warn(&pdev->dev, "host detect has no irq available\n");
- s3c2410_gpio_cfgpin(host->pdata->gpio_detect,
- S3C2410_GPIO_INPUT);
+
+ host->irq_cd = s3c2410_gpio_getirq(host->pdata->gpio_detect);
+
+ if (host->irq_cd >= 0) {
+ if (request_irq(host->irq_cd, s3cmci_irq_cd,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING,
+ DRIVER_NAME, host)) {
+ dev_err(&pdev->dev,
+ "can't get card detect irq.\n");
+ ret = -ENOENT;
+ goto probe_free_gpio_cd;
+ }
+ } else {
+ dev_warn(&pdev->dev,
+ "host detect has no irq available\n");
+ gpio_direction_input(host->pdata->gpio_detect);
+ }
+ } else
+ host->irq_cd = -1;
+
+ if (!host->pdata->no_wprotect) {
+ ret = gpio_request(host->pdata->gpio_wprotect, "s3cmci wp");
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get writeprotect\n");
+ goto probe_free_irq_cd;
+ }
+
+ gpio_direction_input(host->pdata->gpio_wprotect);
}
- if (host->pdata->gpio_wprotect)
- s3c2410_gpio_cfgpin(host->pdata->gpio_wprotect,
- S3C2410_GPIO_INPUT);
+ /* depending on the dma state, get a dma channel to use. */
- if (s3c2410_dma_request(S3CMCI_DMA, &s3cmci_dma_client, NULL) < 0) {
- dev_err(&pdev->dev, "unable to get DMA channel.\n");
- ret = -EBUSY;
- goto probe_free_irq_cd;
+ if (s3cmci_host_usedma(host)) {
+ host->dma = s3c2410_dma_request(DMACH_SDI, &s3cmci_dma_client,
+ host);
+ if (host->dma < 0) {
+ dev_err(&pdev->dev, "cannot get DMA channel.\n");
+ if (!s3cmci_host_canpio()) {
+ ret = -EBUSY;
+ goto probe_free_gpio_wp;
+ } else {
+ dev_warn(&pdev->dev, "falling back to PIO.\n");
+ host->dodma = 0;
+ }
+ }
}
host->clk = clk_get(&pdev->dev, "sdi");
@@ -1363,7 +1706,7 @@ static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
dev_err(&pdev->dev, "failed to find clock source.\n");
ret = PTR_ERR(host->clk);
host->clk = NULL;
- goto probe_free_host;
+ goto probe_free_dma;
}
ret = clk_enable(host->clk);
@@ -1376,7 +1719,11 @@ static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
mmc->ops = &s3cmci_ops;
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+#ifdef CONFIG_MMC_S3C_HW_SDIO_IRQ
+ mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
+#else
mmc->caps = MMC_CAP_4_BIT_DATA;
+#endif
mmc->f_min = host->clk_rate / (host->clk_div * 256);
mmc->f_max = host->clk_rate / host->clk_div;
@@ -1408,8 +1755,12 @@ static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
goto free_cpufreq;
}
+ s3cmci_debugfs_attach(host);
+
platform_set_drvdata(pdev, mmc);
- dev_info(&pdev->dev, "initialisation done.\n");
+ dev_info(&pdev->dev, "%s - using %s, %s SDIO IRQ\n", mmc_hostname(mmc),
+ s3cmci_host_usedma(host) ? "dma" : "pio",
+ mmc->caps & MMC_CAP_SDIO_IRQ ? "hw" : "sw");
return 0;
@@ -1422,6 +1773,18 @@ static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
clk_free:
clk_put(host->clk);
+ probe_free_dma:
+ if (s3cmci_host_usedma(host))
+ s3c2410_dma_free(host->dma, &s3cmci_dma_client);
+
+ probe_free_gpio_wp:
+ if (!host->pdata->no_wprotect)
+ gpio_free(host->pdata->gpio_wprotect);
+
+ probe_free_gpio_cd:
+ if (!host->pdata->no_detect)
+ gpio_free(host->pdata->gpio_detect);
+
probe_free_irq_cd:
if (host->irq_cd >= 0)
free_irq(host->irq_cd, host);
@@ -1433,10 +1796,15 @@ static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
iounmap(host->base);
probe_free_mem_region:
- release_mem_region(host->mem->start, RESSIZE(host->mem));
+ release_mem_region(host->mem->start, resource_size(host->mem));
+
+ probe_free_gpio:
+ for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++)
+ gpio_free(i);
probe_free_host:
mmc_free_host(mmc);
+
probe_out:
return ret;
}
@@ -1449,6 +1817,7 @@ static void s3cmci_shutdown(struct platform_device *pdev)
if (host->irq_cd >= 0)
free_irq(host->irq_cd, host);
+ s3cmci_debugfs_remove(host);
s3cmci_cpufreq_deregister(host);
mmc_remove_host(mmc);
clk_disable(host->clk);
@@ -1458,104 +1827,102 @@ static int __devexit s3cmci_remove(struct platform_device *pdev)
{
struct mmc_host *mmc = platform_get_drvdata(pdev);
struct s3cmci_host *host = mmc_priv(mmc);
+ struct s3c24xx_mci_pdata *pd = host->pdata;
+ int i;
s3cmci_shutdown(pdev);
clk_put(host->clk);
tasklet_disable(&host->pio_tasklet);
- s3c2410_dma_free(S3CMCI_DMA, &s3cmci_dma_client);
+
+ if (s3cmci_host_usedma(host))
+ s3c2410_dma_free(host->dma, &s3cmci_dma_client);
free_irq(host->irq, host);
+ if (!pd->no_wprotect)
+ gpio_free(pd->gpio_wprotect);
+
+ if (!pd->no_detect)
+ gpio_free(pd->gpio_detect);
+
+ for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++)
+ gpio_free(i);
+
+
iounmap(host->base);
- release_mem_region(host->mem->start, RESSIZE(host->mem));
+ release_mem_region(host->mem->start, resource_size(host->mem));
mmc_free_host(mmc);
return 0;
}
-static int __devinit s3cmci_2410_probe(struct platform_device *dev)
-{
- return s3cmci_probe(dev, 0);
-}
+static struct platform_device_id s3cmci_driver_ids[] = {
+ {
+ .name = "s3c2410-sdi",
+ .driver_data = 0,
+ }, {
+ .name = "s3c2412-sdi",
+ .driver_data = 1,
+ }, {
+ .name = "s3c2440-sdi",
+ .driver_data = 1,
+ },
+ { }
+};
-static int __devinit s3cmci_2412_probe(struct platform_device *dev)
-{
- return s3cmci_probe(dev, 1);
-}
+MODULE_DEVICE_TABLE(platform, s3cmci_driver_ids);
-static int __devinit s3cmci_2440_probe(struct platform_device *dev)
-{
- return s3cmci_probe(dev, 1);
-}
#ifdef CONFIG_PM
-static int s3cmci_suspend(struct platform_device *dev, pm_message_t state)
+static int s3cmci_suspend(struct device *dev)
{
- struct mmc_host *mmc = platform_get_drvdata(dev);
+ struct mmc_host *mmc = platform_get_drvdata(to_platform_device(dev));
+ struct pm_message event = { PM_EVENT_SUSPEND };
- return mmc_suspend_host(mmc, state);
+ return mmc_suspend_host(mmc, event);
}
-static int s3cmci_resume(struct platform_device *dev)
+static int s3cmci_resume(struct device *dev)
{
- struct mmc_host *mmc = platform_get_drvdata(dev);
+ struct mmc_host *mmc = platform_get_drvdata(to_platform_device(dev));
return mmc_resume_host(mmc);
}
-#else /* CONFIG_PM */
-#define s3cmci_suspend NULL
-#define s3cmci_resume NULL
-#endif /* CONFIG_PM */
-
-
-static struct platform_driver s3cmci_2410_driver = {
- .driver.name = "s3c2410-sdi",
- .driver.owner = THIS_MODULE,
- .probe = s3cmci_2410_probe,
- .remove = __devexit_p(s3cmci_remove),
- .shutdown = s3cmci_shutdown,
+static struct dev_pm_ops s3cmci_pm = {
.suspend = s3cmci_suspend,
.resume = s3cmci_resume,
};
-static struct platform_driver s3cmci_2412_driver = {
- .driver.name = "s3c2412-sdi",
- .driver.owner = THIS_MODULE,
- .probe = s3cmci_2412_probe,
- .remove = __devexit_p(s3cmci_remove),
- .shutdown = s3cmci_shutdown,
- .suspend = s3cmci_suspend,
- .resume = s3cmci_resume,
-};
+#define s3cmci_pm_ops &s3cmci_pm
+#else /* CONFIG_PM */
+#define s3cmci_pm_ops NULL
+#endif /* CONFIG_PM */
-static struct platform_driver s3cmci_2440_driver = {
- .driver.name = "s3c2440-sdi",
- .driver.owner = THIS_MODULE,
- .probe = s3cmci_2440_probe,
+
+static struct platform_driver s3cmci_driver = {
+ .driver = {
+ .name = "s3c-sdi",
+ .owner = THIS_MODULE,
+ .pm = s3cmci_pm_ops,
+ },
+ .id_table = s3cmci_driver_ids,
+ .probe = s3cmci_probe,
.remove = __devexit_p(s3cmci_remove),
.shutdown = s3cmci_shutdown,
- .suspend = s3cmci_suspend,
- .resume = s3cmci_resume,
};
-
static int __init s3cmci_init(void)
{
- platform_driver_register(&s3cmci_2410_driver);
- platform_driver_register(&s3cmci_2412_driver);
- platform_driver_register(&s3cmci_2440_driver);
- return 0;
+ return platform_driver_register(&s3cmci_driver);
}
static void __exit s3cmci_exit(void)
{
- platform_driver_unregister(&s3cmci_2410_driver);
- platform_driver_unregister(&s3cmci_2412_driver);
- platform_driver_unregister(&s3cmci_2440_driver);
+ platform_driver_unregister(&s3cmci_driver);
}
module_init(s3cmci_init);
@@ -1564,6 +1931,3 @@ module_exit(s3cmci_exit);
MODULE_DESCRIPTION("Samsung S3C MMC/SD Card Interface driver");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Thomas Kleffel <tk@maintech.de>, Ben Dooks <ben-linux@fluff.org>");
-MODULE_ALIAS("platform:s3c2410-sdi");
-MODULE_ALIAS("platform:s3c2412-sdi");
-MODULE_ALIAS("platform:s3c2440-sdi");
diff --git a/drivers/mmc/host/s3cmci.h b/drivers/mmc/host/s3cmci.h
index ca1ba3d58cf..c76b53dbeb6 100644
--- a/drivers/mmc/host/s3cmci.h
+++ b/drivers/mmc/host/s3cmci.h
@@ -8,9 +8,6 @@
* published by the Free Software Foundation.
*/
-/* FIXME: DMA Resource management ?! */
-#define S3CMCI_DMA 0
-
enum s3cmci_waitfor {
COMPLETION_NONE,
COMPLETION_FINALIZE,
@@ -42,6 +39,11 @@ struct s3cmci_host {
int dodma;
int dmatogo;
+ bool irq_disabled;
+ bool irq_enabled;
+ bool irq_state;
+ int sdio_irqen;
+
struct mmc_request *mrq;
int cmd_is_stop;
@@ -68,6 +70,12 @@ struct s3cmci_host {
unsigned int ccnt, dcnt;
struct tasklet_struct pio_tasklet;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debug_root;
+ struct dentry *debug_state;
+ struct dentry *debug_regs;
+#endif
+
#ifdef CONFIG_CPU_FREQ
struct notifier_block freq_transition;
#endif
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index b9eeadf01b7..975e25b19eb 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -805,52 +805,54 @@ static void poll_vortex(struct net_device *dev)
#ifdef CONFIG_PM
-static int vortex_suspend(struct pci_dev *pdev, pm_message_t state)
+static int vortex_suspend(struct device *dev)
{
- struct net_device *dev = pci_get_drvdata(pdev);
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct net_device *ndev = pci_get_drvdata(pdev);
+
+ if (!ndev || !netif_running(ndev))
+ return 0;
+
+ netif_device_detach(ndev);
+ vortex_down(ndev, 1);
- if (dev && netdev_priv(dev)) {
- if (netif_running(dev)) {
- netif_device_detach(dev);
- vortex_down(dev, 1);
- disable_irq(dev->irq);
- }
- pci_save_state(pdev);
- pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
- pci_disable_device(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
- }
return 0;
}
-static int vortex_resume(struct pci_dev *pdev)
+static int vortex_resume(struct device *dev)
{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct vortex_private *vp = netdev_priv(dev);
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct net_device *ndev = pci_get_drvdata(pdev);
int err;
- if (dev && vp) {
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
- err = pci_enable_device(pdev);
- if (err) {
- pr_warning("%s: Could not enable device\n",
- dev->name);
- return err;
- }
- pci_set_master(pdev);
- if (netif_running(dev)) {
- err = vortex_up(dev);
- if (err)
- return err;
- enable_irq(dev->irq);
- netif_device_attach(dev);
- }
- }
+ if (!ndev || !netif_running(ndev))
+ return 0;
+
+ err = vortex_up(ndev);
+ if (err)
+ return err;
+
+ netif_device_attach(ndev);
+
return 0;
}
-#endif /* CONFIG_PM */
+static struct dev_pm_ops vortex_pm_ops = {
+ .suspend = vortex_suspend,
+ .resume = vortex_resume,
+ .freeze = vortex_suspend,
+ .thaw = vortex_resume,
+ .poweroff = vortex_suspend,
+ .restore = vortex_resume,
+};
+
+#define VORTEX_PM_OPS (&vortex_pm_ops)
+
+#else /* !CONFIG_PM */
+
+#define VORTEX_PM_OPS NULL
+
+#endif /* !CONFIG_PM */
#ifdef CONFIG_EISA
static struct eisa_device_id vortex_eisa_ids[] = {
@@ -3199,10 +3201,7 @@ static struct pci_driver vortex_driver = {
.probe = vortex_init_one,
.remove = __devexit_p(vortex_remove_one),
.id_table = vortex_pci_tbl,
-#ifdef CONFIG_PM
- .suspend = vortex_suspend,
- .resume = vortex_resume,
-#endif
+ .driver.pm = VORTEX_PM_OPS,
};
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 2bea67c134f..712776089b4 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1738,6 +1738,13 @@ config KS8851
help
SPI driver for Micrel KS8851 SPI attached network chip.
+config KS8851_MLL
+ tristate "Micrel KS8851 MLL"
+ depends on HAS_IOMEM
+ help
+ This platform driver is for Micrel KS8851 Address/data bus
+ multiplexed network chip.
+
config VIA_RHINE
tristate "VIA Rhine support"
depends on NET_PCI && PCI
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index ae8cd30f13d..d866b8cf65d 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -89,6 +89,7 @@ obj-$(CONFIG_SKY2) += sky2.o
obj-$(CONFIG_SKFP) += skfp/
obj-$(CONFIG_KS8842) += ks8842.o
obj-$(CONFIG_KS8851) += ks8851.o
+obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o
obj-$(CONFIG_VIA_RHINE) += via-rhine.o
obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c
index 09d270913c5..ba29dc319b3 100644
--- a/drivers/net/bcm63xx_enet.c
+++ b/drivers/net/bcm63xx_enet.c
@@ -90,7 +90,7 @@ static int do_mdio_op(struct bcm_enet_priv *priv, unsigned int data)
if (enet_readl(priv, ENET_IR_REG) & ENET_IR_MII)
break;
udelay(1);
- } while (limit-- >= 0);
+ } while (limit-- > 0);
return (limit < 0) ? 1 : 0;
}
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h
index 684c6fe24c8..a80da0e14a5 100644
--- a/drivers/net/benet/be.h
+++ b/drivers/net/benet/be.h
@@ -258,6 +258,7 @@ struct be_adapter {
bool link_up;
u32 port_num;
bool promiscuous;
+ u32 cap;
};
extern const struct ethtool_ops be_ethtool_ops;
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index 3dd76c4170b..79d35d122c0 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -1068,7 +1068,7 @@ int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc)
}
/* Uses mbox */
-int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num)
+int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num, u32 *cap)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_query_fw_cfg *req;
@@ -1088,6 +1088,7 @@ int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num)
if (!status) {
struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb);
*port_num = le32_to_cpu(resp->phys_port);
+ *cap = le32_to_cpu(resp->function_cap);
}
spin_unlock(&adapter->mbox_lock);
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h
index 93e432f3d92..8b4c2cb9ad6 100644
--- a/drivers/net/benet/be_cmds.h
+++ b/drivers/net/benet/be_cmds.h
@@ -760,7 +760,8 @@ extern int be_cmd_set_flow_control(struct be_adapter *adapter,
u32 tx_fc, u32 rx_fc);
extern int be_cmd_get_flow_control(struct be_adapter *adapter,
u32 *tx_fc, u32 *rx_fc);
-extern int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num);
+extern int be_cmd_query_fw_cfg(struct be_adapter *adapter,
+ u32 *port_num, u32 *cap);
extern int be_cmd_reset_function(struct be_adapter *adapter);
extern int be_process_mcc(struct be_adapter *adapter);
extern int be_cmd_write_flashrom(struct be_adapter *adapter,
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index 409cf059590..2f9b50156e0 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -747,9 +747,16 @@ static void be_rx_compl_process(struct be_adapter *adapter,
struct be_eth_rx_compl *rxcp)
{
struct sk_buff *skb;
- u32 vtp, vid;
+ u32 vlanf, vid;
+ u8 vtm;
- vtp = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp);
+ vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp);
+ vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp);
+
+ /* vlanf could be wrongly set in some cards.
+ * ignore if vtm is not set */
+ if ((adapter->cap == 0x400) && !vtm)
+ vlanf = 0;
skb = netdev_alloc_skb(adapter->netdev, BE_HDR_LEN + NET_IP_ALIGN);
if (!skb) {
@@ -772,7 +779,7 @@ static void be_rx_compl_process(struct be_adapter *adapter,
skb->protocol = eth_type_trans(skb, adapter->netdev);
skb->dev = adapter->netdev;
- if (vtp) {
+ if (vlanf) {
if (!adapter->vlan_grp || adapter->num_vlans == 0) {
kfree_skb(skb);
return;
@@ -797,11 +804,18 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
struct be_eq_obj *eq_obj = &adapter->rx_eq;
u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len;
u16 i, rxq_idx = 0, vid, j;
+ u8 vtm;
num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp);
vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp);
rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
+ vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp);
+
+ /* vlanf could be wrongly set in some cards.
+ * ignore if vtm is not set */
+ if ((adapter->cap == 0x400) && !vtm)
+ vlanf = 0;
skb = napi_get_frags(&eq_obj->napi);
if (!skb) {
@@ -2045,7 +2059,8 @@ static int be_hw_up(struct be_adapter *adapter)
if (status)
return status;
- status = be_cmd_query_fw_cfg(adapter, &adapter->port_num);
+ status = be_cmd_query_fw_cfg(adapter,
+ &adapter->port_num, &adapter->cap);
return status;
}
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 6044e12ff9f..ff449de6f3c 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -1182,6 +1182,7 @@ static ssize_t bonding_store_primary(struct device *d,
": %s: Setting %s as primary slave.\n",
bond->dev->name, slave->dev->name);
bond->primary_slave = slave;
+ strcpy(bond->params.primary, slave->dev->name);
bond_select_active_slave(bond);
goto out;
}
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 211c8e9182f..46c87ec7960 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -2733,7 +2733,8 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
cnic_ulp_init(dev);
else if (event == NETDEV_UNREGISTER)
cnic_ulp_exit(dev);
- else if (event == NETDEV_UP) {
+
+ if (event == NETDEV_UP) {
if (cnic_register_netdev(dev) != 0) {
cnic_put(dev);
goto done;
diff --git a/drivers/net/cnic_if.h b/drivers/net/cnic_if.h
index a49235739ee..d8b09efdcb5 100644
--- a/drivers/net/cnic_if.h
+++ b/drivers/net/cnic_if.h
@@ -12,8 +12,8 @@
#ifndef CNIC_IF_H
#define CNIC_IF_H
-#define CNIC_MODULE_VERSION "2.0.0"
-#define CNIC_MODULE_RELDATE "May 21, 2009"
+#define CNIC_MODULE_VERSION "2.0.1"
+#define CNIC_MODULE_RELDATE "Oct 01, 2009"
#define CNIC_ULP_RDMA 0
#define CNIC_ULP_ISCSI 1
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 16c193a6c95..0687c6aa4e4 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -4982,12 +4982,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
goto err_pci_reg;
/* AER (Advanced Error Reporting) hooks */
- err = pci_enable_pcie_error_reporting(pdev);
- if (err) {
- dev_err(&pdev->dev, "pci_enable_pcie_error_reporting failed "
- "0x%x\n", err);
- /* non-fatal, continue */
- }
+ pci_enable_pcie_error_reporting(pdev);
pci_set_master(pdev);
/* PCI config space info */
@@ -5263,7 +5258,6 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
- int err;
/*
* flush_scheduled work may reschedule our watchdog task, so
@@ -5299,10 +5293,7 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
free_netdev(netdev);
/* AER disable */
- err = pci_disable_pcie_error_reporting(pdev);
- if (err)
- dev_err(&pdev->dev,
- "pci_disable_pcie_error_reporting failed 0x%x\n", err);
+ pci_disable_pcie_error_reporting(pdev);
pci_disable_device(pdev);
}
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 33b55f72974..db4b7f1603f 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -258,7 +258,7 @@ static void ax_bump(struct mkiss *ax)
}
if (ax->crcmode != CRC_MODE_SMACK && ax->crcauto) {
printk(KERN_INFO
- "mkiss: %s: Switchting to crc-smack\n",
+ "mkiss: %s: Switching to crc-smack\n",
ax->dev->name);
ax->crcmode = CRC_MODE_SMACK;
}
@@ -272,7 +272,7 @@ static void ax_bump(struct mkiss *ax)
}
if (ax->crcmode != CRC_MODE_FLEX && ax->crcauto) {
printk(KERN_INFO
- "mkiss: %s: Switchting to crc-flexnet\n",
+ "mkiss: %s: Switching to crc-flexnet\n",
ax->dev->name);
ax->crcmode = CRC_MODE_FLEX;
}
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 5d6c1530a8c..714c3a4a44e 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -1246,12 +1246,7 @@ static int __devinit igb_probe(struct pci_dev *pdev,
if (err)
goto err_pci_reg;
- err = pci_enable_pcie_error_reporting(pdev);
- if (err) {
- dev_err(&pdev->dev, "pci_enable_pcie_error_reporting failed "
- "0x%x\n", err);
- /* non-fatal, continue */
- }
+ pci_enable_pcie_error_reporting(pdev);
pci_set_master(pdev);
pci_save_state(pdev);
@@ -1628,7 +1623,6 @@ static void __devexit igb_remove(struct pci_dev *pdev)
struct net_device *netdev = pci_get_drvdata(pdev);
struct igb_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- int err;
/* flush_scheduled work may reschedule our watchdog task, so
* explicitly disable watchdog tasks from being rescheduled */
@@ -1682,10 +1676,7 @@ static void __devexit igb_remove(struct pci_dev *pdev)
free_netdev(netdev);
- err = pci_disable_pcie_error_reporting(pdev);
- if (err)
- dev_err(&pdev->dev,
- "pci_disable_pcie_error_reporting failed 0x%x\n", err);
+ pci_disable_pcie_error_reporting(pdev);
pci_disable_device(pdev);
}
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index e36e951cbc6..aa7286bc436 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -495,7 +495,7 @@ static void veth_take_cap_ack(struct veth_lpar_connection *cnx,
cnx->remote_lp);
} else {
memcpy(&cnx->cap_ack_event, event,
- sizeof(&cnx->cap_ack_event));
+ sizeof(cnx->cap_ack_event));
cnx->state |= VETH_STATE_GOTCAPACK;
veth_kick_statemachine(cnx);
}
diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c
index 56b12f3192f..e2d5343f127 100644
--- a/drivers/net/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ixgbe/ixgbe_82598.c
@@ -425,7 +425,7 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
#endif /* CONFIG_DCB */
default:
hw_dbg(hw, "Flow control param set incorrectly\n");
- ret_val = -IXGBE_ERR_CONFIG;
+ ret_val = IXGBE_ERR_CONFIG;
goto out;
break;
}
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c
index 6621e172df3..40ff120a9ad 100644
--- a/drivers/net/ixgbe/ixgbe_common.c
+++ b/drivers/net/ixgbe/ixgbe_common.c
@@ -1355,9 +1355,7 @@ static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq)
/**
* ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses
* @hw: pointer to hardware structure
- * @addr_list: the list of new addresses
- * @addr_count: number of addresses
- * @next: iterator function to walk the address list
+ * @uc_list: the list of new addresses
*
* The given list replaces any existing list. Clears the secondary addrs from
* receive address registers. Uses unused receive address registers for the
@@ -1663,7 +1661,7 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
#endif /* CONFIG_DCB */
default:
hw_dbg(hw, "Flow control param set incorrectly\n");
- ret_val = -IXGBE_ERR_CONFIG;
+ ret_val = IXGBE_ERR_CONFIG;
goto out;
break;
}
@@ -1734,75 +1732,140 @@ s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
s32 ret_val = 0;
ixgbe_link_speed speed;
u32 pcs_anadv_reg, pcs_lpab_reg, linkstat;
+ u32 links2, anlp1_reg, autoc_reg, links;
bool link_up;
/*
* AN should have completed when the cable was plugged in.
* Look for reasons to bail out. Bail out if:
* - FC autoneg is disabled, or if
- * - we don't have multispeed fiber, or if
- * - we're not running at 1G, or if
- * - link is not up, or if
- * - link is up but AN did not complete, or if
- * - link is up and AN completed but timed out
+ * - link is not up.
*
- * Since we're being called from an LSC, link is already know to be up.
+ * Since we're being called from an LSC, link is already known to be up.
* So use link_up_wait_to_complete=false.
*/
hw->mac.ops.check_link(hw, &speed, &link_up, false);
- linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
-
- if (hw->fc.disable_fc_autoneg ||
- !hw->phy.multispeed_fiber ||
- (speed != IXGBE_LINK_SPEED_1GB_FULL) ||
- !link_up ||
- ((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
- ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
+
+ if (hw->fc.disable_fc_autoneg || (!link_up)) {
hw->fc.fc_was_autonegged = false;
hw->fc.current_mode = hw->fc.requested_mode;
- hw_dbg(hw, "Autoneg FC was skipped.\n");
goto out;
}
/*
+ * On backplane, bail out if
+ * - backplane autoneg was not completed, or if
+ * - link partner is not AN enabled
+ */
+ if (hw->phy.media_type == ixgbe_media_type_backplane) {
+ links = IXGBE_READ_REG(hw, IXGBE_LINKS);
+ links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2);
+ if (((links & IXGBE_LINKS_KX_AN_COMP) == 0) ||
+ ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0)) {
+ hw->fc.fc_was_autonegged = false;
+ hw->fc.current_mode = hw->fc.requested_mode;
+ goto out;
+ }
+ }
+
+ /*
+ * On multispeed fiber at 1g, bail out if
+ * - link is up but AN did not complete, or if
+ * - link is up and AN completed but timed out
+ */
+ if (hw->phy.multispeed_fiber && (speed == IXGBE_LINK_SPEED_1GB_FULL)) {
+ linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
+ if (((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
+ ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
+ hw->fc.fc_was_autonegged = false;
+ hw->fc.current_mode = hw->fc.requested_mode;
+ goto out;
+ }
+ }
+
+ /*
* Read the AN advertisement and LP ability registers and resolve
* local flow control settings accordingly
*/
- pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
- pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
- if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
- (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) {
+ if ((speed == IXGBE_LINK_SPEED_1GB_FULL) &&
+ (hw->phy.media_type != ixgbe_media_type_backplane)) {
+ pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+ pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
+ if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
+ (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) {
+ /*
+ * Now we need to check if the user selected Rx ONLY
+ * of pause frames. In this case, we had to advertise
+ * FULL flow control because we could not advertise RX
+ * ONLY. Hence, we must now check to see if we need to
+ * turn OFF the TRANSMISSION of PAUSE frames.
+ */
+ if (hw->fc.requested_mode == ixgbe_fc_full) {
+ hw->fc.current_mode = ixgbe_fc_full;
+ hw_dbg(hw, "Flow Control = FULL.\n");
+ } else {
+ hw->fc.current_mode = ixgbe_fc_rx_pause;
+ hw_dbg(hw, "Flow Control=RX PAUSE only\n");
+ }
+ } else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
+ (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
+ (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
+ (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
+ hw->fc.current_mode = ixgbe_fc_tx_pause;
+ hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
+ } else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
+ (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
+ !(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
+ (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
+ hw->fc.current_mode = ixgbe_fc_rx_pause;
+ hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
+ } else {
+ hw->fc.current_mode = ixgbe_fc_none;
+ hw_dbg(hw, "Flow Control = NONE.\n");
+ }
+ }
+
+ if (hw->phy.media_type == ixgbe_media_type_backplane) {
/*
- * Now we need to check if the user selected Rx ONLY
- * of pause frames. In this case, we had to advertise
- * FULL flow control because we could not advertise RX
- * ONLY. Hence, we must now check to see if we need to
- * turn OFF the TRANSMISSION of PAUSE frames.
+ * Read the 10g AN autoc and LP ability registers and resolve
+ * local flow control settings accordingly
*/
- if (hw->fc.requested_mode == ixgbe_fc_full) {
- hw->fc.current_mode = ixgbe_fc_full;
- hw_dbg(hw, "Flow Control = FULL.\n");
- } else {
+ autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+ anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1);
+
+ if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
+ (anlp1_reg & IXGBE_ANLP1_SYM_PAUSE)) {
+ /*
+ * Now we need to check if the user selected Rx ONLY
+ * of pause frames. In this case, we had to advertise
+ * FULL flow control because we could not advertise RX
+ * ONLY. Hence, we must now check to see if we need to
+ * turn OFF the TRANSMISSION of PAUSE frames.
+ */
+ if (hw->fc.requested_mode == ixgbe_fc_full) {
+ hw->fc.current_mode = ixgbe_fc_full;
+ hw_dbg(hw, "Flow Control = FULL.\n");
+ } else {
+ hw->fc.current_mode = ixgbe_fc_rx_pause;
+ hw_dbg(hw, "Flow Control=RX PAUSE only\n");
+ }
+ } else if (!(autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
+ (autoc_reg & IXGBE_AUTOC_ASM_PAUSE) &&
+ (anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) &&
+ (anlp1_reg & IXGBE_ANLP1_ASM_PAUSE)) {
+ hw->fc.current_mode = ixgbe_fc_tx_pause;
+ hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
+ } else if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
+ (autoc_reg & IXGBE_AUTOC_ASM_PAUSE) &&
+ !(anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) &&
+ (anlp1_reg & IXGBE_ANLP1_ASM_PAUSE)) {
hw->fc.current_mode = ixgbe_fc_rx_pause;
hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
+ } else {
+ hw->fc.current_mode = ixgbe_fc_none;
+ hw_dbg(hw, "Flow Control = NONE.\n");
}
- } else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
- (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
- (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
- (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
- hw->fc.current_mode = ixgbe_fc_tx_pause;
- hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
- } else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
- (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
- !(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
- (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
- hw->fc.current_mode = ixgbe_fc_rx_pause;
- hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
- } else {
- hw->fc.current_mode = ixgbe_fc_none;
- hw_dbg(hw, "Flow Control = NONE.\n");
}
-
/* Record that current_mode is the result of a successful autoneg */
hw->fc.fc_was_autonegged = true;
@@ -1919,7 +1982,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
#endif /* CONFIG_DCB */
default:
hw_dbg(hw, "Flow control param set incorrectly\n");
- ret_val = -IXGBE_ERR_CONFIG;
+ ret_val = IXGBE_ERR_CONFIG;
goto out;
break;
}
@@ -1927,9 +1990,6 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
- /* Enable and restart autoneg to inform the link partner */
- reg |= IXGBE_PCS1GLCTL_AN_ENABLE | IXGBE_PCS1GLCTL_AN_RESTART;
-
/* Disable AN timeout */
if (hw->fc.strict_ieee)
reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
@@ -1937,6 +1997,70 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
hw_dbg(hw, "Set up FC; PCS1GLCTL = 0x%08X\n", reg);
+ /*
+ * Set up the 10G flow control advertisement registers so the HW
+ * can do fc autoneg once the cable is plugged in. If we end up
+ * using 1g instead, this is harmless.
+ */
+ reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+
+ /*
+ * The possible values of fc.requested_mode are:
+ * 0: Flow control is completely disabled
+ * 1: Rx flow control is enabled (we can receive pause frames,
+ * but not send pause frames).
+ * 2: Tx flow control is enabled (we can send pause frames but
+ * we do not support receiving pause frames).
+ * 3: Both Rx and Tx flow control (symmetric) are enabled.
+ * other: Invalid.
+ */
+ switch (hw->fc.requested_mode) {
+ case ixgbe_fc_none:
+ /* Flow control completely disabled by software override. */
+ reg &= ~(IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE);
+ break;
+ case ixgbe_fc_rx_pause:
+ /*
+ * Rx Flow control is enabled and Tx Flow control is
+ * disabled by software override. Since there really
+ * isn't a way to advertise that we are capable of RX
+ * Pause ONLY, we will advertise that we support both
+ * symmetric and asymmetric Rx PAUSE. Later, we will
+ * disable the adapter's ability to send PAUSE frames.
+ */
+ reg |= (IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE);
+ break;
+ case ixgbe_fc_tx_pause:
+ /*
+ * Tx Flow control is enabled, and Rx Flow control is
+ * disabled by software override.
+ */
+ reg |= (IXGBE_AUTOC_ASM_PAUSE);
+ reg &= ~(IXGBE_AUTOC_SYM_PAUSE);
+ break;
+ case ixgbe_fc_full:
+ /* Flow control (both Rx and Tx) is enabled by SW override. */
+ reg |= (IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE);
+ break;
+#ifdef CONFIG_DCB
+ case ixgbe_fc_pfc:
+ goto out;
+ break;
+#endif /* CONFIG_DCB */
+ default:
+ hw_dbg(hw, "Flow control param set incorrectly\n");
+ ret_val = IXGBE_ERR_CONFIG;
+ goto out;
+ break;
+ }
+ /*
+ * AUTOC restart handles negotiation of 1G and 10G. There is
+ * no need to set the PCS1GCTL register.
+ */
+ reg |= IXGBE_AUTOC_AN_RESTART;
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg);
+ hw_dbg(hw, "Set up FC; IXGBE_AUTOC = 0x%08X\n", reg);
+
out:
return ret_val;
}
@@ -2000,7 +2124,7 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
while (timeout) {
if (ixgbe_get_eeprom_semaphore(hw))
- return -IXGBE_ERR_SWFW_SYNC;
+ return IXGBE_ERR_SWFW_SYNC;
gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
if (!(gssr & (fwmask | swmask)))
@@ -2017,7 +2141,7 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
if (!timeout) {
hw_dbg(hw, "Driver can't access resource, GSSR timeout.\n");
- return -IXGBE_ERR_SWFW_SYNC;
+ return IXGBE_ERR_SWFW_SYNC;
}
gssr |= swmask;
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 53b0a668025..fa314cb005a 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -53,6 +53,10 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = {
{"tx_packets", IXGBE_STAT(net_stats.tx_packets)},
{"rx_bytes", IXGBE_STAT(net_stats.rx_bytes)},
{"tx_bytes", IXGBE_STAT(net_stats.tx_bytes)},
+ {"rx_pkts_nic", IXGBE_STAT(stats.gprc)},
+ {"tx_pkts_nic", IXGBE_STAT(stats.gptc)},
+ {"rx_bytes_nic", IXGBE_STAT(stats.gorc)},
+ {"tx_bytes_nic", IXGBE_STAT(stats.gotc)},
{"lsc_int", IXGBE_STAT(lsc_int)},
{"tx_busy", IXGBE_STAT(tx_busy)},
{"non_eop_descs", IXGBE_STAT(non_eop_descs)},
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index c407bd9de0d..28fbb9d281f 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -49,7 +49,7 @@ char ixgbe_driver_name[] = "ixgbe";
static const char ixgbe_driver_string[] =
"Intel(R) 10 Gigabit PCI Express Network Driver";
-#define DRV_VERSION "2.0.37-k2"
+#define DRV_VERSION "2.0.44-k2"
const char ixgbe_driver_version[] = DRV_VERSION;
static char ixgbe_copyright[] = "Copyright (c) 1999-2009 Intel Corporation.";
@@ -1885,12 +1885,29 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0);
adapter->tx_ring[i].head = IXGBE_TDH(j);
adapter->tx_ring[i].tail = IXGBE_TDT(j);
- /* Disable Tx Head Writeback RO bit, since this hoses
+ /*
+ * Disable Tx Head Writeback RO bit, since this hoses
* bookkeeping if things aren't delivered in order.
*/
- txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j));
+ switch (hw->mac.type) {
+ case ixgbe_mac_82598EB:
+ txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j));
+ break;
+ case ixgbe_mac_82599EB:
+ default:
+ txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(j));
+ break;
+ }
txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
- IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl);
+ switch (hw->mac.type) {
+ case ixgbe_mac_82598EB:
+ IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl);
+ break;
+ case ixgbe_mac_82599EB:
+ default:
+ IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(j), txctrl);
+ break;
+ }
}
if (hw->mac.type == ixgbe_mac_82599EB) {
/* We enable 8 traffic classes, DCB only */
@@ -4432,10 +4449,13 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
/* 82598 hardware only has a 32 bit counter in the high register */
if (hw->mac.type == ixgbe_mac_82599EB) {
+ u64 tmp;
adapter->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GORCL);
- IXGBE_READ_REG(hw, IXGBE_GORCH); /* to clear */
+ tmp = IXGBE_READ_REG(hw, IXGBE_GORCH) & 0xF; /* 4 high bits of GORC */
+ adapter->stats.gorc += (tmp << 32);
adapter->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL);
- IXGBE_READ_REG(hw, IXGBE_GOTCH); /* to clear */
+ tmp = IXGBE_READ_REG(hw, IXGBE_GOTCH) & 0xF; /* 4 high bits of GOTC */
+ adapter->stats.gotc += (tmp << 32);
adapter->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORL);
IXGBE_READ_REG(hw, IXGBE_TORH); /* to clear */
adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
@@ -5071,7 +5091,6 @@ static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb,
/* Right now, we support IPv4 only */
struct ixgbe_atr_input atr_input;
struct tcphdr *th;
- struct udphdr *uh;
struct iphdr *iph = ip_hdr(skb);
struct ethhdr *eth = (struct ethhdr *)skb->data;
u16 vlan_id, src_port, dst_port, flex_bytes;
@@ -5085,12 +5104,6 @@ static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb,
dst_port = th->dest;
l4type |= IXGBE_ATR_L4TYPE_TCP;
/* l4type IPv4 type is 0, no need to assign */
- } else if(iph->protocol == IPPROTO_UDP) {
- uh = udp_hdr(skb);
- src_port = uh->source;
- dst_port = uh->dest;
- l4type |= IXGBE_ATR_L4TYPE_UDP;
- /* l4type IPv4 type is 0, no need to assign */
} else {
/* Unsupported L4 header, just bail here */
return;
@@ -5494,12 +5507,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
goto err_pci_reg;
}
- err = pci_enable_pcie_error_reporting(pdev);
- if (err) {
- dev_err(&pdev->dev, "pci_enable_pcie_error_reporting failed "
- "0x%x\n", err);
- /* non-fatal, continue */
- }
+ pci_enable_pcie_error_reporting(pdev);
pci_set_master(pdev);
pci_save_state(pdev);
@@ -5808,7 +5816,6 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct ixgbe_adapter *adapter = netdev_priv(netdev);
- int err;
set_bit(__IXGBE_DOWN, &adapter->state);
/* clear the module not found bit to make sure the worker won't
@@ -5859,10 +5866,7 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
free_netdev(netdev);
- err = pci_disable_pcie_error_reporting(pdev);
- if (err)
- dev_err(&pdev->dev,
- "pci_disable_pcie_error_reporting failed 0x%x\n", err);
+ pci_disable_pcie_error_reporting(pdev);
pci_disable_device(pdev);
}
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index 8761d7899f7..7c93e923bf2 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -1336,6 +1336,8 @@
#define IXGBE_AUTOC_KX4_SUPP 0x80000000
#define IXGBE_AUTOC_KX_SUPP 0x40000000
#define IXGBE_AUTOC_PAUSE 0x30000000
+#define IXGBE_AUTOC_ASM_PAUSE 0x20000000
+#define IXGBE_AUTOC_SYM_PAUSE 0x10000000
#define IXGBE_AUTOC_RF 0x08000000
#define IXGBE_AUTOC_PD_TMR 0x06000000
#define IXGBE_AUTOC_AN_RX_LOOSE 0x01000000
@@ -1404,6 +1406,8 @@
#define IXGBE_LINK_UP_TIME 90 /* 9.0 Seconds */
#define IXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */
+#define IXGBE_LINKS2_AN_SUPPORTED 0x00000040
+
/* PCS1GLSTA Bit Masks */
#define IXGBE_PCS1GLSTA_LINK_OK 1
#define IXGBE_PCS1GLSTA_SYNK_OK 0x10
@@ -1424,6 +1428,11 @@
#define IXGBE_PCS1GLCTL_AN_ENABLE 0x10000
#define IXGBE_PCS1GLCTL_AN_RESTART 0x20000
+/* ANLP1 Bit Masks */
+#define IXGBE_ANLP1_PAUSE 0x0C00
+#define IXGBE_ANLP1_SYM_PAUSE 0x0400
+#define IXGBE_ANLP1_ASM_PAUSE 0x0800
+
/* SW Semaphore Register bitmasks */
#define IXGBE_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */
#define IXGBE_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */
diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c
new file mode 100644
index 00000000000..0be14d702be
--- /dev/null
+++ b/drivers/net/ks8851_mll.c
@@ -0,0 +1,1697 @@
+/**
+ * drivers/net/ks8851_mll.c
+ * Copyright (c) 2009 Micrel Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/**
+ * Supports:
+ * KS8851 16bit MLL chip from Micrel Inc.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/cache.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+
+#define DRV_NAME "ks8851_mll"
+
+static u8 KS_DEFAULT_MAC_ADDRESS[] = { 0x00, 0x10, 0xA1, 0x86, 0x95, 0x11 };
+#define MAX_RECV_FRAMES 32
+#define MAX_BUF_SIZE 2048
+#define TX_BUF_SIZE 2000
+#define RX_BUF_SIZE 2000
+
+#define KS_CCR 0x08
+#define CCR_EEPROM (1 << 9)
+#define CCR_SPI (1 << 8)
+#define CCR_8BIT (1 << 7)
+#define CCR_16BIT (1 << 6)
+#define CCR_32BIT (1 << 5)
+#define CCR_SHARED (1 << 4)
+#define CCR_32PIN (1 << 0)
+
+/* MAC address registers */
+#define KS_MARL 0x10
+#define KS_MARM 0x12
+#define KS_MARH 0x14
+
+#define KS_OBCR 0x20
+#define OBCR_ODS_16MA (1 << 6)
+
+#define KS_EEPCR 0x22
+#define EEPCR_EESA (1 << 4)
+#define EEPCR_EESB (1 << 3)
+#define EEPCR_EEDO (1 << 2)
+#define EEPCR_EESCK (1 << 1)
+#define EEPCR_EECS (1 << 0)
+
+#define KS_MBIR 0x24
+#define MBIR_TXMBF (1 << 12)
+#define MBIR_TXMBFA (1 << 11)
+#define MBIR_RXMBF (1 << 4)
+#define MBIR_RXMBFA (1 << 3)
+
+#define KS_GRR 0x26
+#define GRR_QMU (1 << 1)
+#define GRR_GSR (1 << 0)
+
+#define KS_WFCR 0x2A
+#define WFCR_MPRXE (1 << 7)
+#define WFCR_WF3E (1 << 3)
+#define WFCR_WF2E (1 << 2)
+#define WFCR_WF1E (1 << 1)
+#define WFCR_WF0E (1 << 0)
+
+#define KS_WF0CRC0 0x30
+#define KS_WF0CRC1 0x32
+#define KS_WF0BM0 0x34
+#define KS_WF0BM1 0x36
+#define KS_WF0BM2 0x38
+#define KS_WF0BM3 0x3A
+
+#define KS_WF1CRC0 0x40
+#define KS_WF1CRC1 0x42
+#define KS_WF1BM0 0x44
+#define KS_WF1BM1 0x46
+#define KS_WF1BM2 0x48
+#define KS_WF1BM3 0x4A
+
+#define KS_WF2CRC0 0x50
+#define KS_WF2CRC1 0x52
+#define KS_WF2BM0 0x54
+#define KS_WF2BM1 0x56
+#define KS_WF2BM2 0x58
+#define KS_WF2BM3 0x5A
+
+#define KS_WF3CRC0 0x60
+#define KS_WF3CRC1 0x62
+#define KS_WF3BM0 0x64
+#define KS_WF3BM1 0x66
+#define KS_WF3BM2 0x68
+#define KS_WF3BM3 0x6A
+
+#define KS_TXCR 0x70
+#define TXCR_TCGICMP (1 << 8)
+#define TXCR_TCGUDP (1 << 7)
+#define TXCR_TCGTCP (1 << 6)
+#define TXCR_TCGIP (1 << 5)
+#define TXCR_FTXQ (1 << 4)
+#define TXCR_TXFCE (1 << 3)
+#define TXCR_TXPE (1 << 2)
+#define TXCR_TXCRC (1 << 1)
+#define TXCR_TXE (1 << 0)
+
+#define KS_TXSR 0x72
+#define TXSR_TXLC (1 << 13)
+#define TXSR_TXMC (1 << 12)
+#define TXSR_TXFID_MASK (0x3f << 0)
+#define TXSR_TXFID_SHIFT (0)
+#define TXSR_TXFID_GET(_v) (((_v) >> 0) & 0x3f)
+
+
+#define KS_RXCR1 0x74
+#define RXCR1_FRXQ (1 << 15)
+#define RXCR1_RXUDPFCC (1 << 14)
+#define RXCR1_RXTCPFCC (1 << 13)
+#define RXCR1_RXIPFCC (1 << 12)
+#define RXCR1_RXPAFMA (1 << 11)
+#define RXCR1_RXFCE (1 << 10)
+#define RXCR1_RXEFE (1 << 9)
+#define RXCR1_RXMAFMA (1 << 8)
+#define RXCR1_RXBE (1 << 7)
+#define RXCR1_RXME (1 << 6)
+#define RXCR1_RXUE (1 << 5)
+#define RXCR1_RXAE (1 << 4)
+#define RXCR1_RXINVF (1 << 1)
+#define RXCR1_RXE (1 << 0)
+#define RXCR1_FILTER_MASK (RXCR1_RXINVF | RXCR1_RXAE | \
+ RXCR1_RXMAFMA | RXCR1_RXPAFMA)
+
+#define KS_RXCR2 0x76
+#define RXCR2_SRDBL_MASK (0x7 << 5)
+#define RXCR2_SRDBL_SHIFT (5)
+#define RXCR2_SRDBL_4B (0x0 << 5)
+#define RXCR2_SRDBL_8B (0x1 << 5)
+#define RXCR2_SRDBL_16B (0x2 << 5)
+#define RXCR2_SRDBL_32B (0x3 << 5)
+/* #define RXCR2_SRDBL_FRAME (0x4 << 5) */
+#define RXCR2_IUFFP (1 << 4)
+#define RXCR2_RXIUFCEZ (1 << 3)
+#define RXCR2_UDPLFE (1 << 2)
+#define RXCR2_RXICMPFCC (1 << 1)
+#define RXCR2_RXSAF (1 << 0)
+
+#define KS_TXMIR 0x78
+
+#define KS_RXFHSR 0x7C
+#define RXFSHR_RXFV (1 << 15)
+#define RXFSHR_RXICMPFCS (1 << 13)
+#define RXFSHR_RXIPFCS (1 << 12)
+#define RXFSHR_RXTCPFCS (1 << 11)
+#define RXFSHR_RXUDPFCS (1 << 10)
+#define RXFSHR_RXBF (1 << 7)
+#define RXFSHR_RXMF (1 << 6)
+#define RXFSHR_RXUF (1 << 5)
+#define RXFSHR_RXMR (1 << 4)
+#define RXFSHR_RXFT (1 << 3)
+#define RXFSHR_RXFTL (1 << 2)
+#define RXFSHR_RXRF (1 << 1)
+#define RXFSHR_RXCE (1 << 0)
+#define RXFSHR_ERR (RXFSHR_RXCE | RXFSHR_RXRF |\
+ RXFSHR_RXFTL | RXFSHR_RXMR |\
+ RXFSHR_RXICMPFCS | RXFSHR_RXIPFCS |\
+ RXFSHR_RXTCPFCS)
+#define KS_RXFHBCR 0x7E
+#define RXFHBCR_CNT_MASK 0x0FFF
+
+#define KS_TXQCR 0x80
+#define TXQCR_AETFE (1 << 2)
+#define TXQCR_TXQMAM (1 << 1)
+#define TXQCR_METFE (1 << 0)
+
+#define KS_RXQCR 0x82
+#define RXQCR_RXDTTS (1 << 12)
+#define RXQCR_RXDBCTS (1 << 11)
+#define RXQCR_RXFCTS (1 << 10)
+#define RXQCR_RXIPHTOE (1 << 9)
+#define RXQCR_RXDTTE (1 << 7)
+#define RXQCR_RXDBCTE (1 << 6)
+#define RXQCR_RXFCTE (1 << 5)
+#define RXQCR_ADRFE (1 << 4)
+#define RXQCR_SDA (1 << 3)
+#define RXQCR_RRXEF (1 << 0)
+#define RXQCR_CMD_CNTL (RXQCR_RXFCTE|RXQCR_ADRFE)
+
+#define KS_TXFDPR 0x84
+#define TXFDPR_TXFPAI (1 << 14)
+#define TXFDPR_TXFP_MASK (0x7ff << 0)
+#define TXFDPR_TXFP_SHIFT (0)
+
+#define KS_RXFDPR 0x86
+#define RXFDPR_RXFPAI (1 << 14)
+
+#define KS_RXDTTR 0x8C
+#define KS_RXDBCTR 0x8E
+
+#define KS_IER 0x90
+#define KS_ISR 0x92
+#define IRQ_LCI (1 << 15)
+#define IRQ_TXI (1 << 14)
+#define IRQ_RXI (1 << 13)
+#define IRQ_RXOI (1 << 11)
+#define IRQ_TXPSI (1 << 9)
+#define IRQ_RXPSI (1 << 8)
+#define IRQ_TXSAI (1 << 6)
+#define IRQ_RXWFDI (1 << 5)
+#define IRQ_RXMPDI (1 << 4)
+#define IRQ_LDI (1 << 3)
+#define IRQ_EDI (1 << 2)
+#define IRQ_SPIBEI (1 << 1)
+#define IRQ_DEDI (1 << 0)
+
+#define KS_RXFCTR 0x9C
+#define RXFCTR_THRESHOLD_MASK 0x00FF
+
+#define KS_RXFC 0x9D
+#define RXFCTR_RXFC_MASK (0xff << 8)
+#define RXFCTR_RXFC_SHIFT (8)
+#define RXFCTR_RXFC_GET(_v) (((_v) >> 8) & 0xff)
+#define RXFCTR_RXFCT_MASK (0xff << 0)
+#define RXFCTR_RXFCT_SHIFT (0)
+
+#define KS_TXNTFSR 0x9E
+
+#define KS_MAHTR0 0xA0
+#define KS_MAHTR1 0xA2
+#define KS_MAHTR2 0xA4
+#define KS_MAHTR3 0xA6
+
+#define KS_FCLWR 0xB0
+#define KS_FCHWR 0xB2
+#define KS_FCOWR 0xB4
+
+#define KS_CIDER 0xC0
+#define CIDER_ID 0x8870
+#define CIDER_REV_MASK (0x7 << 1)
+#define CIDER_REV_SHIFT (1)
+#define CIDER_REV_GET(_v) (((_v) >> 1) & 0x7)
+
+#define KS_CGCR 0xC6
+#define KS_IACR 0xC8
+#define IACR_RDEN (1 << 12)
+#define IACR_TSEL_MASK (0x3 << 10)
+#define IACR_TSEL_SHIFT (10)
+#define IACR_TSEL_MIB (0x3 << 10)
+#define IACR_ADDR_MASK (0x1f << 0)
+#define IACR_ADDR_SHIFT (0)
+
+#define KS_IADLR 0xD0
+#define KS_IAHDR 0xD2
+
+#define KS_PMECR 0xD4
+#define PMECR_PME_DELAY (1 << 14)
+#define PMECR_PME_POL (1 << 12)
+#define PMECR_WOL_WAKEUP (1 << 11)
+#define PMECR_WOL_MAGICPKT (1 << 10)
+#define PMECR_WOL_LINKUP (1 << 9)
+#define PMECR_WOL_ENERGY (1 << 8)
+#define PMECR_AUTO_WAKE_EN (1 << 7)
+#define PMECR_WAKEUP_NORMAL (1 << 6)
+#define PMECR_WKEVT_MASK (0xf << 2)
+#define PMECR_WKEVT_SHIFT (2)
+#define PMECR_WKEVT_GET(_v) (((_v) >> 2) & 0xf)
+#define PMECR_WKEVT_ENERGY (0x1 << 2)
+#define PMECR_WKEVT_LINK (0x2 << 2)
+#define PMECR_WKEVT_MAGICPKT (0x4 << 2)
+#define PMECR_WKEVT_FRAME (0x8 << 2)
+#define PMECR_PM_MASK (0x3 << 0)
+#define PMECR_PM_SHIFT (0)
+#define PMECR_PM_NORMAL (0x0 << 0)
+#define PMECR_PM_ENERGY (0x1 << 0)
+#define PMECR_PM_SOFTDOWN (0x2 << 0)
+#define PMECR_PM_POWERSAVE (0x3 << 0)
+
+/* Standard MII PHY data */
+#define KS_P1MBCR 0xE4
+#define P1MBCR_FORCE_FDX (1 << 8)
+
+#define KS_P1MBSR 0xE6
+#define P1MBSR_AN_COMPLETE (1 << 5)
+#define P1MBSR_AN_CAPABLE (1 << 3)
+#define P1MBSR_LINK_UP (1 << 2)
+
+#define KS_PHY1ILR 0xE8
+#define KS_PHY1IHR 0xEA
+#define KS_P1ANAR 0xEC
+#define KS_P1ANLPR 0xEE
+
+#define KS_P1SCLMD 0xF4
+#define P1SCLMD_LEDOFF (1 << 15)
+#define P1SCLMD_TXIDS (1 << 14)
+#define P1SCLMD_RESTARTAN (1 << 13)
+#define P1SCLMD_DISAUTOMDIX (1 << 10)
+#define P1SCLMD_FORCEMDIX (1 << 9)
+#define P1SCLMD_AUTONEGEN (1 << 7)
+#define P1SCLMD_FORCE100 (1 << 6)
+#define P1SCLMD_FORCEFDX (1 << 5)
+#define P1SCLMD_ADV_FLOW (1 << 4)
+#define P1SCLMD_ADV_100BT_FDX (1 << 3)
+#define P1SCLMD_ADV_100BT_HDX (1 << 2)
+#define P1SCLMD_ADV_10BT_FDX (1 << 1)
+#define P1SCLMD_ADV_10BT_HDX (1 << 0)
+
+#define KS_P1CR 0xF6
+#define P1CR_HP_MDIX (1 << 15)
+#define P1CR_REV_POL (1 << 13)
+#define P1CR_OP_100M (1 << 10)
+#define P1CR_OP_FDX (1 << 9)
+#define P1CR_OP_MDI (1 << 7)
+#define P1CR_AN_DONE (1 << 6)
+#define P1CR_LINK_GOOD (1 << 5)
+#define P1CR_PNTR_FLOW (1 << 4)
+#define P1CR_PNTR_100BT_FDX (1 << 3)
+#define P1CR_PNTR_100BT_HDX (1 << 2)
+#define P1CR_PNTR_10BT_FDX (1 << 1)
+#define P1CR_PNTR_10BT_HDX (1 << 0)
+
+/* TX Frame control */
+
+#define TXFR_TXIC (1 << 15)
+#define TXFR_TXFID_MASK (0x3f << 0)
+#define TXFR_TXFID_SHIFT (0)
+
+#define KS_P1SR 0xF8
+#define P1SR_HP_MDIX (1 << 15)
+#define P1SR_REV_POL (1 << 13)
+#define P1SR_OP_100M (1 << 10)
+#define P1SR_OP_FDX (1 << 9)
+#define P1SR_OP_MDI (1 << 7)
+#define P1SR_AN_DONE (1 << 6)
+#define P1SR_LINK_GOOD (1 << 5)
+#define P1SR_PNTR_FLOW (1 << 4)
+#define P1SR_PNTR_100BT_FDX (1 << 3)
+#define P1SR_PNTR_100BT_HDX (1 << 2)
+#define P1SR_PNTR_10BT_FDX (1 << 1)
+#define P1SR_PNTR_10BT_HDX (1 << 0)
+
+#define ENUM_BUS_NONE 0
+#define ENUM_BUS_8BIT 1
+#define ENUM_BUS_16BIT 2
+#define ENUM_BUS_32BIT 3
+
+#define MAX_MCAST_LST 32
+#define HW_MCAST_SIZE 8
+#define MAC_ADDR_LEN 6
+
+/**
+ * union ks_tx_hdr - tx header data
+ * @txb: The header as bytes
+ * @txw: The header as 16bit, little-endian words
+ *
+ * A dual representation of the tx header data to allow
+ * access to individual bytes, and to allow 16bit accesses
+ * with 16bit alignment.
+ */
+union ks_tx_hdr {
+ u8 txb[4];
+ __le16 txw[2];
+};
+
+/**
+ * struct ks_net - KS8851 driver private data
+ * @net_device : The network device we're bound to
+ * @hw_addr : start address of data register.
+ * @hw_addr_cmd : start address of command register.
+ * @txh : temporaly buffer to save status/length.
+ * @lock : Lock to ensure that the device is not accessed when busy.
+ * @pdev : Pointer to platform device.
+ * @mii : The MII state information for the mii calls.
+ * @frame_head_info : frame header information for multi-pkt rx.
+ * @statelock : Lock on this structure for tx list.
+ * @msg_enable : The message flags controlling driver output (see ethtool).
+ * @frame_cnt : number of frames received.
+ * @bus_width : i/o bus width.
+ * @irq : irq number assigned to this device.
+ * @rc_rxqcr : Cached copy of KS_RXQCR.
+ * @rc_txcr : Cached copy of KS_TXCR.
+ * @rc_ier : Cached copy of KS_IER.
+ * @sharedbus : Multipex(addr and data bus) mode indicator.
+ * @cmd_reg_cache : command register cached.
+ * @cmd_reg_cache_int : command register cached. Used in the irq handler.
+ * @promiscuous : promiscuous mode indicator.
+ * @all_mcast : mutlicast indicator.
+ * @mcast_lst_size : size of multicast list.
+ * @mcast_lst : multicast list.
+ * @mcast_bits : multicast enabed.
+ * @mac_addr : MAC address assigned to this device.
+ * @fid : frame id.
+ * @extra_byte : number of extra byte prepended rx pkt.
+ * @enabled : indicator this device works.
+ *
+ * The @lock ensures that the chip is protected when certain operations are
+ * in progress. When the read or write packet transfer is in progress, most
+ * of the chip registers are not accessible until the transfer is finished and
+ * the DMA has been de-asserted.
+ *
+ * The @statelock is used to protect information in the structure which may
+ * need to be accessed via several sources, such as the network driver layer
+ * or one of the work queues.
+ *
+ */
+
+/* Receive multiplex framer header info */
+struct type_frame_head {
+ u16 sts; /* Frame status */
+ u16 len; /* Byte count */
+};
+
+struct ks_net {
+ struct net_device *netdev;
+ void __iomem *hw_addr;
+ void __iomem *hw_addr_cmd;
+ union ks_tx_hdr txh ____cacheline_aligned;
+ struct mutex lock; /* spinlock to be interrupt safe */
+ struct platform_device *pdev;
+ struct mii_if_info mii;
+ struct type_frame_head *frame_head_info;
+ spinlock_t statelock;
+ u32 msg_enable;
+ u32 frame_cnt;
+ int bus_width;
+ int irq;
+
+ u16 rc_rxqcr;
+ u16 rc_txcr;
+ u16 rc_ier;
+ u16 sharedbus;
+ u16 cmd_reg_cache;
+ u16 cmd_reg_cache_int;
+ u16 promiscuous;
+ u16 all_mcast;
+ u16 mcast_lst_size;
+ u8 mcast_lst[MAX_MCAST_LST][MAC_ADDR_LEN];
+ u8 mcast_bits[HW_MCAST_SIZE];
+ u8 mac_addr[6];
+ u8 fid;
+ u8 extra_byte;
+ u8 enabled;
+};
+
+static int msg_enable;
+
+#define ks_info(_ks, _msg...) dev_info(&(_ks)->pdev->dev, _msg)
+#define ks_warn(_ks, _msg...) dev_warn(&(_ks)->pdev->dev, _msg)
+#define ks_dbg(_ks, _msg...) dev_dbg(&(_ks)->pdev->dev, _msg)
+#define ks_err(_ks, _msg...) dev_err(&(_ks)->pdev->dev, _msg)
+
+#define BE3 0x8000 /* Byte Enable 3 */
+#define BE2 0x4000 /* Byte Enable 2 */
+#define BE1 0x2000 /* Byte Enable 1 */
+#define BE0 0x1000 /* Byte Enable 0 */
+
+/**
+ * register read/write calls.
+ *
+ * All these calls issue transactions to access the chip's registers. They
+ * all require that the necessary lock is held to prevent accesses when the
+ * chip is busy transfering packet data (RX/TX FIFO accesses).
+ */
+
+/**
+ * ks_rdreg8 - read 8 bit register from device
+ * @ks : The chip information
+ * @offset: The register address
+ *
+ * Read a 8bit register from the chip, returning the result
+ */
+static u8 ks_rdreg8(struct ks_net *ks, int offset)
+{
+ u16 data;
+ u8 shift_bit = offset & 0x03;
+ u8 shift_data = (offset & 1) << 3;
+ ks->cmd_reg_cache = (u16) offset | (u16)(BE0 << shift_bit);
+ iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd);
+ data = ioread16(ks->hw_addr);
+ return (u8)(data >> shift_data);
+}
+
+/**
+ * ks_rdreg16 - read 16 bit register from device
+ * @ks : The chip information
+ * @offset: The register address
+ *
+ * Read a 16bit register from the chip, returning the result
+ */
+
+static u16 ks_rdreg16(struct ks_net *ks, int offset)
+{
+ ks->cmd_reg_cache = (u16)offset | ((BE1 | BE0) << (offset & 0x02));
+ iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd);
+ return ioread16(ks->hw_addr);
+}
+
+/**
+ * ks_wrreg8 - write 8bit register value to chip
+ * @ks: The chip information
+ * @offset: The register address
+ * @value: The value to write
+ *
+ */
+static void ks_wrreg8(struct ks_net *ks, int offset, u8 value)
+{
+ u8 shift_bit = (offset & 0x03);
+ u16 value_write = (u16)(value << ((offset & 1) << 3));
+ ks->cmd_reg_cache = (u16)offset | (BE0 << shift_bit);
+ iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd);
+ iowrite16(value_write, ks->hw_addr);
+}
+
+/**
+ * ks_wrreg16 - write 16bit register value to chip
+ * @ks: The chip information
+ * @offset: The register address
+ * @value: The value to write
+ *
+ */
+
+static void ks_wrreg16(struct ks_net *ks, int offset, u16 value)
+{
+ ks->cmd_reg_cache = (u16)offset | ((BE1 | BE0) << (offset & 0x02));
+ iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd);
+ iowrite16(value, ks->hw_addr);
+}
+
+/**
+ * ks_inblk - read a block of data from QMU. This is called after sudo DMA mode enabled.
+ * @ks: The chip state
+ * @wptr: buffer address to save data
+ * @len: length in byte to read
+ *
+ */
+static inline void ks_inblk(struct ks_net *ks, u16 *wptr, u32 len)
+{
+ len >>= 1;
+ while (len--)
+ *wptr++ = (u16)ioread16(ks->hw_addr);
+}
+
+/**
+ * ks_outblk - write data to QMU. This is called after sudo DMA mode enabled.
+ * @ks: The chip information
+ * @wptr: buffer address
+ * @len: length in byte to write
+ *
+ */
+static inline void ks_outblk(struct ks_net *ks, u16 *wptr, u32 len)
+{
+ len >>= 1;
+ while (len--)
+ iowrite16(*wptr++, ks->hw_addr);
+}
+
+/**
+ * ks_tx_fifo_space - return the available hardware buffer size.
+ * @ks: The chip information
+ *
+ */
+static inline u16 ks_tx_fifo_space(struct ks_net *ks)
+{
+ return ks_rdreg16(ks, KS_TXMIR) & 0x1fff;
+}
+
+/**
+ * ks_save_cmd_reg - save the command register from the cache.
+ * @ks: The chip information
+ *
+ */
+static inline void ks_save_cmd_reg(struct ks_net *ks)
+{
+ /*ks8851 MLL has a bug to read back the command register.
+ * So rely on software to save the content of command register.
+ */
+ ks->cmd_reg_cache_int = ks->cmd_reg_cache;
+}
+
+/**
+ * ks_restore_cmd_reg - restore the command register from the cache and
+ * write to hardware register.
+ * @ks: The chip information
+ *
+ */
+static inline void ks_restore_cmd_reg(struct ks_net *ks)
+{
+ ks->cmd_reg_cache = ks->cmd_reg_cache_int;
+ iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd);
+}
+
+/**
+ * ks_set_powermode - set power mode of the device
+ * @ks: The chip information
+ * @pwrmode: The power mode value to write to KS_PMECR.
+ *
+ * Change the power mode of the chip.
+ */
+static void ks_set_powermode(struct ks_net *ks, unsigned pwrmode)
+{
+ unsigned pmecr;
+
+ if (netif_msg_hw(ks))
+ ks_dbg(ks, "setting power mode %d\n", pwrmode);
+
+ ks_rdreg16(ks, KS_GRR);
+ pmecr = ks_rdreg16(ks, KS_PMECR);
+ pmecr &= ~PMECR_PM_MASK;
+ pmecr |= pwrmode;
+
+ ks_wrreg16(ks, KS_PMECR, pmecr);
+}
+
+/**
+ * ks_read_config - read chip configuration of bus width.
+ * @ks: The chip information
+ *
+ */
+static void ks_read_config(struct ks_net *ks)
+{
+ u16 reg_data = 0;
+
+ /* Regardless of bus width, 8 bit read should always work.*/
+ reg_data = ks_rdreg8(ks, KS_CCR) & 0x00FF;
+ reg_data |= ks_rdreg8(ks, KS_CCR+1) << 8;
+
+ /* addr/data bus are multiplexed */
+ ks->sharedbus = (reg_data & CCR_SHARED) == CCR_SHARED;
+
+ /* There are garbage data when reading data from QMU,
+ depending on bus-width.
+ */
+
+ if (reg_data & CCR_8BIT) {
+ ks->bus_width = ENUM_BUS_8BIT;
+ ks->extra_byte = 1;
+ } else if (reg_data & CCR_16BIT) {
+ ks->bus_width = ENUM_BUS_16BIT;
+ ks->extra_byte = 2;
+ } else {
+ ks->bus_width = ENUM_BUS_32BIT;
+ ks->extra_byte = 4;
+ }
+}
+
+/**
+ * ks_soft_reset - issue one of the soft reset to the device
+ * @ks: The device state.
+ * @op: The bit(s) to set in the GRR
+ *
+ * Issue the relevant soft-reset command to the device's GRR register
+ * specified by @op.
+ *
+ * Note, the delays are in there as a caution to ensure that the reset
+ * has time to take effect and then complete. Since the datasheet does
+ * not currently specify the exact sequence, we have chosen something
+ * that seems to work with our device.
+ */
+static void ks_soft_reset(struct ks_net *ks, unsigned op)
+{
+ /* Disable interrupt first */
+ ks_wrreg16(ks, KS_IER, 0x0000);
+ ks_wrreg16(ks, KS_GRR, op);
+ mdelay(10); /* wait a short time to effect reset */
+ ks_wrreg16(ks, KS_GRR, 0);
+ mdelay(1); /* wait for condition to clear */
+}
+
+
+/**
+ * ks_read_qmu - read 1 pkt data from the QMU.
+ * @ks: The chip information
+ * @buf: buffer address to save 1 pkt
+ * @len: Pkt length
+ * Here is the sequence to read 1 pkt:
+ * 1. set sudo DMA mode
+ * 2. read prepend data
+ * 3. read pkt data
+ * 4. reset sudo DMA Mode
+ */
+static inline void ks_read_qmu(struct ks_net *ks, u16 *buf, u32 len)
+{
+ u32 r = ks->extra_byte & 0x1 ;
+ u32 w = ks->extra_byte - r;
+
+ /* 1. set sudo DMA mode */
+ ks_wrreg16(ks, KS_RXFDPR, RXFDPR_RXFPAI);
+ ks_wrreg8(ks, KS_RXQCR, (ks->rc_rxqcr | RXQCR_SDA) & 0xff);
+
+ /* 2. read prepend data */
+ /**
+ * read 4 + extra bytes and discard them.
+ * extra bytes for dummy, 2 for status, 2 for len
+ */
+
+ /* use likely(r) for 8 bit access for performance */
+ if (unlikely(r))
+ ioread8(ks->hw_addr);
+ ks_inblk(ks, buf, w + 2 + 2);
+
+ /* 3. read pkt data */
+ ks_inblk(ks, buf, ALIGN(len, 4));
+
+ /* 4. reset sudo DMA Mode */
+ ks_wrreg8(ks, KS_RXQCR, ks->rc_rxqcr);
+}
+
+/**
+ * ks_rcv - read multiple pkts data from the QMU.
+ * @ks: The chip information
+ * @netdev: The network device being opened.
+ *
+ * Read all of header information before reading pkt content.
+ * It is not allowed only port of pkts in QMU after issuing
+ * interrupt ack.
+ */
+static void ks_rcv(struct ks_net *ks, struct net_device *netdev)
+{
+ u32 i;
+ struct type_frame_head *frame_hdr = ks->frame_head_info;
+ struct sk_buff *skb;
+
+ ks->frame_cnt = ks_rdreg16(ks, KS_RXFCTR) >> 8;
+
+ /* read all header information */
+ for (i = 0; i < ks->frame_cnt; i++) {
+ /* Checking Received packet status */
+ frame_hdr->sts = ks_rdreg16(ks, KS_RXFHSR);
+ /* Get packet len from hardware */
+ frame_hdr->len = ks_rdreg16(ks, KS_RXFHBCR);
+ frame_hdr++;
+ }
+
+ frame_hdr = ks->frame_head_info;
+ while (ks->frame_cnt--) {
+ skb = dev_alloc_skb(frame_hdr->len + 16);
+ if (likely(skb && (frame_hdr->sts & RXFSHR_RXFV) &&
+ (frame_hdr->len < RX_BUF_SIZE) && frame_hdr->len)) {
+ skb_reserve(skb, 2);
+ /* read data block including CRC 4 bytes */
+ ks_read_qmu(ks, (u16 *)skb->data, frame_hdr->len + 4);
+ skb_put(skb, frame_hdr->len);
+ skb->dev = netdev;
+ skb->protocol = eth_type_trans(skb, netdev);
+ netif_rx(skb);
+ } else {
+ printk(KERN_ERR "%s: err:skb alloc\n", __func__);
+ ks_wrreg16(ks, KS_RXQCR, (ks->rc_rxqcr | RXQCR_RRXEF));
+ if (skb)
+ dev_kfree_skb_irq(skb);
+ }
+ frame_hdr++;
+ }
+}
+
+/**
+ * ks_update_link_status - link status update.
+ * @netdev: The network device being opened.
+ * @ks: The chip information
+ *
+ */
+
+static void ks_update_link_status(struct net_device *netdev, struct ks_net *ks)
+{
+ /* check the status of the link */
+ u32 link_up_status;
+ if (ks_rdreg16(ks, KS_P1SR) & P1SR_LINK_GOOD) {
+ netif_carrier_on(netdev);
+ link_up_status = true;
+ } else {
+ netif_carrier_off(netdev);
+ link_up_status = false;
+ }
+ if (netif_msg_link(ks))
+ ks_dbg(ks, "%s: %s\n",
+ __func__, link_up_status ? "UP" : "DOWN");
+}
+
+/**
+ * ks_irq - device interrupt handler
+ * @irq: Interrupt number passed from the IRQ hnalder.
+ * @pw: The private word passed to register_irq(), our struct ks_net.
+ *
+ * This is the handler invoked to find out what happened
+ *
+ * Read the interrupt status, work out what needs to be done and then clear
+ * any of the interrupts that are not needed.
+ */
+
+static irqreturn_t ks_irq(int irq, void *pw)
+{
+ struct ks_net *ks = pw;
+ struct net_device *netdev = ks->netdev;
+ u16 status;
+
+ /*this should be the first in IRQ handler */
+ ks_save_cmd_reg(ks);
+
+ status = ks_rdreg16(ks, KS_ISR);
+ if (unlikely(!status)) {
+ ks_restore_cmd_reg(ks);
+ return IRQ_NONE;
+ }
+
+ ks_wrreg16(ks, KS_ISR, status);
+
+ if (likely(status & IRQ_RXI))
+ ks_rcv(ks, netdev);
+
+ if (unlikely(status & IRQ_LCI))
+ ks_update_link_status(netdev, ks);
+
+ if (unlikely(status & IRQ_TXI))
+ netif_wake_queue(netdev);
+
+ if (unlikely(status & IRQ_LDI)) {
+
+ u16 pmecr = ks_rdreg16(ks, KS_PMECR);
+ pmecr &= ~PMECR_WKEVT_MASK;
+ ks_wrreg16(ks, KS_PMECR, pmecr | PMECR_WKEVT_LINK);
+ }
+
+ /* this should be the last in IRQ handler*/
+ ks_restore_cmd_reg(ks);
+ return IRQ_HANDLED;
+}
+
+
+/**
+ * ks_net_open - open network device
+ * @netdev: The network device being opened.
+ *
+ * Called when the network device is marked active, such as a user executing
+ * 'ifconfig up' on the device.
+ */
+static int ks_net_open(struct net_device *netdev)
+{
+ struct ks_net *ks = netdev_priv(netdev);
+ int err;
+
+#define KS_INT_FLAGS (IRQF_DISABLED|IRQF_TRIGGER_LOW)
+ /* lock the card, even if we may not actually do anything
+ * else at the moment.
+ */
+
+ if (netif_msg_ifup(ks))
+ ks_dbg(ks, "%s - entry\n", __func__);
+
+ /* reset the HW */
+ err = request_irq(ks->irq, ks_irq, KS_INT_FLAGS, DRV_NAME, ks);
+
+ if (err) {
+ printk(KERN_ERR "Failed to request IRQ: %d: %d\n",
+ ks->irq, err);
+ return err;
+ }
+
+ if (netif_msg_ifup(ks))
+ ks_dbg(ks, "network device %s up\n", netdev->name);
+
+ return 0;
+}
+
+/**
+ * ks_net_stop - close network device
+ * @netdev: The device being closed.
+ *
+ * Called to close down a network device which has been active. Cancell any
+ * work, shutdown the RX and TX process and then place the chip into a low
+ * power state whilst it is not being used.
+ */
+static int ks_net_stop(struct net_device *netdev)
+{
+ struct ks_net *ks = netdev_priv(netdev);
+
+ if (netif_msg_ifdown(ks))
+ ks_info(ks, "%s: shutting down\n", netdev->name);
+
+ netif_stop_queue(netdev);
+
+ kfree(ks->frame_head_info);
+
+ mutex_lock(&ks->lock);
+
+ /* turn off the IRQs and ack any outstanding */
+ ks_wrreg16(ks, KS_IER, 0x0000);
+ ks_wrreg16(ks, KS_ISR, 0xffff);
+
+ /* shutdown RX process */
+ ks_wrreg16(ks, KS_RXCR1, 0x0000);
+
+ /* shutdown TX process */
+ ks_wrreg16(ks, KS_TXCR, 0x0000);
+
+ /* set powermode to soft power down to save power */
+ ks_set_powermode(ks, PMECR_PM_SOFTDOWN);
+ free_irq(ks->irq, netdev);
+ mutex_unlock(&ks->lock);
+ return 0;
+}
+
+
+/**
+ * ks_write_qmu - write 1 pkt data to the QMU.
+ * @ks: The chip information
+ * @pdata: buffer address to save 1 pkt
+ * @len: Pkt length in byte
+ * Here is the sequence to write 1 pkt:
+ * 1. set sudo DMA mode
+ * 2. write status/length
+ * 3. write pkt data
+ * 4. reset sudo DMA Mode
+ * 5. reset sudo DMA mode
+ * 6. Wait until pkt is out
+ */
+static void ks_write_qmu(struct ks_net *ks, u8 *pdata, u16 len)
+{
+ unsigned fid = ks->fid;
+
+ fid = ks->fid;
+ ks->fid = (ks->fid + 1) & TXFR_TXFID_MASK;
+
+ /* reduce the tx interrupt occurrances. */
+ if (!fid)
+ fid |= TXFR_TXIC; /* irq on completion */
+
+ /* start header at txb[0] to align txw entries */
+ ks->txh.txw[0] = cpu_to_le16(fid);
+ ks->txh.txw[1] = cpu_to_le16(len);
+
+ /* 1. set sudo-DMA mode */
+ ks_wrreg8(ks, KS_RXQCR, (ks->rc_rxqcr | RXQCR_SDA) & 0xff);
+ /* 2. write status/lenth info */
+ ks_outblk(ks, ks->txh.txw, 4);
+ /* 3. write pkt data */
+ ks_outblk(ks, (u16 *)pdata, ALIGN(len, 4));
+ /* 4. reset sudo-DMA mode */
+ ks_wrreg8(ks, KS_RXQCR, ks->rc_rxqcr);
+ /* 5. Enqueue Tx(move the pkt from TX buffer into TXQ) */
+ ks_wrreg16(ks, KS_TXQCR, TXQCR_METFE);
+ /* 6. wait until TXQCR_METFE is auto-cleared */
+ while (ks_rdreg16(ks, KS_TXQCR) & TXQCR_METFE)
+ ;
+}
+
+static void ks_disable_int(struct ks_net *ks)
+{
+ ks_wrreg16(ks, KS_IER, 0x0000);
+} /* ks_disable_int */
+
+static void ks_enable_int(struct ks_net *ks)
+{
+ ks_wrreg16(ks, KS_IER, ks->rc_ier);
+} /* ks_enable_int */
+
+/**
+ * ks_start_xmit - transmit packet
+ * @skb : The buffer to transmit
+ * @netdev : The device used to transmit the packet.
+ *
+ * Called by the network layer to transmit the @skb.
+ * spin_lock_irqsave is required because tx and rx should be mutual exclusive.
+ * So while tx is in-progress, prevent IRQ interrupt from happenning.
+ */
+static int ks_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+ int retv = NETDEV_TX_OK;
+ struct ks_net *ks = netdev_priv(netdev);
+
+ disable_irq(netdev->irq);
+ ks_disable_int(ks);
+ spin_lock(&ks->statelock);
+
+ /* Extra space are required:
+ * 4 byte for alignment, 4 for status/length, 4 for CRC
+ */
+
+ if (likely(ks_tx_fifo_space(ks) >= skb->len + 12)) {
+ ks_write_qmu(ks, skb->data, skb->len);
+ dev_kfree_skb(skb);
+ } else
+ retv = NETDEV_TX_BUSY;
+ spin_unlock(&ks->statelock);
+ ks_enable_int(ks);
+ enable_irq(netdev->irq);
+ return retv;
+}
+
+/**
+ * ks_start_rx - ready to serve pkts
+ * @ks : The chip information
+ *
+ */
+static void ks_start_rx(struct ks_net *ks)
+{
+ u16 cntl;
+
+ /* Enables QMU Receive (RXCR1). */
+ cntl = ks_rdreg16(ks, KS_RXCR1);
+ cntl |= RXCR1_RXE ;
+ ks_wrreg16(ks, KS_RXCR1, cntl);
+} /* ks_start_rx */
+
+/**
+ * ks_stop_rx - stop to serve pkts
+ * @ks : The chip information
+ *
+ */
+static void ks_stop_rx(struct ks_net *ks)
+{
+ u16 cntl;
+
+ /* Disables QMU Receive (RXCR1). */
+ cntl = ks_rdreg16(ks, KS_RXCR1);
+ cntl &= ~RXCR1_RXE ;
+ ks_wrreg16(ks, KS_RXCR1, cntl);
+
+} /* ks_stop_rx */
+
+static unsigned long const ethernet_polynomial = 0x04c11db7U;
+
+static unsigned long ether_gen_crc(int length, u8 *data)
+{
+ long crc = -1;
+ while (--length >= 0) {
+ u8 current_octet = *data++;
+ int bit;
+
+ for (bit = 0; bit < 8; bit++, current_octet >>= 1) {
+ crc = (crc << 1) ^
+ ((crc < 0) ^ (current_octet & 1) ?
+ ethernet_polynomial : 0);
+ }
+ }
+ return (unsigned long)crc;
+} /* ether_gen_crc */
+
+/**
+* ks_set_grpaddr - set multicast information
+* @ks : The chip information
+*/
+
+static void ks_set_grpaddr(struct ks_net *ks)
+{
+ u8 i;
+ u32 index, position, value;
+
+ memset(ks->mcast_bits, 0, sizeof(u8) * HW_MCAST_SIZE);
+
+ for (i = 0; i < ks->mcast_lst_size; i++) {
+ position = (ether_gen_crc(6, ks->mcast_lst[i]) >> 26) & 0x3f;
+ index = position >> 3;
+ value = 1 << (position & 7);
+ ks->mcast_bits[index] |= (u8)value;
+ }
+
+ for (i = 0; i < HW_MCAST_SIZE; i++) {
+ if (i & 1) {
+ ks_wrreg16(ks, (u16)((KS_MAHTR0 + i) & ~1),
+ (ks->mcast_bits[i] << 8) |
+ ks->mcast_bits[i - 1]);
+ }
+ }
+} /* ks_set_grpaddr */
+
+/*
+* ks_clear_mcast - clear multicast information
+*
+* @ks : The chip information
+* This routine removes all mcast addresses set in the hardware.
+*/
+
+static void ks_clear_mcast(struct ks_net *ks)
+{
+ u16 i, mcast_size;
+ for (i = 0; i < HW_MCAST_SIZE; i++)
+ ks->mcast_bits[i] = 0;
+
+ mcast_size = HW_MCAST_SIZE >> 2;
+ for (i = 0; i < mcast_size; i++)
+ ks_wrreg16(ks, KS_MAHTR0 + (2*i), 0);
+}
+
+static void ks_set_promis(struct ks_net *ks, u16 promiscuous_mode)
+{
+ u16 cntl;
+ ks->promiscuous = promiscuous_mode;
+ ks_stop_rx(ks); /* Stop receiving for reconfiguration */
+ cntl = ks_rdreg16(ks, KS_RXCR1);
+
+ cntl &= ~RXCR1_FILTER_MASK;
+ if (promiscuous_mode)
+ /* Enable Promiscuous mode */
+ cntl |= RXCR1_RXAE | RXCR1_RXINVF;
+ else
+ /* Disable Promiscuous mode (default normal mode) */
+ cntl |= RXCR1_RXPAFMA;
+
+ ks_wrreg16(ks, KS_RXCR1, cntl);
+
+ if (ks->enabled)
+ ks_start_rx(ks);
+
+} /* ks_set_promis */
+
+static void ks_set_mcast(struct ks_net *ks, u16 mcast)
+{
+ u16 cntl;
+
+ ks->all_mcast = mcast;
+ ks_stop_rx(ks); /* Stop receiving for reconfiguration */
+ cntl = ks_rdreg16(ks, KS_RXCR1);
+ cntl &= ~RXCR1_FILTER_MASK;
+ if (mcast)
+ /* Enable "Perfect with Multicast address passed mode" */
+ cntl |= (RXCR1_RXAE | RXCR1_RXMAFMA | RXCR1_RXPAFMA);
+ else
+ /**
+ * Disable "Perfect with Multicast address passed
+ * mode" (normal mode).
+ */
+ cntl |= RXCR1_RXPAFMA;
+
+ ks_wrreg16(ks, KS_RXCR1, cntl);
+
+ if (ks->enabled)
+ ks_start_rx(ks);
+} /* ks_set_mcast */
+
+static void ks_set_rx_mode(struct net_device *netdev)
+{
+ struct ks_net *ks = netdev_priv(netdev);
+ struct dev_mc_list *ptr;
+
+ /* Turn on/off promiscuous mode. */
+ if ((netdev->flags & IFF_PROMISC) == IFF_PROMISC)
+ ks_set_promis(ks,
+ (u16)((netdev->flags & IFF_PROMISC) == IFF_PROMISC));
+ /* Turn on/off all mcast mode. */
+ else if ((netdev->flags & IFF_ALLMULTI) == IFF_ALLMULTI)
+ ks_set_mcast(ks,
+ (u16)((netdev->flags & IFF_ALLMULTI) == IFF_ALLMULTI));
+ else
+ ks_set_promis(ks, false);
+
+ if ((netdev->flags & IFF_MULTICAST) && netdev->mc_count) {
+ if (netdev->mc_count <= MAX_MCAST_LST) {
+ int i = 0;
+ for (ptr = netdev->mc_list; ptr; ptr = ptr->next) {
+ if (!(*ptr->dmi_addr & 1))
+ continue;
+ if (i >= MAX_MCAST_LST)
+ break;
+ memcpy(ks->mcast_lst[i++], ptr->dmi_addr,
+ MAC_ADDR_LEN);
+ }
+ ks->mcast_lst_size = (u8)i;
+ ks_set_grpaddr(ks);
+ } else {
+ /**
+ * List too big to support so
+ * turn on all mcast mode.
+ */
+ ks->mcast_lst_size = MAX_MCAST_LST;
+ ks_set_mcast(ks, true);
+ }
+ } else {
+ ks->mcast_lst_size = 0;
+ ks_clear_mcast(ks);
+ }
+} /* ks_set_rx_mode */
+
+static void ks_set_mac(struct ks_net *ks, u8 *data)
+{
+ u16 *pw = (u16 *)data;
+ u16 w, u;
+
+ ks_stop_rx(ks); /* Stop receiving for reconfiguration */
+
+ u = *pw++;
+ w = ((u & 0xFF) << 8) | ((u >> 8) & 0xFF);
+ ks_wrreg16(ks, KS_MARH, w);
+
+ u = *pw++;
+ w = ((u & 0xFF) << 8) | ((u >> 8) & 0xFF);
+ ks_wrreg16(ks, KS_MARM, w);
+
+ u = *pw;
+ w = ((u & 0xFF) << 8) | ((u >> 8) & 0xFF);
+ ks_wrreg16(ks, KS_MARL, w);
+
+ memcpy(ks->mac_addr, data, 6);
+
+ if (ks->enabled)
+ ks_start_rx(ks);
+}
+
+static int ks_set_mac_address(struct net_device *netdev, void *paddr)
+{
+ struct ks_net *ks = netdev_priv(netdev);
+ struct sockaddr *addr = paddr;
+ u8 *da;
+
+ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+
+ da = (u8 *)netdev->dev_addr;
+
+ ks_set_mac(ks, da);
+ return 0;
+}
+
+static int ks_net_ioctl(struct net_device *netdev, struct ifreq *req, int cmd)
+{
+ struct ks_net *ks = netdev_priv(netdev);
+
+ if (!netif_running(netdev))
+ return -EINVAL;
+
+ return generic_mii_ioctl(&ks->mii, if_mii(req), cmd, NULL);
+}
+
+static const struct net_device_ops ks_netdev_ops = {
+ .ndo_open = ks_net_open,
+ .ndo_stop = ks_net_stop,
+ .ndo_do_ioctl = ks_net_ioctl,
+ .ndo_start_xmit = ks_start_xmit,
+ .ndo_set_mac_address = ks_set_mac_address,
+ .ndo_set_rx_mode = ks_set_rx_mode,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
+/* ethtool support */
+
+static void ks_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *di)
+{
+ strlcpy(di->driver, DRV_NAME, sizeof(di->driver));
+ strlcpy(di->version, "1.00", sizeof(di->version));
+ strlcpy(di->bus_info, dev_name(netdev->dev.parent),
+ sizeof(di->bus_info));
+}
+
+static u32 ks_get_msglevel(struct net_device *netdev)
+{
+ struct ks_net *ks = netdev_priv(netdev);
+ return ks->msg_enable;
+}
+
+static void ks_set_msglevel(struct net_device *netdev, u32 to)
+{
+ struct ks_net *ks = netdev_priv(netdev);
+ ks->msg_enable = to;
+}
+
+static int ks_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+ struct ks_net *ks = netdev_priv(netdev);
+ return mii_ethtool_gset(&ks->mii, cmd);
+}
+
+static int ks_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+ struct ks_net *ks = netdev_priv(netdev);
+ return mii_ethtool_sset(&ks->mii, cmd);
+}
+
+static u32 ks_get_link(struct net_device *netdev)
+{
+ struct ks_net *ks = netdev_priv(netdev);
+ return mii_link_ok(&ks->mii);
+}
+
+static int ks_nway_reset(struct net_device *netdev)
+{
+ struct ks_net *ks = netdev_priv(netdev);
+ return mii_nway_restart(&ks->mii);
+}
+
+static const struct ethtool_ops ks_ethtool_ops = {
+ .get_drvinfo = ks_get_drvinfo,
+ .get_msglevel = ks_get_msglevel,
+ .set_msglevel = ks_set_msglevel,
+ .get_settings = ks_get_settings,
+ .set_settings = ks_set_settings,
+ .get_link = ks_get_link,
+ .nway_reset = ks_nway_reset,
+};
+
+/* MII interface controls */
+
+/**
+ * ks_phy_reg - convert MII register into a KS8851 register
+ * @reg: MII register number.
+ *
+ * Return the KS8851 register number for the corresponding MII PHY register
+ * if possible. Return zero if the MII register has no direct mapping to the
+ * KS8851 register set.
+ */
+static int ks_phy_reg(int reg)
+{
+ switch (reg) {
+ case MII_BMCR:
+ return KS_P1MBCR;
+ case MII_BMSR:
+ return KS_P1MBSR;
+ case MII_PHYSID1:
+ return KS_PHY1ILR;
+ case MII_PHYSID2:
+ return KS_PHY1IHR;
+ case MII_ADVERTISE:
+ return KS_P1ANAR;
+ case MII_LPA:
+ return KS_P1ANLPR;
+ }
+
+ return 0x0;
+}
+
+/**
+ * ks_phy_read - MII interface PHY register read.
+ * @netdev: The network device the PHY is on.
+ * @phy_addr: Address of PHY (ignored as we only have one)
+ * @reg: The register to read.
+ *
+ * This call reads data from the PHY register specified in @reg. Since the
+ * device does not support all the MII registers, the non-existant values
+ * are always returned as zero.
+ *
+ * We return zero for unsupported registers as the MII code does not check
+ * the value returned for any error status, and simply returns it to the
+ * caller. The mii-tool that the driver was tested with takes any -ve error
+ * as real PHY capabilities, thus displaying incorrect data to the user.
+ */
+static int ks_phy_read(struct net_device *netdev, int phy_addr, int reg)
+{
+ struct ks_net *ks = netdev_priv(netdev);
+ int ksreg;
+ int result;
+
+ ksreg = ks_phy_reg(reg);
+ if (!ksreg)
+ return 0x0; /* no error return allowed, so use zero */
+
+ mutex_lock(&ks->lock);
+ result = ks_rdreg16(ks, ksreg);
+ mutex_unlock(&ks->lock);
+
+ return result;
+}
+
+static void ks_phy_write(struct net_device *netdev,
+ int phy, int reg, int value)
+{
+ struct ks_net *ks = netdev_priv(netdev);
+ int ksreg;
+
+ ksreg = ks_phy_reg(reg);
+ if (ksreg) {
+ mutex_lock(&ks->lock);
+ ks_wrreg16(ks, ksreg, value);
+ mutex_unlock(&ks->lock);
+ }
+}
+
+/**
+ * ks_read_selftest - read the selftest memory info.
+ * @ks: The device state
+ *
+ * Read and check the TX/RX memory selftest information.
+ */
+static int ks_read_selftest(struct ks_net *ks)
+{
+ unsigned both_done = MBIR_TXMBF | MBIR_RXMBF;
+ int ret = 0;
+ unsigned rd;
+
+ rd = ks_rdreg16(ks, KS_MBIR);
+
+ if ((rd & both_done) != both_done) {
+ ks_warn(ks, "Memory selftest not finished\n");
+ return 0;
+ }
+
+ if (rd & MBIR_TXMBFA) {
+ ks_err(ks, "TX memory selftest fails\n");
+ ret |= 1;
+ }
+
+ if (rd & MBIR_RXMBFA) {
+ ks_err(ks, "RX memory selftest fails\n");
+ ret |= 2;
+ }
+
+ ks_info(ks, "the selftest passes\n");
+ return ret;
+}
+
+static void ks_disable(struct ks_net *ks)
+{
+ u16 w;
+
+ w = ks_rdreg16(ks, KS_TXCR);
+
+ /* Disables QMU Transmit (TXCR). */
+ w &= ~TXCR_TXE;
+ ks_wrreg16(ks, KS_TXCR, w);
+
+ /* Disables QMU Receive (RXCR1). */
+ w = ks_rdreg16(ks, KS_RXCR1);
+ w &= ~RXCR1_RXE ;
+ ks_wrreg16(ks, KS_RXCR1, w);
+
+ ks->enabled = false;
+
+} /* ks_disable */
+
+static void ks_setup(struct ks_net *ks)
+{
+ u16 w;
+
+ /**
+ * Configure QMU Transmit
+ */
+
+ /* Setup Transmit Frame Data Pointer Auto-Increment (TXFDPR) */
+ ks_wrreg16(ks, KS_TXFDPR, TXFDPR_TXFPAI);
+
+ /* Setup Receive Frame Data Pointer Auto-Increment */
+ ks_wrreg16(ks, KS_RXFDPR, RXFDPR_RXFPAI);
+
+ /* Setup Receive Frame Threshold - 1 frame (RXFCTFC) */
+ ks_wrreg16(ks, KS_RXFCTR, 1 & RXFCTR_THRESHOLD_MASK);
+
+ /* Setup RxQ Command Control (RXQCR) */
+ ks->rc_rxqcr = RXQCR_CMD_CNTL;
+ ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr);
+
+ /**
+ * set the force mode to half duplex, default is full duplex
+ * because if the auto-negotiation fails, most switch uses
+ * half-duplex.
+ */
+
+ w = ks_rdreg16(ks, KS_P1MBCR);
+ w &= ~P1MBCR_FORCE_FDX;
+ ks_wrreg16(ks, KS_P1MBCR, w);
+
+ w = TXCR_TXFCE | TXCR_TXPE | TXCR_TXCRC | TXCR_TCGIP;
+ ks_wrreg16(ks, KS_TXCR, w);
+
+ w = RXCR1_RXFCE | RXCR1_RXBE | RXCR1_RXUE;
+
+ if (ks->promiscuous) /* bPromiscuous */
+ w |= (RXCR1_RXAE | RXCR1_RXINVF);
+ else if (ks->all_mcast) /* Multicast address passed mode */
+ w |= (RXCR1_RXAE | RXCR1_RXMAFMA | RXCR1_RXPAFMA);
+ else /* Normal mode */
+ w |= RXCR1_RXPAFMA;
+
+ ks_wrreg16(ks, KS_RXCR1, w);
+} /*ks_setup */
+
+
+static void ks_setup_int(struct ks_net *ks)
+{
+ ks->rc_ier = 0x00;
+ /* Clear the interrupts status of the hardware. */
+ ks_wrreg16(ks, KS_ISR, 0xffff);
+
+ /* Enables the interrupts of the hardware. */
+ ks->rc_ier = (IRQ_LCI | IRQ_TXI | IRQ_RXI);
+} /* ks_setup_int */
+
+void ks_enable(struct ks_net *ks)
+{
+ u16 w;
+
+ w = ks_rdreg16(ks, KS_TXCR);
+ /* Enables QMU Transmit (TXCR). */
+ ks_wrreg16(ks, KS_TXCR, w | TXCR_TXE);
+
+ /*
+ * RX Frame Count Threshold Enable and Auto-Dequeue RXQ Frame
+ * Enable
+ */
+
+ w = ks_rdreg16(ks, KS_RXQCR);
+ ks_wrreg16(ks, KS_RXQCR, w | RXQCR_RXFCTE);
+
+ /* Enables QMU Receive (RXCR1). */
+ w = ks_rdreg16(ks, KS_RXCR1);
+ ks_wrreg16(ks, KS_RXCR1, w | RXCR1_RXE);
+ ks->enabled = true;
+} /* ks_enable */
+
+static int ks_hw_init(struct ks_net *ks)
+{
+#define MHEADER_SIZE (sizeof(struct type_frame_head) * MAX_RECV_FRAMES)
+ ks->promiscuous = 0;
+ ks->all_mcast = 0;
+ ks->mcast_lst_size = 0;
+
+ ks->frame_head_info = (struct type_frame_head *) \
+ kmalloc(MHEADER_SIZE, GFP_KERNEL);
+ if (!ks->frame_head_info) {
+ printk(KERN_ERR "Error: Fail to allocate frame memory\n");
+ return false;
+ }
+
+ ks_set_mac(ks, KS_DEFAULT_MAC_ADDRESS);
+ return true;
+}
+
+
+static int __devinit ks8851_probe(struct platform_device *pdev)
+{
+ int err = -ENOMEM;
+ struct resource *io_d, *io_c;
+ struct net_device *netdev;
+ struct ks_net *ks;
+ u16 id, data;
+
+ io_d = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ io_c = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+
+ if (!request_mem_region(io_d->start, resource_size(io_d), DRV_NAME))
+ goto err_mem_region;
+
+ if (!request_mem_region(io_c->start, resource_size(io_c), DRV_NAME))
+ goto err_mem_region1;
+
+ netdev = alloc_etherdev(sizeof(struct ks_net));
+ if (!netdev)
+ goto err_alloc_etherdev;
+
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+
+ ks = netdev_priv(netdev);
+ ks->netdev = netdev;
+ ks->hw_addr = ioremap(io_d->start, resource_size(io_d));
+
+ if (!ks->hw_addr)
+ goto err_ioremap;
+
+ ks->hw_addr_cmd = ioremap(io_c->start, resource_size(io_c));
+ if (!ks->hw_addr_cmd)
+ goto err_ioremap1;
+
+ ks->irq = platform_get_irq(pdev, 0);
+
+ if (ks->irq < 0) {
+ err = ks->irq;
+ goto err_get_irq;
+ }
+
+ ks->pdev = pdev;
+
+ mutex_init(&ks->lock);
+ spin_lock_init(&ks->statelock);
+
+ netdev->netdev_ops = &ks_netdev_ops;
+ netdev->ethtool_ops = &ks_ethtool_ops;
+
+ /* setup mii state */
+ ks->mii.dev = netdev;
+ ks->mii.phy_id = 1,
+ ks->mii.phy_id_mask = 1;
+ ks->mii.reg_num_mask = 0xf;
+ ks->mii.mdio_read = ks_phy_read;
+ ks->mii.mdio_write = ks_phy_write;
+
+ ks_info(ks, "message enable is %d\n", msg_enable);
+ /* set the default message enable */
+ ks->msg_enable = netif_msg_init(msg_enable, (NETIF_MSG_DRV |
+ NETIF_MSG_PROBE |
+ NETIF_MSG_LINK));
+ ks_read_config(ks);
+
+ /* simple check for a valid chip being connected to the bus */
+ if ((ks_rdreg16(ks, KS_CIDER) & ~CIDER_REV_MASK) != CIDER_ID) {
+ ks_err(ks, "failed to read device ID\n");
+ err = -ENODEV;
+ goto err_register;
+ }
+
+ if (ks_read_selftest(ks)) {
+ ks_err(ks, "failed to read device ID\n");
+ err = -ENODEV;
+ goto err_register;
+ }
+
+ err = register_netdev(netdev);
+ if (err)
+ goto err_register;
+
+ platform_set_drvdata(pdev, netdev);
+
+ ks_soft_reset(ks, GRR_GSR);
+ ks_hw_init(ks);
+ ks_disable(ks);
+ ks_setup(ks);
+ ks_setup_int(ks);
+ ks_enable_int(ks);
+ ks_enable(ks);
+ memcpy(netdev->dev_addr, ks->mac_addr, 6);
+
+ data = ks_rdreg16(ks, KS_OBCR);
+ ks_wrreg16(ks, KS_OBCR, data | OBCR_ODS_16MA);
+
+ /**
+ * If you want to use the default MAC addr,
+ * comment out the 2 functions below.
+ */
+
+ random_ether_addr(netdev->dev_addr);
+ ks_set_mac(ks, netdev->dev_addr);
+
+ id = ks_rdreg16(ks, KS_CIDER);
+
+ printk(KERN_INFO DRV_NAME
+ " Found chip, family: 0x%x, id: 0x%x, rev: 0x%x\n",
+ (id >> 8) & 0xff, (id >> 4) & 0xf, (id >> 1) & 0x7);
+ return 0;
+
+err_register:
+err_get_irq:
+ iounmap(ks->hw_addr_cmd);
+err_ioremap1:
+ iounmap(ks->hw_addr);
+err_ioremap:
+ free_netdev(netdev);
+err_alloc_etherdev:
+ release_mem_region(io_c->start, resource_size(io_c));
+err_mem_region1:
+ release_mem_region(io_d->start, resource_size(io_d));
+err_mem_region:
+ return err;
+}
+
+static int __devexit ks8851_remove(struct platform_device *pdev)
+{
+ struct net_device *netdev = platform_get_drvdata(pdev);
+ struct ks_net *ks = netdev_priv(netdev);
+ struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ unregister_netdev(netdev);
+ iounmap(ks->hw_addr);
+ free_netdev(netdev);
+ release_mem_region(iomem->start, resource_size(iomem));
+ platform_set_drvdata(pdev, NULL);
+ return 0;
+
+}
+
+static struct platform_driver ks8851_platform_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = ks8851_probe,
+ .remove = __devexit_p(ks8851_remove),
+};
+
+static int __init ks8851_init(void)
+{
+ return platform_driver_register(&ks8851_platform_driver);
+}
+
+static void __exit ks8851_exit(void)
+{
+ platform_driver_unregister(&ks8851_platform_driver);
+}
+
+module_init(ks8851_init);
+module_exit(ks8851_exit);
+
+MODULE_DESCRIPTION("KS8851 MLL Network driver");
+MODULE_AUTHOR("David Choi <david.choi@micrel.com>");
+MODULE_LICENSE("GPL");
+module_param_named(message, msg_enable, int, 0);
+MODULE_PARM_DESC(message, "Message verbosity level (0=none, 31=all)");
+
diff --git a/drivers/net/meth.c b/drivers/net/meth.c
index 92ceb689b4d..2af81735386 100644
--- a/drivers/net/meth.c
+++ b/drivers/net/meth.c
@@ -828,7 +828,7 @@ static int __exit meth_remove(struct platform_device *pdev)
static struct platform_driver meth_driver = {
.probe = meth_probe,
- .remove = __devexit_p(meth_remove),
+ .remove = __exit_p(meth_remove),
.driver = {
.name = "meth",
.owner = THIS_MODULE,
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c
index cc394d07375..5910df60c93 100644
--- a/drivers/net/pppol2tp.c
+++ b/drivers/net/pppol2tp.c
@@ -2179,7 +2179,7 @@ static int pppol2tp_session_setsockopt(struct sock *sk,
* session or the special tunnel type.
*/
static int pppol2tp_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
struct pppol2tp_session *session = sk->sk_user_data;
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h
index a9845a2f243..30d5585beee 100644
--- a/drivers/net/qlge/qlge.h
+++ b/drivers/net/qlge/qlge.h
@@ -1381,15 +1381,15 @@ struct intr_context {
/* adapter flags definitions. */
enum {
- QL_ADAPTER_UP = (1 << 0), /* Adapter has been brought up. */
- QL_LEGACY_ENABLED = (1 << 3),
- QL_MSI_ENABLED = (1 << 3),
- QL_MSIX_ENABLED = (1 << 4),
- QL_DMA64 = (1 << 5),
- QL_PROMISCUOUS = (1 << 6),
- QL_ALLMULTI = (1 << 7),
- QL_PORT_CFG = (1 << 8),
- QL_CAM_RT_SET = (1 << 9),
+ QL_ADAPTER_UP = 0, /* Adapter has been brought up. */
+ QL_LEGACY_ENABLED = 1,
+ QL_MSI_ENABLED = 2,
+ QL_MSIX_ENABLED = 3,
+ QL_DMA64 = 4,
+ QL_PROMISCUOUS = 5,
+ QL_ALLMULTI = 6,
+ QL_PORT_CFG = 7,
+ QL_CAM_RT_SET = 8,
};
/* link_status bit definitions */
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 7783c5db81d..3d0efea3211 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -3142,14 +3142,14 @@ static int ql_route_initialize(struct ql_adapter *qdev)
{
int status = 0;
- status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK);
+ /* Clear all the entries in the routing table. */
+ status = ql_clear_routing_entries(qdev);
if (status)
return status;
- /* Clear all the entries in the routing table. */
- status = ql_clear_routing_entries(qdev);
+ status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK);
if (status)
- goto exit;
+ return status;
status = ql_set_routing_reg(qdev, RT_IDX_ALL_ERR_SLOT, RT_IDX_ERR, 1);
if (status) {
@@ -3380,12 +3380,10 @@ static int ql_adapter_down(struct ql_adapter *qdev)
ql_free_rx_buffers(qdev);
- spin_lock(&qdev->hw_lock);
status = ql_adapter_reset(qdev);
if (status)
QPRINTK(qdev, IFDOWN, ERR, "reset(func #%d) FAILED!\n",
qdev->func);
- spin_unlock(&qdev->hw_lock);
return status;
}
@@ -3705,7 +3703,7 @@ static void ql_asic_reset_work(struct work_struct *work)
struct ql_adapter *qdev =
container_of(work, struct ql_adapter, asic_reset_work.work);
int status;
-
+ rtnl_lock();
status = ql_adapter_down(qdev);
if (status)
goto error;
@@ -3713,12 +3711,12 @@ static void ql_asic_reset_work(struct work_struct *work)
status = ql_adapter_up(qdev);
if (status)
goto error;
-
+ rtnl_unlock();
return;
error:
QPRINTK(qdev, IFUP, ALERT,
"Driver up/down cycle failed, closing device\n");
- rtnl_lock();
+
set_bit(QL_ADAPTER_UP, &qdev->flags);
dev_close(qdev->ndev);
rtnl_unlock();
@@ -3834,11 +3832,14 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
return err;
}
+ qdev->ndev = ndev;
+ qdev->pdev = pdev;
+ pci_set_drvdata(pdev, ndev);
pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
if (pos <= 0) {
dev_err(&pdev->dev, PFX "Cannot find PCI Express capability, "
"aborting.\n");
- goto err_out;
+ return pos;
} else {
pci_read_config_word(pdev, pos + PCI_EXP_DEVCTL, &val16);
val16 &= ~PCI_EXP_DEVCTL_NOSNOOP_EN;
@@ -3851,7 +3852,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
err = pci_request_regions(pdev, DRV_NAME);
if (err) {
dev_err(&pdev->dev, "PCI region request failed.\n");
- goto err_out;
+ return err;
}
pci_set_master(pdev);
@@ -3869,7 +3870,6 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
goto err_out;
}
- pci_set_drvdata(pdev, ndev);
qdev->reg_base =
ioremap_nocache(pci_resource_start(pdev, 1),
pci_resource_len(pdev, 1));
@@ -3889,8 +3889,6 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
goto err_out;
}
- qdev->ndev = ndev;
- qdev->pdev = pdev;
err = ql_get_board_info(qdev);
if (err) {
dev_err(&pdev->dev, "Register access failed.\n");
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index ecf3279fbef..f4dfd1f679a 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -826,7 +826,7 @@ static int __exit sgiseeq_remove(struct platform_device *pdev)
static struct platform_driver sgiseeq_driver = {
.probe = sgiseeq_probe,
- .remove = __devexit_p(sgiseeq_remove),
+ .remove = __exit_p(sgiseeq_remove),
.driver = {
.name = "sgiseeq",
.owner = THIS_MODULE,
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 55bad408196..01f6811f132 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -3935,11 +3935,14 @@ static int __devinit skge_probe(struct pci_dev *pdev,
#endif
err = -ENOMEM;
- hw = kzalloc(sizeof(*hw), GFP_KERNEL);
+ /* space for skge@pci:0000:04:00.0 */
+ hw = kzalloc(sizeof(*hw) + strlen(DRV_NAME "@pci:" )
+ + strlen(pci_name(pdev)) + 1, GFP_KERNEL);
if (!hw) {
dev_err(&pdev->dev, "cannot allocate hardware struct\n");
goto err_out_free_regions;
}
+ sprintf(hw->irq_name, DRV_NAME "@pci:%s", pci_name(pdev));
hw->pdev = pdev;
spin_lock_init(&hw->hw_lock);
@@ -3974,7 +3977,7 @@ static int __devinit skge_probe(struct pci_dev *pdev,
goto err_out_free_netdev;
}
- err = request_irq(pdev->irq, skge_intr, IRQF_SHARED, dev->name, hw);
+ err = request_irq(pdev->irq, skge_intr, IRQF_SHARED, hw->irq_name, hw);
if (err) {
dev_err(&pdev->dev, "%s: cannot assign irq %d\n",
dev->name, pdev->irq);
@@ -3982,14 +3985,17 @@ static int __devinit skge_probe(struct pci_dev *pdev,
}
skge_show_addr(dev);
- if (hw->ports > 1 && (dev1 = skge_devinit(hw, 1, using_dac))) {
- if (register_netdev(dev1) == 0)
+ if (hw->ports > 1) {
+ dev1 = skge_devinit(hw, 1, using_dac);
+ if (dev1 && register_netdev(dev1) == 0)
skge_show_addr(dev1);
else {
/* Failure to register second port need not be fatal */
dev_warn(&pdev->dev, "register of second port failed\n");
hw->dev[1] = NULL;
- free_netdev(dev1);
+ hw->ports = 1;
+ if (dev1)
+ free_netdev(dev1);
}
}
pci_set_drvdata(pdev, hw);
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index 17caccbb768..831de1b6e96 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -2423,6 +2423,8 @@ struct skge_hw {
u16 phy_addr;
spinlock_t phy_lock;
struct tasklet_struct phy_task;
+
+ char irq_name[0]; /* skge@pci:000:04:00.0 */
};
enum pause_control {
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index ef1165718dd..2ab5c39f33c 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -4487,13 +4487,16 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
wol_default = device_may_wakeup(&pdev->dev) ? WAKE_MAGIC : 0;
err = -ENOMEM;
- hw = kzalloc(sizeof(*hw), GFP_KERNEL);
+
+ hw = kzalloc(sizeof(*hw) + strlen(DRV_NAME "@pci:")
+ + strlen(pci_name(pdev)) + 1, GFP_KERNEL);
if (!hw) {
dev_err(&pdev->dev, "cannot allocate hardware struct\n");
goto err_out_free_regions;
}
hw->pdev = pdev;
+ sprintf(hw->irq_name, DRV_NAME "@pci:%s", pci_name(pdev));
hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
if (!hw->regs) {
@@ -4539,7 +4542,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
err = request_irq(pdev->irq, sky2_intr,
(hw->flags & SKY2_HW_USE_MSI) ? 0 : IRQF_SHARED,
- dev->name, hw);
+ hw->irq_name, hw);
if (err) {
dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq);
goto err_out_unregister;
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index e0f23a10104..ed54129698b 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -2085,6 +2085,8 @@ struct sky2_hw {
struct timer_list watchdog_timer;
struct work_struct restart_work;
wait_queue_head_t msi_wait;
+
+ char irq_name[0];
};
static inline int sky2_is_copper(const struct sky2_hw *hw)
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 82b45d8797b..524691cd989 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2412,7 +2412,6 @@ struct ring_info {
struct tx_ring_info {
struct sk_buff *skb;
- u32 prev_vlan_tag;
};
struct tg3_config_info {
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index d445845f277..8d009760277 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -948,7 +948,7 @@ free:
return err;
}
-static void virtnet_remove(struct virtio_device *vdev)
+static void __devexit virtnet_remove(struct virtio_device *vdev)
{
struct virtnet_info *vi = vdev->priv;
struct sk_buff *skb;
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 49ea9c92b7e..d7a764a2fc1 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -31,13 +31,12 @@ config STRIP
---help---
Say Y if you have a Metricom radio and intend to use Starmode Radio
IP. STRIP is a radio protocol developed for the MosquitoNet project
- (on the WWW at <http://mosquitonet.stanford.edu/>) to send Internet
- traffic using Metricom radios. Metricom radios are small, battery
- powered, 100kbit/sec packet radio transceivers, about the size and
- weight of a cellular telephone. (You may also have heard them called
- "Metricom modems" but we avoid the term "modem" because it misleads
- many people into thinking that you can plug a Metricom modem into a
- phone line and use it as a modem.)
+ to send Internet traffic using Metricom radios. Metricom radios are
+ small, battery powered, 100kbit/sec packet radio transceivers, about
+ the size and weight of a cellular telephone. (You may also have heard
+ them called "Metricom modems" but we avoid the term "modem" because
+ it misleads many people into thinking that you can plug a Metricom
+ modem into a phone line and use it as a modem.)
You can use STRIP on any Linux machine with a serial port, although
it is obviously most useful for people with laptop computers. If you
diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c
index b3e5cf3735b..dbd488da18b 100644
--- a/drivers/net/wireless/ath/ar9170/phy.c
+++ b/drivers/net/wireless/ath/ar9170/phy.c
@@ -1141,7 +1141,8 @@ static int ar9170_set_freq_cal_data(struct ar9170 *ar,
u8 vpds[2][AR5416_PD_GAIN_ICEPTS];
u8 pwrs[2][AR5416_PD_GAIN_ICEPTS];
int chain, idx, i;
- u8 f;
+ u32 phy_data = 0;
+ u8 f, tmp;
switch (channel->band) {
case IEEE80211_BAND_2GHZ:
@@ -1208,9 +1209,6 @@ static int ar9170_set_freq_cal_data(struct ar9170 *ar,
}
for (i = 0; i < 76; i++) {
- u32 phy_data;
- u8 tmp;
-
if (i < 25) {
tmp = ar9170_interpolate_val(i, &pwrs[0][0],
&vpds[0][0]);
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index e96091b3149..9c1397996e0 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -340,10 +340,15 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
q->mmio_base + B43_PIO_TXDATA,
sizeof(u16));
if (data_len & 1) {
+ u8 tail[2] = { 0, };
+
/* Write the last byte. */
ctl &= ~B43_PIO_TXCTL_WRITEHI;
b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
- b43_piotx_write16(q, B43_PIO_TXDATA, data[data_len - 1]);
+ tail[0] = data[data_len - 1];
+ ssb_block_write(dev->dev, tail, 2,
+ q->mmio_base + B43_PIO_TXDATA,
+ sizeof(u16));
}
return ctl;
@@ -386,26 +391,31 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
q->mmio_base + B43_PIO8_TXDATA,
sizeof(u32));
if (data_len & 3) {
- u32 value = 0;
+ u8 tail[4] = { 0, };
/* Write the last few bytes. */
ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 |
B43_PIO8_TXCTL_24_31);
- data = &(data[data_len - 1]);
switch (data_len & 3) {
case 3:
- ctl |= B43_PIO8_TXCTL_16_23;
- value |= (u32)(*data) << 16;
- data--;
+ ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15;
+ tail[0] = data[data_len - 3];
+ tail[1] = data[data_len - 2];
+ tail[2] = data[data_len - 1];
+ break;
case 2:
ctl |= B43_PIO8_TXCTL_8_15;
- value |= (u32)(*data) << 8;
- data--;
+ tail[0] = data[data_len - 2];
+ tail[1] = data[data_len - 1];
+ break;
case 1:
- value |= (u32)(*data);
+ tail[0] = data[data_len - 1];
+ break;
}
b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
- b43_piotx_write32(q, B43_PIO8_TXDATA, value);
+ ssb_block_write(dev->dev, tail, 4,
+ q->mmio_base + B43_PIO8_TXDATA,
+ sizeof(u32));
}
return ctl;
@@ -693,21 +703,25 @@ data_ready:
q->mmio_base + B43_PIO8_RXDATA,
sizeof(u32));
if (len & 3) {
- u32 value;
- char *data;
+ u8 tail[4] = { 0, };
/* Read the last few bytes. */
- value = b43_piorx_read32(q, B43_PIO8_RXDATA);
- data = &(skb->data[len + padding - 1]);
+ ssb_block_read(dev->dev, tail, 4,
+ q->mmio_base + B43_PIO8_RXDATA,
+ sizeof(u32));
switch (len & 3) {
case 3:
- *data = (value >> 16);
- data--;
+ skb->data[len + padding - 3] = tail[0];
+ skb->data[len + padding - 2] = tail[1];
+ skb->data[len + padding - 1] = tail[2];
+ break;
case 2:
- *data = (value >> 8);
- data--;
+ skb->data[len + padding - 2] = tail[0];
+ skb->data[len + padding - 1] = tail[1];
+ break;
case 1:
- *data = value;
+ skb->data[len + padding - 1] = tail[0];
+ break;
}
}
} else {
@@ -715,11 +729,13 @@ data_ready:
q->mmio_base + B43_PIO_RXDATA,
sizeof(u16));
if (len & 1) {
- u16 value;
+ u8 tail[2] = { 0, };
/* Read the last byte. */
- value = b43_piorx_read16(q, B43_PIO_RXDATA);
- skb->data[len + padding - 1] = value;
+ ssb_block_read(dev->dev, tail, 2,
+ q->mmio_base + B43_PIO_RXDATA,
+ sizeof(u16));
+ skb->data[len + padding - 1] = tail[0];
}
}
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 896f532182f..38cfd79e059 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -631,6 +631,9 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
data->beacon_int = 1024 * info->beacon_int / 1000 * HZ / 1000;
if (WARN_ON(!data->beacon_int))
data->beacon_int = 1;
+ if (data->started)
+ mod_timer(&data->beacon_timer,
+ jiffies + data->beacon_int);
}
if (changed & BSS_CHANGED_ERP_CTS_PROT) {
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 1cbd9b4a3ef..b8f5ee33445 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2381,6 +2381,7 @@ static struct usb_device_id rt73usb_device_table[] = {
/* Huawei-3Com */
{ USB_DEVICE(0x1472, 0x0009), USB_DEVICE_DATA(&rt73usb_ops) },
/* Hercules */
+ { USB_DEVICE(0x06f8, 0xe002), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x06f8, 0xe010), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x06f8, 0xe020), USB_DEVICE_DATA(&rt73usb_ops) },
/* Linksys */
diff --git a/drivers/pcmcia/sa1100_assabet.c b/drivers/pcmcia/sa1100_assabet.c
index f424146a2bc..ac8aa09ba0d 100644
--- a/drivers/pcmcia/sa1100_assabet.c
+++ b/drivers/pcmcia/sa1100_assabet.c
@@ -130,7 +130,7 @@ static struct pcmcia_low_level assabet_pcmcia_ops = {
.socket_suspend = assabet_pcmcia_socket_suspend,
};
-int __init pcmcia_assabet_init(struct device *dev)
+int pcmcia_assabet_init(struct device *dev)
{
int ret = -ENODEV;
diff --git a/drivers/pcmcia/sa1100_neponset.c b/drivers/pcmcia/sa1100_neponset.c
index 4c41e86ccff..0c76d337815 100644
--- a/drivers/pcmcia/sa1100_neponset.c
+++ b/drivers/pcmcia/sa1100_neponset.c
@@ -123,7 +123,7 @@ static struct pcmcia_low_level neponset_pcmcia_ops = {
.socket_suspend = sa1111_pcmcia_socket_suspend,
};
-int __init pcmcia_neponset_init(struct sa1111_dev *sadev)
+int pcmcia_neponset_init(struct sa1111_dev *sadev)
{
int ret = -ENODEV;
diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c
index 1b78f639ead..76769978285 100644
--- a/drivers/s390/cio/qdio_debug.c
+++ b/drivers/s390/cio/qdio_debug.c
@@ -125,7 +125,7 @@ static int qstat_seq_open(struct inode *inode, struct file *filp)
filp->f_path.dentry->d_inode->i_private);
}
-static struct file_operations debugfs_fops = {
+static const struct file_operations debugfs_fops = {
.owner = THIS_MODULE,
.open = qstat_seq_open,
.read = seq_read,
diff --git a/drivers/s390/cio/qdio_perf.c b/drivers/s390/cio/qdio_perf.c
index eff943923c6..968e3c7c263 100644
--- a/drivers/s390/cio/qdio_perf.c
+++ b/drivers/s390/cio/qdio_perf.c
@@ -84,7 +84,7 @@ static int qdio_perf_seq_open(struct inode *inode, struct file *filp)
return single_open(filp, qdio_perf_proc_show, NULL);
}
-static struct file_operations qdio_perf_proc_fops = {
+static const struct file_operations qdio_perf_proc_fops = {
.owner = THIS_MODULE,
.open = qdio_perf_seq_open,
.read = seq_read,
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 0cb049f5cc5..747a5e5c127 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1317,7 +1317,7 @@ static void sg_rq_end_io(struct request *rq, int uptodate)
}
}
-static struct file_operations sg_fops = {
+static const struct file_operations sg_fops = {
.owner = THIS_MODULE,
.read = sg_read,
.write = sg_write,
@@ -2194,9 +2194,11 @@ static int sg_proc_seq_show_int(struct seq_file *s, void *v);
static int sg_proc_single_open_adio(struct inode *inode, struct file *file);
static ssize_t sg_proc_write_adio(struct file *filp, const char __user *buffer,
size_t count, loff_t *off);
-static struct file_operations adio_fops = {
- /* .owner, .read and .llseek added in sg_proc_init() */
+static const struct file_operations adio_fops = {
+ .owner = THIS_MODULE,
.open = sg_proc_single_open_adio,
+ .read = seq_read,
+ .llseek = seq_lseek,
.write = sg_proc_write_adio,
.release = single_release,
};
@@ -2204,23 +2206,32 @@ static struct file_operations adio_fops = {
static int sg_proc_single_open_dressz(struct inode *inode, struct file *file);
static ssize_t sg_proc_write_dressz(struct file *filp,
const char __user *buffer, size_t count, loff_t *off);
-static struct file_operations dressz_fops = {
+static const struct file_operations dressz_fops = {
+ .owner = THIS_MODULE,
.open = sg_proc_single_open_dressz,
+ .read = seq_read,
+ .llseek = seq_lseek,
.write = sg_proc_write_dressz,
.release = single_release,
};
static int sg_proc_seq_show_version(struct seq_file *s, void *v);
static int sg_proc_single_open_version(struct inode *inode, struct file *file);
-static struct file_operations version_fops = {
+static const struct file_operations version_fops = {
+ .owner = THIS_MODULE,
.open = sg_proc_single_open_version,
+ .read = seq_read,
+ .llseek = seq_lseek,
.release = single_release,
};
static int sg_proc_seq_show_devhdr(struct seq_file *s, void *v);
static int sg_proc_single_open_devhdr(struct inode *inode, struct file *file);
-static struct file_operations devhdr_fops = {
+static const struct file_operations devhdr_fops = {
+ .owner = THIS_MODULE,
.open = sg_proc_single_open_devhdr,
+ .read = seq_read,
+ .llseek = seq_lseek,
.release = single_release,
};
@@ -2229,8 +2240,11 @@ static int sg_proc_open_dev(struct inode *inode, struct file *file);
static void * dev_seq_start(struct seq_file *s, loff_t *pos);
static void * dev_seq_next(struct seq_file *s, void *v, loff_t *pos);
static void dev_seq_stop(struct seq_file *s, void *v);
-static struct file_operations dev_fops = {
+static const struct file_operations dev_fops = {
+ .owner = THIS_MODULE,
.open = sg_proc_open_dev,
+ .read = seq_read,
+ .llseek = seq_lseek,
.release = seq_release,
};
static const struct seq_operations dev_seq_ops = {
@@ -2242,8 +2256,11 @@ static const struct seq_operations dev_seq_ops = {
static int sg_proc_seq_show_devstrs(struct seq_file *s, void *v);
static int sg_proc_open_devstrs(struct inode *inode, struct file *file);
-static struct file_operations devstrs_fops = {
+static const struct file_operations devstrs_fops = {
+ .owner = THIS_MODULE,
.open = sg_proc_open_devstrs,
+ .read = seq_read,
+ .llseek = seq_lseek,
.release = seq_release,
};
static const struct seq_operations devstrs_seq_ops = {
@@ -2255,8 +2272,11 @@ static const struct seq_operations devstrs_seq_ops = {
static int sg_proc_seq_show_debug(struct seq_file *s, void *v);
static int sg_proc_open_debug(struct inode *inode, struct file *file);
-static struct file_operations debug_fops = {
+static const struct file_operations debug_fops = {
+ .owner = THIS_MODULE,
.open = sg_proc_open_debug,
+ .read = seq_read,
+ .llseek = seq_lseek,
.release = seq_release,
};
static const struct seq_operations debug_seq_ops = {
@@ -2269,7 +2289,7 @@ static const struct seq_operations debug_seq_ops = {
struct sg_proc_leaf {
const char * name;
- struct file_operations * fops;
+ const struct file_operations * fops;
};
static struct sg_proc_leaf sg_proc_leaf_arr[] = {
@@ -2295,9 +2315,6 @@ sg_proc_init(void)
for (k = 0; k < num_leaves; ++k) {
leaf = &sg_proc_leaf_arr[k];
mask = leaf->fops->write ? S_IRUGO | S_IWUSR : S_IRUGO;
- leaf->fops->owner = THIS_MODULE;
- leaf->fops->read = seq_read;
- leaf->fops->llseek = seq_lseek;
proc_create(leaf->name, mask, sg_proc_sgp, leaf->fops);
}
return 0;
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 2209620d234..b1ae774016f 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -64,6 +64,8 @@ static int serial_index(struct uart_port *port)
return (serial8250_reg.minor - 64) + port->line;
}
+static unsigned int skip_txen_test; /* force skip of txen test at init time */
+
/*
* Debugging.
*/
@@ -2108,7 +2110,7 @@ static int serial8250_startup(struct uart_port *port)
is variable. So, let's just don't test if we receive
TX irq. This way, we'll never enable UART_BUG_TXEN.
*/
- if (up->port.flags & UPF_NO_TXEN_TEST)
+ if (skip_txen_test || up->port.flags & UPF_NO_TXEN_TEST)
goto dont_test_tx_en;
/*
@@ -3248,6 +3250,9 @@ MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices"
module_param(nr_uarts, uint, 0644);
MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")");
+module_param(skip_txen_test, uint, 0644);
+MODULE_PARM_DESC(skip_txen_test, "Skip checking for the TXEN bug at init time");
+
#ifdef CONFIG_SERIAL_8250_RSA
module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444);
MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index e70712044a7..e5225725727 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -862,7 +862,7 @@ config SERIAL_IMX_CONSOLE
config SERIAL_UARTLITE
tristate "Xilinx uartlite serial port support"
- depends on PPC32 || MICROBLAZE
+ depends on PPC32 || MICROBLAZE || MFD_TIMBERDALE
select SERIAL_CORE
help
Say Y here if you want to use the Xilinx uartlite serial controller.
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c
index 2d7feecaf49..0028b6f89ce 100644
--- a/drivers/serial/icom.c
+++ b/drivers/serial/icom.c
@@ -307,7 +307,7 @@ static void stop_processor(struct icom_port *icom_port)
if (port < 4) {
temp = readl(stop_proc[port].global_control_reg);
temp =
- (temp & ~start_proc[port].processor_id) | stop_proc[port].processor_id;
+ (temp & ~start_proc[port].processor_id) | stop_proc[port].processor_id;
writel(temp, stop_proc[port].global_control_reg);
/* write flush */
@@ -336,7 +336,7 @@ static void start_processor(struct icom_port *icom_port)
if (port < 4) {
temp = readl(start_proc[port].global_control_reg);
temp =
- (temp & ~stop_proc[port].processor_id) | start_proc[port].processor_id;
+ (temp & ~stop_proc[port].processor_id) | start_proc[port].processor_id;
writel(temp, start_proc[port].global_control_reg);
/* write flush */
@@ -509,8 +509,8 @@ static void load_code(struct icom_port *icom_port)
dev_err(&icom_port->adapter->pci_dev->dev,"Port not opertional\n");
}
- if (new_page != NULL)
- pci_free_consistent(dev, 4096, new_page, temp_pci);
+ if (new_page != NULL)
+ pci_free_consistent(dev, 4096, new_page, temp_pci);
}
static int startup(struct icom_port *icom_port)
@@ -1493,15 +1493,15 @@ static int __devinit icom_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
int index;
- unsigned int command_reg;
- int retval;
- struct icom_adapter *icom_adapter;
- struct icom_port *icom_port;
+ unsigned int command_reg;
+ int retval;
+ struct icom_adapter *icom_adapter;
+ struct icom_port *icom_port;
- retval = pci_enable_device(dev);
- if (retval) {
+ retval = pci_enable_device(dev);
+ if (retval) {
dev_err(&dev->dev, "Device enable FAILED\n");
- return retval;
+ return retval;
}
if ( (retval = pci_request_regions(dev, "icom"))) {
@@ -1510,23 +1510,23 @@ static int __devinit icom_probe(struct pci_dev *dev,
return retval;
}
- pci_set_master(dev);
+ pci_set_master(dev);
- if ( (retval = pci_read_config_dword(dev, PCI_COMMAND, &command_reg))) {
+ if ( (retval = pci_read_config_dword(dev, PCI_COMMAND, &command_reg))) {
dev_err(&dev->dev, "PCI Config read FAILED\n");
- return retval;
- }
+ return retval;
+ }
pci_write_config_dword(dev, PCI_COMMAND,
command_reg | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER
| PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
- if (ent->driver_data == ADAPTER_V1) {
+ if (ent->driver_data == ADAPTER_V1) {
pci_write_config_dword(dev, 0x44, 0x8300830A);
- } else {
+ } else {
pci_write_config_dword(dev, 0x44, 0x42004200);
pci_write_config_dword(dev, 0x48, 0x42004200);
- }
+ }
retval = icom_alloc_adapter(&icom_adapter);
@@ -1536,10 +1536,10 @@ static int __devinit icom_probe(struct pci_dev *dev,
goto probe_exit0;
}
- icom_adapter->base_addr_pci = pci_resource_start(dev, 0);
- icom_adapter->pci_dev = dev;
- icom_adapter->version = ent->driver_data;
- icom_adapter->subsystem_id = ent->subdevice;
+ icom_adapter->base_addr_pci = pci_resource_start(dev, 0);
+ icom_adapter->pci_dev = dev;
+ icom_adapter->version = ent->driver_data;
+ icom_adapter->subsystem_id = ent->subdevice;
retval = icom_init_ports(icom_adapter);
@@ -1548,7 +1548,7 @@ static int __devinit icom_probe(struct pci_dev *dev,
goto probe_exit1;
}
- icom_adapter->base_addr = pci_ioremap_bar(dev, 0);
+ icom_adapter->base_addr = pci_ioremap_bar(dev, 0);
if (!icom_adapter->base_addr)
goto probe_exit1;
@@ -1562,7 +1562,7 @@ static int __devinit icom_probe(struct pci_dev *dev,
retval = icom_load_ports(icom_adapter);
- for (index = 0; index < icom_adapter->numb_ports; index++) {
+ for (index = 0; index < icom_adapter->numb_ports; index++) {
icom_port = &icom_adapter->port_info[index];
if (icom_port->status == ICOM_PORT_ACTIVE) {
@@ -1579,7 +1579,7 @@ static int __devinit icom_probe(struct pci_dev *dev,
icom_port->status = ICOM_PORT_OFF;
dev_err(&dev->dev, "Device add failed\n");
} else
- dev_info(&dev->dev, "Device added\n");
+ dev_info(&dev->dev, "Device added\n");
}
}
@@ -1595,9 +1595,7 @@ probe_exit0:
pci_release_regions(dev);
pci_disable_device(dev);
- return retval;
-
-
+ return retval;
}
static void __devexit icom_remove(struct pci_dev *dev)
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index 7f5e2687322..2199d819a98 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -638,7 +638,7 @@ static void __init sa1100_init_ports(void)
PPSR |= PPC_TXD1 | PPC_TXD3;
}
-void __init sa1100_register_uart_fns(struct sa1100_port_fns *fns)
+void __devinit sa1100_register_uart_fns(struct sa1100_port_fns *fns)
{
if (fns->get_mctrl)
sa1100_pops.get_mctrl = fns->get_mctrl;
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
index 0f7cf4c453e..c50e9fbbf74 100644
--- a/drivers/serial/serial_txx9.c
+++ b/drivers/serial/serial_txx9.c
@@ -221,21 +221,26 @@ sio_quot_set(struct uart_txx9_port *up, int quot)
sio_out(up, TXX9_SIBGR, 0xff | TXX9_SIBGR_BCLK_T6);
}
+static struct uart_txx9_port *to_uart_txx9_port(struct uart_port *port)
+{
+ return container_of(port, struct uart_txx9_port, port);
+}
+
static void serial_txx9_stop_tx(struct uart_port *port)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
sio_mask(up, TXX9_SIDICR, TXX9_SIDICR_TIE);
}
static void serial_txx9_start_tx(struct uart_port *port)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
sio_set(up, TXX9_SIDICR, TXX9_SIDICR_TIE);
}
static void serial_txx9_stop_rx(struct uart_port *port)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
up->port.read_status_mask &= ~TXX9_SIDISR_RDIS;
}
@@ -246,7 +251,7 @@ static void serial_txx9_enable_ms(struct uart_port *port)
static void serial_txx9_initialize(struct uart_port *port)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
unsigned int tmout = 10000;
sio_out(up, TXX9_SIFCR, TXX9_SIFCR_SWRST);
@@ -414,7 +419,7 @@ static irqreturn_t serial_txx9_interrupt(int irq, void *dev_id)
static unsigned int serial_txx9_tx_empty(struct uart_port *port)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
unsigned long flags;
unsigned int ret;
@@ -427,7 +432,7 @@ static unsigned int serial_txx9_tx_empty(struct uart_port *port)
static unsigned int serial_txx9_get_mctrl(struct uart_port *port)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
unsigned int ret;
/* no modem control lines */
@@ -440,7 +445,7 @@ static unsigned int serial_txx9_get_mctrl(struct uart_port *port)
static void serial_txx9_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
if (mctrl & TIOCM_RTS)
sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSSC);
@@ -450,7 +455,7 @@ static void serial_txx9_set_mctrl(struct uart_port *port, unsigned int mctrl)
static void serial_txx9_break_ctl(struct uart_port *port, int break_state)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
unsigned long flags;
spin_lock_irqsave(&up->port.lock, flags);
@@ -494,7 +499,7 @@ static int serial_txx9_get_poll_char(struct uart_port *port)
{
unsigned int ier;
unsigned char c;
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
/*
* First save the IER then disable the interrupts
@@ -520,7 +525,7 @@ static int serial_txx9_get_poll_char(struct uart_port *port)
static void serial_txx9_put_poll_char(struct uart_port *port, unsigned char c)
{
unsigned int ier;
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
/*
* First save the IER then disable the interrupts
@@ -551,7 +556,7 @@ static void serial_txx9_put_poll_char(struct uart_port *port, unsigned char c)
static int serial_txx9_startup(struct uart_port *port)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
unsigned long flags;
int retval;
@@ -596,7 +601,7 @@ static int serial_txx9_startup(struct uart_port *port)
static void serial_txx9_shutdown(struct uart_port *port)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
unsigned long flags;
/*
@@ -636,7 +641,7 @@ static void
serial_txx9_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
unsigned int cval, fcr = 0;
unsigned long flags;
unsigned int baud, quot;
@@ -814,19 +819,19 @@ static void serial_txx9_release_resource(struct uart_txx9_port *up)
static void serial_txx9_release_port(struct uart_port *port)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
serial_txx9_release_resource(up);
}
static int serial_txx9_request_port(struct uart_port *port)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
return serial_txx9_request_resource(up);
}
static void serial_txx9_config_port(struct uart_port *port, int uflags)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
int ret;
/*
@@ -897,7 +902,7 @@ static void __init serial_txx9_register_ports(struct uart_driver *drv,
static void serial_txx9_console_putchar(struct uart_port *port, int ch)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
wait_for_xmitr(up);
sio_out(up, TXX9_SITFIFO, ch);
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 6d7a3f82c54..21a118269ca 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -17,7 +17,7 @@ obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o
obj-$(CONFIG_SPI_AU1550) += au1550_spi.o
obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
obj-$(CONFIG_SPI_GPIO) += spi_gpio.o
-obj-$(CONFIG_SPI_IMX) += mxc_spi.o
+obj-$(CONFIG_SPI_IMX) += spi_imx.o
obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o
obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o
obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o
diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/spi_imx.c
index b1447236ae8..89c22efedfb 100644
--- a/drivers/spi/mxc_spi.c
+++ b/drivers/spi/spi_imx.c
@@ -48,14 +48,14 @@
#define MXC_INT_RR (1 << 0) /* Receive data ready interrupt */
#define MXC_INT_TE (1 << 1) /* Transmit FIFO empty interrupt */
-struct mxc_spi_config {
+struct spi_imx_config {
unsigned int speed_hz;
unsigned int bpw;
unsigned int mode;
int cs;
};
-struct mxc_spi_data {
+struct spi_imx_data {
struct spi_bitbang bitbang;
struct completion xfer_done;
@@ -66,43 +66,43 @@ struct mxc_spi_data {
int *chipselect;
unsigned int count;
- void (*tx)(struct mxc_spi_data *);
- void (*rx)(struct mxc_spi_data *);
+ void (*tx)(struct spi_imx_data *);
+ void (*rx)(struct spi_imx_data *);
void *rx_buf;
const void *tx_buf;
unsigned int txfifo; /* number of words pushed in tx FIFO */
/* SoC specific functions */
- void (*intctrl)(struct mxc_spi_data *, int);
- int (*config)(struct mxc_spi_data *, struct mxc_spi_config *);
- void (*trigger)(struct mxc_spi_data *);
- int (*rx_available)(struct mxc_spi_data *);
+ void (*intctrl)(struct spi_imx_data *, int);
+ int (*config)(struct spi_imx_data *, struct spi_imx_config *);
+ void (*trigger)(struct spi_imx_data *);
+ int (*rx_available)(struct spi_imx_data *);
};
#define MXC_SPI_BUF_RX(type) \
-static void mxc_spi_buf_rx_##type(struct mxc_spi_data *mxc_spi) \
+static void spi_imx_buf_rx_##type(struct spi_imx_data *spi_imx) \
{ \
- unsigned int val = readl(mxc_spi->base + MXC_CSPIRXDATA); \
+ unsigned int val = readl(spi_imx->base + MXC_CSPIRXDATA); \
\
- if (mxc_spi->rx_buf) { \
- *(type *)mxc_spi->rx_buf = val; \
- mxc_spi->rx_buf += sizeof(type); \
+ if (spi_imx->rx_buf) { \
+ *(type *)spi_imx->rx_buf = val; \
+ spi_imx->rx_buf += sizeof(type); \
} \
}
#define MXC_SPI_BUF_TX(type) \
-static void mxc_spi_buf_tx_##type(struct mxc_spi_data *mxc_spi) \
+static void spi_imx_buf_tx_##type(struct spi_imx_data *spi_imx) \
{ \
type val = 0; \
\
- if (mxc_spi->tx_buf) { \
- val = *(type *)mxc_spi->tx_buf; \
- mxc_spi->tx_buf += sizeof(type); \
+ if (spi_imx->tx_buf) { \
+ val = *(type *)spi_imx->tx_buf; \
+ spi_imx->tx_buf += sizeof(type); \
} \
\
- mxc_spi->count -= sizeof(type); \
+ spi_imx->count -= sizeof(type); \
\
- writel(val, mxc_spi->base + MXC_CSPITXDATA); \
+ writel(val, spi_imx->base + MXC_CSPITXDATA); \
}
MXC_SPI_BUF_RX(u8)
@@ -119,7 +119,7 @@ static int mxc_clkdivs[] = {0, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192,
256, 384, 512, 768, 1024};
/* MX21, MX27 */
-static unsigned int mxc_spi_clkdiv_1(unsigned int fin,
+static unsigned int spi_imx_clkdiv_1(unsigned int fin,
unsigned int fspi)
{
int i, max;
@@ -137,7 +137,7 @@ static unsigned int mxc_spi_clkdiv_1(unsigned int fin,
}
/* MX1, MX31, MX35 */
-static unsigned int mxc_spi_clkdiv_2(unsigned int fin,
+static unsigned int spi_imx_clkdiv_2(unsigned int fin,
unsigned int fspi)
{
int i, div = 4;
@@ -174,7 +174,7 @@ static unsigned int mxc_spi_clkdiv_2(unsigned int fin,
* the i.MX35 has a slightly different register layout for bits
* we do not use here.
*/
-static void mx31_intctrl(struct mxc_spi_data *mxc_spi, int enable)
+static void mx31_intctrl(struct spi_imx_data *spi_imx, int enable)
{
unsigned int val = 0;
@@ -183,24 +183,24 @@ static void mx31_intctrl(struct mxc_spi_data *mxc_spi, int enable)
if (enable & MXC_INT_RR)
val |= MX31_INTREG_RREN;
- writel(val, mxc_spi->base + MXC_CSPIINT);
+ writel(val, spi_imx->base + MXC_CSPIINT);
}
-static void mx31_trigger(struct mxc_spi_data *mxc_spi)
+static void mx31_trigger(struct spi_imx_data *spi_imx)
{
unsigned int reg;
- reg = readl(mxc_spi->base + MXC_CSPICTRL);
+ reg = readl(spi_imx->base + MXC_CSPICTRL);
reg |= MX31_CSPICTRL_XCH;
- writel(reg, mxc_spi->base + MXC_CSPICTRL);
+ writel(reg, spi_imx->base + MXC_CSPICTRL);
}
-static int mx31_config(struct mxc_spi_data *mxc_spi,
- struct mxc_spi_config *config)
+static int mx31_config(struct spi_imx_data *spi_imx,
+ struct spi_imx_config *config)
{
unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER;
- reg |= mxc_spi_clkdiv_2(mxc_spi->spi_clk, config->speed_hz) <<
+ reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<
MX31_CSPICTRL_DR_SHIFT;
if (cpu_is_mx31())
@@ -223,14 +223,14 @@ static int mx31_config(struct mxc_spi_data *mxc_spi,
reg |= (config->cs + 32) << MX35_CSPICTRL_CS_SHIFT;
}
- writel(reg, mxc_spi->base + MXC_CSPICTRL);
+ writel(reg, spi_imx->base + MXC_CSPICTRL);
return 0;
}
-static int mx31_rx_available(struct mxc_spi_data *mxc_spi)
+static int mx31_rx_available(struct spi_imx_data *spi_imx)
{
- return readl(mxc_spi->base + MX31_CSPISTATUS) & MX31_STATUS_RR;
+ return readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR;
}
#define MX27_INTREG_RR (1 << 4)
@@ -246,7 +246,7 @@ static int mx31_rx_available(struct mxc_spi_data *mxc_spi)
#define MX27_CSPICTRL_DR_SHIFT 14
#define MX27_CSPICTRL_CS_SHIFT 19
-static void mx27_intctrl(struct mxc_spi_data *mxc_spi, int enable)
+static void mx27_intctrl(struct spi_imx_data *spi_imx, int enable)
{
unsigned int val = 0;
@@ -255,24 +255,24 @@ static void mx27_intctrl(struct mxc_spi_data *mxc_spi, int enable)
if (enable & MXC_INT_RR)
val |= MX27_INTREG_RREN;
- writel(val, mxc_spi->base + MXC_CSPIINT);
+ writel(val, spi_imx->base + MXC_CSPIINT);
}
-static void mx27_trigger(struct mxc_spi_data *mxc_spi)
+static void mx27_trigger(struct spi_imx_data *spi_imx)
{
unsigned int reg;
- reg = readl(mxc_spi->base + MXC_CSPICTRL);
+ reg = readl(spi_imx->base + MXC_CSPICTRL);
reg |= MX27_CSPICTRL_XCH;
- writel(reg, mxc_spi->base + MXC_CSPICTRL);
+ writel(reg, spi_imx->base + MXC_CSPICTRL);
}
-static int mx27_config(struct mxc_spi_data *mxc_spi,
- struct mxc_spi_config *config)
+static int mx27_config(struct spi_imx_data *spi_imx,
+ struct spi_imx_config *config)
{
unsigned int reg = MX27_CSPICTRL_ENABLE | MX27_CSPICTRL_MASTER;
- reg |= mxc_spi_clkdiv_1(mxc_spi->spi_clk, config->speed_hz) <<
+ reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, config->speed_hz) <<
MX27_CSPICTRL_DR_SHIFT;
reg |= config->bpw - 1;
@@ -285,14 +285,14 @@ static int mx27_config(struct mxc_spi_data *mxc_spi,
if (config->cs < 0)
reg |= (config->cs + 32) << MX27_CSPICTRL_CS_SHIFT;
- writel(reg, mxc_spi->base + MXC_CSPICTRL);
+ writel(reg, spi_imx->base + MXC_CSPICTRL);
return 0;
}
-static int mx27_rx_available(struct mxc_spi_data *mxc_spi)
+static int mx27_rx_available(struct spi_imx_data *spi_imx)
{
- return readl(mxc_spi->base + MXC_CSPIINT) & MX27_INTREG_RR;
+ return readl(spi_imx->base + MXC_CSPIINT) & MX27_INTREG_RR;
}
#define MX1_INTREG_RR (1 << 3)
@@ -306,7 +306,7 @@ static int mx27_rx_available(struct mxc_spi_data *mxc_spi)
#define MX1_CSPICTRL_MASTER (1 << 10)
#define MX1_CSPICTRL_DR_SHIFT 13
-static void mx1_intctrl(struct mxc_spi_data *mxc_spi, int enable)
+static void mx1_intctrl(struct spi_imx_data *spi_imx, int enable)
{
unsigned int val = 0;
@@ -315,24 +315,24 @@ static void mx1_intctrl(struct mxc_spi_data *mxc_spi, int enable)
if (enable & MXC_INT_RR)
val |= MX1_INTREG_RREN;
- writel(val, mxc_spi->base + MXC_CSPIINT);
+ writel(val, spi_imx->base + MXC_CSPIINT);
}
-static void mx1_trigger(struct mxc_spi_data *mxc_spi)
+static void mx1_trigger(struct spi_imx_data *spi_imx)
{
unsigned int reg;
- reg = readl(mxc_spi->base + MXC_CSPICTRL);
+ reg = readl(spi_imx->base + MXC_CSPICTRL);
reg |= MX1_CSPICTRL_XCH;
- writel(reg, mxc_spi->base + MXC_CSPICTRL);
+ writel(reg, spi_imx->base + MXC_CSPICTRL);
}
-static int mx1_config(struct mxc_spi_data *mxc_spi,
- struct mxc_spi_config *config)
+static int mx1_config(struct spi_imx_data *spi_imx,
+ struct spi_imx_config *config)
{
unsigned int reg = MX1_CSPICTRL_ENABLE | MX1_CSPICTRL_MASTER;
- reg |= mxc_spi_clkdiv_2(mxc_spi->spi_clk, config->speed_hz) <<
+ reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<
MX1_CSPICTRL_DR_SHIFT;
reg |= config->bpw - 1;
@@ -341,156 +341,151 @@ static int mx1_config(struct mxc_spi_data *mxc_spi,
if (config->mode & SPI_CPOL)
reg |= MX1_CSPICTRL_POL;
- writel(reg, mxc_spi->base + MXC_CSPICTRL);
+ writel(reg, spi_imx->base + MXC_CSPICTRL);
return 0;
}
-static int mx1_rx_available(struct mxc_spi_data *mxc_spi)
+static int mx1_rx_available(struct spi_imx_data *spi_imx)
{
- return readl(mxc_spi->base + MXC_CSPIINT) & MX1_INTREG_RR;
+ return readl(spi_imx->base + MXC_CSPIINT) & MX1_INTREG_RR;
}
-static void mxc_spi_chipselect(struct spi_device *spi, int is_active)
+static void spi_imx_chipselect(struct spi_device *spi, int is_active)
{
- struct mxc_spi_data *mxc_spi = spi_master_get_devdata(spi->master);
- unsigned int cs = 0;
- int gpio = mxc_spi->chipselect[spi->chip_select];
- struct mxc_spi_config config;
+ struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+ int gpio = spi_imx->chipselect[spi->chip_select];
+ int active = is_active != BITBANG_CS_INACTIVE;
+ int dev_is_lowactive = !(spi->mode & SPI_CS_HIGH);
- if (spi->mode & SPI_CS_HIGH)
- cs = 1;
-
- if (is_active == BITBANG_CS_INACTIVE) {
- if (gpio >= 0)
- gpio_set_value(gpio, !cs);
+ if (gpio < 0)
return;
- }
-
- config.bpw = spi->bits_per_word;
- config.speed_hz = spi->max_speed_hz;
- config.mode = spi->mode;
- config.cs = mxc_spi->chipselect[spi->chip_select];
-
- mxc_spi->config(mxc_spi, &config);
-
- /* Initialize the functions for transfer */
- if (config.bpw <= 8) {
- mxc_spi->rx = mxc_spi_buf_rx_u8;
- mxc_spi->tx = mxc_spi_buf_tx_u8;
- } else if (config.bpw <= 16) {
- mxc_spi->rx = mxc_spi_buf_rx_u16;
- mxc_spi->tx = mxc_spi_buf_tx_u16;
- } else if (config.bpw <= 32) {
- mxc_spi->rx = mxc_spi_buf_rx_u32;
- mxc_spi->tx = mxc_spi_buf_tx_u32;
- } else
- BUG();
- if (gpio >= 0)
- gpio_set_value(gpio, cs);
-
- return;
+ gpio_set_value(gpio, dev_is_lowactive ^ active);
}
-static void mxc_spi_push(struct mxc_spi_data *mxc_spi)
+static void spi_imx_push(struct spi_imx_data *spi_imx)
{
- while (mxc_spi->txfifo < 8) {
- if (!mxc_spi->count)
+ while (spi_imx->txfifo < 8) {
+ if (!spi_imx->count)
break;
- mxc_spi->tx(mxc_spi);
- mxc_spi->txfifo++;
+ spi_imx->tx(spi_imx);
+ spi_imx->txfifo++;
}
- mxc_spi->trigger(mxc_spi);
+ spi_imx->trigger(spi_imx);
}
-static irqreturn_t mxc_spi_isr(int irq, void *dev_id)
+static irqreturn_t spi_imx_isr(int irq, void *dev_id)
{
- struct mxc_spi_data *mxc_spi = dev_id;
+ struct spi_imx_data *spi_imx = dev_id;
- while (mxc_spi->rx_available(mxc_spi)) {
- mxc_spi->rx(mxc_spi);
- mxc_spi->txfifo--;
+ while (spi_imx->rx_available(spi_imx)) {
+ spi_imx->rx(spi_imx);
+ spi_imx->txfifo--;
}
- if (mxc_spi->count) {
- mxc_spi_push(mxc_spi);
+ if (spi_imx->count) {
+ spi_imx_push(spi_imx);
return IRQ_HANDLED;
}
- if (mxc_spi->txfifo) {
+ if (spi_imx->txfifo) {
/* No data left to push, but still waiting for rx data,
* enable receive data available interrupt.
*/
- mxc_spi->intctrl(mxc_spi, MXC_INT_RR);
+ spi_imx->intctrl(spi_imx, MXC_INT_RR);
return IRQ_HANDLED;
}
- mxc_spi->intctrl(mxc_spi, 0);
- complete(&mxc_spi->xfer_done);
+ spi_imx->intctrl(spi_imx, 0);
+ complete(&spi_imx->xfer_done);
return IRQ_HANDLED;
}
-static int mxc_spi_setupxfer(struct spi_device *spi,
+static int spi_imx_setupxfer(struct spi_device *spi,
struct spi_transfer *t)
{
- struct mxc_spi_data *mxc_spi = spi_master_get_devdata(spi->master);
- struct mxc_spi_config config;
+ struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+ struct spi_imx_config config;
config.bpw = t ? t->bits_per_word : spi->bits_per_word;
config.speed_hz = t ? t->speed_hz : spi->max_speed_hz;
config.mode = spi->mode;
+ config.cs = spi_imx->chipselect[spi->chip_select];
+
+ if (!config.speed_hz)
+ config.speed_hz = spi->max_speed_hz;
+ if (!config.bpw)
+ config.bpw = spi->bits_per_word;
+ if (!config.speed_hz)
+ config.speed_hz = spi->max_speed_hz;
+
+ /* Initialize the functions for transfer */
+ if (config.bpw <= 8) {
+ spi_imx->rx = spi_imx_buf_rx_u8;
+ spi_imx->tx = spi_imx_buf_tx_u8;
+ } else if (config.bpw <= 16) {
+ spi_imx->rx = spi_imx_buf_rx_u16;
+ spi_imx->tx = spi_imx_buf_tx_u16;
+ } else if (config.bpw <= 32) {
+ spi_imx->rx = spi_imx_buf_rx_u32;
+ spi_imx->tx = spi_imx_buf_tx_u32;
+ } else
+ BUG();
- mxc_spi->config(mxc_spi, &config);
+ spi_imx->config(spi_imx, &config);
return 0;
}
-static int mxc_spi_transfer(struct spi_device *spi,
+static int spi_imx_transfer(struct spi_device *spi,
struct spi_transfer *transfer)
{
- struct mxc_spi_data *mxc_spi = spi_master_get_devdata(spi->master);
+ struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
- mxc_spi->tx_buf = transfer->tx_buf;
- mxc_spi->rx_buf = transfer->rx_buf;
- mxc_spi->count = transfer->len;
- mxc_spi->txfifo = 0;
+ spi_imx->tx_buf = transfer->tx_buf;
+ spi_imx->rx_buf = transfer->rx_buf;
+ spi_imx->count = transfer->len;
+ spi_imx->txfifo = 0;
- init_completion(&mxc_spi->xfer_done);
+ init_completion(&spi_imx->xfer_done);
- mxc_spi_push(mxc_spi);
+ spi_imx_push(spi_imx);
- mxc_spi->intctrl(mxc_spi, MXC_INT_TE);
+ spi_imx->intctrl(spi_imx, MXC_INT_TE);
- wait_for_completion(&mxc_spi->xfer_done);
+ wait_for_completion(&spi_imx->xfer_done);
return transfer->len;
}
-static int mxc_spi_setup(struct spi_device *spi)
+static int spi_imx_setup(struct spi_device *spi)
{
- if (!spi->bits_per_word)
- spi->bits_per_word = 8;
+ struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+ int gpio = spi_imx->chipselect[spi->chip_select];
pr_debug("%s: mode %d, %u bpw, %d hz\n", __func__,
spi->mode, spi->bits_per_word, spi->max_speed_hz);
- mxc_spi_chipselect(spi, BITBANG_CS_INACTIVE);
+ if (gpio >= 0)
+ gpio_direction_output(gpio, spi->mode & SPI_CS_HIGH ? 0 : 1);
+
+ spi_imx_chipselect(spi, BITBANG_CS_INACTIVE);
return 0;
}
-static void mxc_spi_cleanup(struct spi_device *spi)
+static void spi_imx_cleanup(struct spi_device *spi)
{
}
-static int __init mxc_spi_probe(struct platform_device *pdev)
+static int __init spi_imx_probe(struct platform_device *pdev)
{
struct spi_imx_master *mxc_platform_info;
struct spi_master *master;
- struct mxc_spi_data *mxc_spi;
+ struct spi_imx_data *spi_imx;
struct resource *res;
int i, ret;
@@ -500,7 +495,7 @@ static int __init mxc_spi_probe(struct platform_device *pdev)
return -EINVAL;
}
- master = spi_alloc_master(&pdev->dev, sizeof(struct mxc_spi_data));
+ master = spi_alloc_master(&pdev->dev, sizeof(struct spi_imx_data));
if (!master)
return -ENOMEM;
@@ -509,32 +504,32 @@ static int __init mxc_spi_probe(struct platform_device *pdev)
master->bus_num = pdev->id;
master->num_chipselect = mxc_platform_info->num_chipselect;
- mxc_spi = spi_master_get_devdata(master);
- mxc_spi->bitbang.master = spi_master_get(master);
- mxc_spi->chipselect = mxc_platform_info->chipselect;
+ spi_imx = spi_master_get_devdata(master);
+ spi_imx->bitbang.master = spi_master_get(master);
+ spi_imx->chipselect = mxc_platform_info->chipselect;
for (i = 0; i < master->num_chipselect; i++) {
- if (mxc_spi->chipselect[i] < 0)
+ if (spi_imx->chipselect[i] < 0)
continue;
- ret = gpio_request(mxc_spi->chipselect[i], DRIVER_NAME);
+ ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME);
if (ret) {
i--;
while (i > 0)
- if (mxc_spi->chipselect[i] >= 0)
- gpio_free(mxc_spi->chipselect[i--]);
+ if (spi_imx->chipselect[i] >= 0)
+ gpio_free(spi_imx->chipselect[i--]);
dev_err(&pdev->dev, "can't get cs gpios");
goto out_master_put;
}
- gpio_direction_output(mxc_spi->chipselect[i], 1);
}
- mxc_spi->bitbang.chipselect = mxc_spi_chipselect;
- mxc_spi->bitbang.setup_transfer = mxc_spi_setupxfer;
- mxc_spi->bitbang.txrx_bufs = mxc_spi_transfer;
- mxc_spi->bitbang.master->setup = mxc_spi_setup;
- mxc_spi->bitbang.master->cleanup = mxc_spi_cleanup;
+ spi_imx->bitbang.chipselect = spi_imx_chipselect;
+ spi_imx->bitbang.setup_transfer = spi_imx_setupxfer;
+ spi_imx->bitbang.txrx_bufs = spi_imx_transfer;
+ spi_imx->bitbang.master->setup = spi_imx_setup;
+ spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
+ spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
- init_completion(&mxc_spi->xfer_done);
+ init_completion(&spi_imx->xfer_done);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
@@ -549,58 +544,58 @@ static int __init mxc_spi_probe(struct platform_device *pdev)
goto out_gpio_free;
}
- mxc_spi->base = ioremap(res->start, resource_size(res));
- if (!mxc_spi->base) {
+ spi_imx->base = ioremap(res->start, resource_size(res));
+ if (!spi_imx->base) {
ret = -EINVAL;
goto out_release_mem;
}
- mxc_spi->irq = platform_get_irq(pdev, 0);
- if (!mxc_spi->irq) {
+ spi_imx->irq = platform_get_irq(pdev, 0);
+ if (!spi_imx->irq) {
ret = -EINVAL;
goto out_iounmap;
}
- ret = request_irq(mxc_spi->irq, mxc_spi_isr, 0, DRIVER_NAME, mxc_spi);
+ ret = request_irq(spi_imx->irq, spi_imx_isr, 0, DRIVER_NAME, spi_imx);
if (ret) {
- dev_err(&pdev->dev, "can't get irq%d: %d\n", mxc_spi->irq, ret);
+ dev_err(&pdev->dev, "can't get irq%d: %d\n", spi_imx->irq, ret);
goto out_iounmap;
}
if (cpu_is_mx31() || cpu_is_mx35()) {
- mxc_spi->intctrl = mx31_intctrl;
- mxc_spi->config = mx31_config;
- mxc_spi->trigger = mx31_trigger;
- mxc_spi->rx_available = mx31_rx_available;
+ spi_imx->intctrl = mx31_intctrl;
+ spi_imx->config = mx31_config;
+ spi_imx->trigger = mx31_trigger;
+ spi_imx->rx_available = mx31_rx_available;
} else if (cpu_is_mx27() || cpu_is_mx21()) {
- mxc_spi->intctrl = mx27_intctrl;
- mxc_spi->config = mx27_config;
- mxc_spi->trigger = mx27_trigger;
- mxc_spi->rx_available = mx27_rx_available;
+ spi_imx->intctrl = mx27_intctrl;
+ spi_imx->config = mx27_config;
+ spi_imx->trigger = mx27_trigger;
+ spi_imx->rx_available = mx27_rx_available;
} else if (cpu_is_mx1()) {
- mxc_spi->intctrl = mx1_intctrl;
- mxc_spi->config = mx1_config;
- mxc_spi->trigger = mx1_trigger;
- mxc_spi->rx_available = mx1_rx_available;
+ spi_imx->intctrl = mx1_intctrl;
+ spi_imx->config = mx1_config;
+ spi_imx->trigger = mx1_trigger;
+ spi_imx->rx_available = mx1_rx_available;
} else
BUG();
- mxc_spi->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(mxc_spi->clk)) {
+ spi_imx->clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(spi_imx->clk)) {
dev_err(&pdev->dev, "unable to get clock\n");
- ret = PTR_ERR(mxc_spi->clk);
+ ret = PTR_ERR(spi_imx->clk);
goto out_free_irq;
}
- clk_enable(mxc_spi->clk);
- mxc_spi->spi_clk = clk_get_rate(mxc_spi->clk);
+ clk_enable(spi_imx->clk);
+ spi_imx->spi_clk = clk_get_rate(spi_imx->clk);
if (!cpu_is_mx31() || !cpu_is_mx35())
- writel(1, mxc_spi->base + MXC_RESET);
+ writel(1, spi_imx->base + MXC_RESET);
- mxc_spi->intctrl(mxc_spi, 0);
+ spi_imx->intctrl(spi_imx, 0);
- ret = spi_bitbang_start(&mxc_spi->bitbang);
+ ret = spi_bitbang_start(&spi_imx->bitbang);
if (ret) {
dev_err(&pdev->dev, "bitbang start failed with %d\n", ret);
goto out_clk_put;
@@ -611,18 +606,18 @@ static int __init mxc_spi_probe(struct platform_device *pdev)
return ret;
out_clk_put:
- clk_disable(mxc_spi->clk);
- clk_put(mxc_spi->clk);
+ clk_disable(spi_imx->clk);
+ clk_put(spi_imx->clk);
out_free_irq:
- free_irq(mxc_spi->irq, mxc_spi);
+ free_irq(spi_imx->irq, spi_imx);
out_iounmap:
- iounmap(mxc_spi->base);
+ iounmap(spi_imx->base);
out_release_mem:
release_mem_region(res->start, resource_size(res));
out_gpio_free:
for (i = 0; i < master->num_chipselect; i++)
- if (mxc_spi->chipselect[i] >= 0)
- gpio_free(mxc_spi->chipselect[i]);
+ if (spi_imx->chipselect[i] >= 0)
+ gpio_free(spi_imx->chipselect[i]);
out_master_put:
spi_master_put(master);
kfree(master);
@@ -630,24 +625,24 @@ out_master_put:
return ret;
}
-static int __exit mxc_spi_remove(struct platform_device *pdev)
+static int __exit spi_imx_remove(struct platform_device *pdev)
{
struct spi_master *master = platform_get_drvdata(pdev);
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- struct mxc_spi_data *mxc_spi = spi_master_get_devdata(master);
+ struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
int i;
- spi_bitbang_stop(&mxc_spi->bitbang);
+ spi_bitbang_stop(&spi_imx->bitbang);
- writel(0, mxc_spi->base + MXC_CSPICTRL);
- clk_disable(mxc_spi->clk);
- clk_put(mxc_spi->clk);
- free_irq(mxc_spi->irq, mxc_spi);
- iounmap(mxc_spi->base);
+ writel(0, spi_imx->base + MXC_CSPICTRL);
+ clk_disable(spi_imx->clk);
+ clk_put(spi_imx->clk);
+ free_irq(spi_imx->irq, spi_imx);
+ iounmap(spi_imx->base);
for (i = 0; i < master->num_chipselect; i++)
- if (mxc_spi->chipselect[i] >= 0)
- gpio_free(mxc_spi->chipselect[i]);
+ if (spi_imx->chipselect[i] >= 0)
+ gpio_free(spi_imx->chipselect[i]);
spi_master_put(master);
@@ -658,27 +653,27 @@ static int __exit mxc_spi_remove(struct platform_device *pdev)
return 0;
}
-static struct platform_driver mxc_spi_driver = {
+static struct platform_driver spi_imx_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
},
- .probe = mxc_spi_probe,
- .remove = __exit_p(mxc_spi_remove),
+ .probe = spi_imx_probe,
+ .remove = __exit_p(spi_imx_remove),
};
-static int __init mxc_spi_init(void)
+static int __init spi_imx_init(void)
{
- return platform_driver_register(&mxc_spi_driver);
+ return platform_driver_register(&spi_imx_driver);
}
-static void __exit mxc_spi_exit(void)
+static void __exit spi_imx_exit(void)
{
- platform_driver_unregister(&mxc_spi_driver);
+ platform_driver_unregister(&spi_imx_driver);
}
-module_init(mxc_spi_init);
-module_exit(mxc_spi_exit);
+module_init(spi_imx_init);
+module_exit(spi_imx_exit);
MODULE_DESCRIPTION("SPI Master Controller driver");
MODULE_AUTHOR("Sascha Hauer, Pengutronix");
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index f921bd1109e..5d23983f02f 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -537,7 +537,7 @@ static int spidev_release(struct inode *inode, struct file *filp)
return status;
}
-static struct file_operations spidev_fops = {
+static const struct file_operations spidev_fops = {
.owner = THIS_MODULE,
/* REVISIT switch to aio primitives, so that userspace
* gets more complete API coverage. It'll simplify things
diff --git a/drivers/staging/dst/dcore.c b/drivers/staging/dst/dcore.c
index ac8577358ba..ee1601026fb 100644
--- a/drivers/staging/dst/dcore.c
+++ b/drivers/staging/dst/dcore.c
@@ -847,7 +847,7 @@ static dst_command_func dst_commands[] = {
/*
* Configuration parser.
*/
-static void cn_dst_callback(struct cn_msg *msg)
+static void cn_dst_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
{
struct dst_ctl *ctl;
int err;
@@ -855,6 +855,11 @@ static void cn_dst_callback(struct cn_msg *msg)
struct dst_node *n = NULL, *tmp;
unsigned int hash;
+ if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN)) {
+ err = -EPERM;
+ goto out;
+ }
+
if (msg->len < sizeof(struct dst_ctl)) {
err = -EBADMSG;
goto out;
diff --git a/drivers/staging/pohmelfs/config.c b/drivers/staging/pohmelfs/config.c
index 90f962ee5fd..5d04bf5b021 100644
--- a/drivers/staging/pohmelfs/config.c
+++ b/drivers/staging/pohmelfs/config.c
@@ -527,10 +527,13 @@ out_unlock:
return err;
}
-static void pohmelfs_cn_callback(struct cn_msg *msg)
+static void pohmelfs_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
{
int err;
+ if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN))
+ return;
+
switch (msg->flags) {
case POHMELFS_FLAGS_ADD:
case POHMELFS_FLAGS_DEL:
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 333ee02e7b2..864f0ba6a34 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -993,7 +993,7 @@ skip_io_on_zombie:
return retval;
}
-static struct file_operations fops = {
+static const struct file_operations fops = {
.owner = THIS_MODULE,
.read = usbtmc_read,
.write = usbtmc_write,
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index 29500154d00..2d867fd2241 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -875,7 +875,7 @@ printer_ioctl(struct file *fd, unsigned int code, unsigned long arg)
}
/* used after endpoint configuration */
-static struct file_operations printer_io_operations = {
+static const struct file_operations printer_io_operations = {
.owner = THIS_MODULE,
.open = printer_open,
.read = printer_read,
diff --git a/drivers/usb/host/whci/debug.c b/drivers/usb/host/whci/debug.c
index cf2d45946c5..2273c815941 100644
--- a/drivers/usb/host/whci/debug.c
+++ b/drivers/usb/host/whci/debug.c
@@ -134,7 +134,7 @@ static int pzl_open(struct inode *inode, struct file *file)
return single_open(file, pzl_print, inode->i_private);
}
-static struct file_operations di_fops = {
+static const struct file_operations di_fops = {
.open = di_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -142,7 +142,7 @@ static struct file_operations di_fops = {
.owner = THIS_MODULE,
};
-static struct file_operations asl_fops = {
+static const struct file_operations asl_fops = {
.open = asl_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -150,7 +150,7 @@ static struct file_operations asl_fops = {
.owner = THIS_MODULE,
};
-static struct file_operations pzl_fops = {
+static const struct file_operations pzl_fops = {
.open = pzl_open,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
index d645f3899fe..32d0199d0c3 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -429,8 +429,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
return read_count;
}
-static struct
-file_operations usb_rio_fops = {
+static const struct file_operations usb_rio_fops = {
.owner = THIS_MODULE,
.read = read_rio,
.write = write_rio,
diff --git a/drivers/uwb/uwb-debug.c b/drivers/uwb/uwb-debug.c
index 4a42993700c..2eecec0c13c 100644
--- a/drivers/uwb/uwb-debug.c
+++ b/drivers/uwb/uwb-debug.c
@@ -205,7 +205,7 @@ static ssize_t command_write(struct file *file, const char __user *buf,
return ret < 0 ? ret : len;
}
-static struct file_operations command_fops = {
+static const struct file_operations command_fops = {
.open = command_open,
.write = command_write,
.read = NULL,
@@ -255,7 +255,7 @@ static int reservations_open(struct inode *inode, struct file *file)
return single_open(file, reservations_print, inode->i_private);
}
-static struct file_operations reservations_fops = {
+static const struct file_operations reservations_fops = {
.open = reservations_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -283,7 +283,7 @@ static int drp_avail_open(struct inode *inode, struct file *file)
return single_open(file, drp_avail_print, inode->i_private);
}
-static struct file_operations drp_avail_fops = {
+static const struct file_operations drp_avail_fops = {
.open = drp_avail_open,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index e98baf6916b..e35232a1857 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -67,11 +67,14 @@ static DEFINE_MUTEX(uvfb_lock);
* find the kernel part of the task struct, copy the registers and
* the buffer contents and then complete the task.
*/
-static void uvesafb_cn_callback(struct cn_msg *msg)
+static void uvesafb_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
{
struct uvesafb_task *utask;
struct uvesafb_ktask *task;
+ if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN))
+ return;
+
if (msg->seq >= UVESAFB_TASKS_MAX)
return;
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c
index 52ccb3d3a96..45c126fea31 100644
--- a/drivers/w1/w1_netlink.c
+++ b/drivers/w1/w1_netlink.c
@@ -306,7 +306,7 @@ static int w1_netlink_send_error(struct cn_msg *rcmsg, struct w1_netlink_msg *rm
return error;
}
-static void w1_cn_callback(struct cn_msg *msg)
+static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
{
struct w1_netlink_msg *m = (struct w1_netlink_msg *)(msg + 1);
struct w1_netlink_cmd *cmd;