summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2012-05-15 11:21:26 +0400
committerHerbert Xu <herbert@gondor.apana.org.au>2012-05-15 11:21:26 +0400
commitb29e2679d0da91c60d3ac190d9c3bd65ac2f68c5 (patch)
tree518ec8f4bfd316e91bcc30f434edb78529557eba /drivers/net
parent8a63b1994c500d4825ee73dc71502deffe5b135b (diff)
parent4bb2d1009f671815870e8f78e826e4f9071392a7 (diff)
downloadlinux-b29e2679d0da91c60d3ac190d9c3bd65ac2f68c5.tar.xz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux
Merge mainline to add prerequisite for ARM ux500 crypto support.
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/Space.c2
-rw-r--r--drivers/net/bonding/bond_main.c82
-rw-r--r--drivers/net/bonding/bonding.h18
-rw-r--r--drivers/net/ethernet/broadcom/cnic.c12
-rw-r--r--drivers/net/ethernet/broadcom/cnic_defs.h28
-rw-r--r--drivers/net/ethernet/broadcom/cnic_if.h4
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c25
-rw-r--r--drivers/net/ethernet/broadcom/tg3.h1
-rw-r--r--drivers/net/ethernet/cirrus/Kconfig19
-rw-r--r--drivers/net/ethernet/cirrus/cs89x0.c148
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c39
-rw-r--r--drivers/net/ethernet/freescale/gianfar.h2
-rw-r--r--drivers/net/ethernet/marvell/sky2.c11
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic.h4
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c4
-rw-r--r--drivers/net/ethernet/smsc/smc91x.c2
-rw-r--r--drivers/net/irda/Kconfig2
-rw-r--r--drivers/net/irda/sa1100_ir.c953
-rw-r--r--drivers/net/usb/cdc-phonet.c6
-rw-r--r--drivers/net/usb/qmi_wwan.c36
-rw-r--r--drivers/net/usb/usbnet.c11
-rw-r--r--drivers/net/wireless/iwlegacy/3945.c3
-rw-r--r--drivers/net/wireless/iwlegacy/4965-mac.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rx.c2
-rw-r--r--drivers/net/xen-netfront.c4
25 files changed, 815 insertions, 606 deletions
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index 068c3563e00f..88bbd8ffa7fe 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -190,8 +190,10 @@ static struct devprobe2 isa_probes[] __initdata = {
{seeq8005_probe, 0},
#endif
#ifdef CONFIG_CS89x0
+#ifndef CONFIG_CS89x0_PLATFORM
{cs89x0_probe, 0},
#endif
+#endif
#ifdef CONFIG_AT1700
{at1700_probe, 0},
#endif
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 0730203a19f2..b920d829692a 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -2573,12 +2573,16 @@ re_arm:
static int bond_has_this_ip(struct bonding *bond, __be32 ip)
{
struct vlan_entry *vlan;
+ struct net_device *vlan_dev;
- if (ip == bond->master_ip)
+ if (ip == bond_confirm_addr(bond->dev, 0, ip))
return 1;
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
- if (ip == vlan->vlan_ip)
+ rcu_read_lock();
+ vlan_dev = __vlan_find_dev_deep(bond->dev, vlan->vlan_id);
+ rcu_read_unlock();
+ if (vlan_dev && ip == bond_confirm_addr(vlan_dev, 0, ip))
return 1;
}
@@ -2620,17 +2624,19 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
int i, vlan_id;
__be32 *targets = bond->params.arp_targets;
struct vlan_entry *vlan;
- struct net_device *vlan_dev;
+ struct net_device *vlan_dev = NULL;
struct rtable *rt;
for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
+ __be32 addr;
if (!targets[i])
break;
pr_debug("basa: target %x\n", targets[i]);
if (!bond_vlan_used(bond)) {
pr_debug("basa: empty vlan: arp_send\n");
+ addr = bond_confirm_addr(bond->dev, targets[i], 0);
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
- bond->master_ip, 0);
+ addr, 0);
continue;
}
@@ -2655,8 +2661,9 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
if (rt->dst.dev == bond->dev) {
ip_rt_put(rt);
pr_debug("basa: rtdev == bond->dev: arp_send\n");
+ addr = bond_confirm_addr(bond->dev, targets[i], 0);
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
- bond->master_ip, 0);
+ addr, 0);
continue;
}
@@ -2674,10 +2681,11 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
}
}
- if (vlan_id) {
+ if (vlan_id && vlan_dev) {
ip_rt_put(rt);
+ addr = bond_confirm_addr(vlan_dev, targets[i], 0);
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
- vlan->vlan_ip, vlan_id);
+ addr, vlan_id);
continue;
}
@@ -3299,68 +3307,10 @@ static int bond_netdev_event(struct notifier_block *this,
return NOTIFY_DONE;
}
-/*
- * bond_inetaddr_event: handle inetaddr notifier chain events.
- *
- * We keep track of device IPs primarily to use as source addresses in
- * ARP monitor probes (rather than spewing out broadcasts all the time).
- *
- * We track one IP for the main device (if it has one), plus one per VLAN.
- */
-static int bond_inetaddr_event(struct notifier_block *this, unsigned long event, void *ptr)
-{
- struct in_ifaddr *ifa = ptr;
- struct net_device *vlan_dev, *event_dev = ifa->ifa_dev->dev;
- struct bond_net *bn = net_generic(dev_net(event_dev), bond_net_id);
- struct bonding *bond;
- struct vlan_entry *vlan;
-
- /* we only care about primary address */
- if(ifa->ifa_flags & IFA_F_SECONDARY)
- return NOTIFY_DONE;
-
- list_for_each_entry(bond, &bn->dev_list, bond_list) {
- if (bond->dev == event_dev) {
- switch (event) {
- case NETDEV_UP:
- bond->master_ip = ifa->ifa_local;
- return NOTIFY_OK;
- case NETDEV_DOWN:
- bond->master_ip = 0;
- return NOTIFY_OK;
- default:
- return NOTIFY_DONE;
- }
- }
-
- list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
- vlan_dev = __vlan_find_dev_deep(bond->dev,
- vlan->vlan_id);
- if (vlan_dev == event_dev) {
- switch (event) {
- case NETDEV_UP:
- vlan->vlan_ip = ifa->ifa_local;
- return NOTIFY_OK;
- case NETDEV_DOWN:
- vlan->vlan_ip = 0;
- return NOTIFY_OK;
- default:
- return NOTIFY_DONE;
- }
- }
- }
- }
- return NOTIFY_DONE;
-}
-
static struct notifier_block bond_netdev_notifier = {
.notifier_call = bond_netdev_event,
};
-static struct notifier_block bond_inetaddr_notifier = {
- .notifier_call = bond_inetaddr_event,
-};
-
/*---------------------------- Hashing Policies -----------------------------*/
/*
@@ -4929,7 +4879,6 @@ static int __init bonding_init(void)
}
register_netdevice_notifier(&bond_netdev_notifier);
- register_inetaddr_notifier(&bond_inetaddr_notifier);
out:
return res;
err:
@@ -4943,7 +4892,6 @@ err_link:
static void __exit bonding_exit(void)
{
unregister_netdevice_notifier(&bond_netdev_notifier);
- unregister_inetaddr_notifier(&bond_inetaddr_notifier);
bond_destroy_debugfs();
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 1aecc37e5b4d..9f2bae6616d3 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -21,6 +21,7 @@
#include <linux/cpumask.h>
#include <linux/in6.h>
#include <linux/netpoll.h>
+#include <linux/inetdevice.h>
#include "bond_3ad.h"
#include "bond_alb.h"
@@ -166,7 +167,6 @@ struct bond_parm_tbl {
struct vlan_entry {
struct list_head vlan_list;
- __be32 vlan_ip;
unsigned short vlan_id;
};
@@ -232,7 +232,6 @@ struct bonding {
struct list_head bond_list;
struct netdev_hw_addr_list mc_list;
int (*xmit_hash_policy)(struct sk_buff *, int);
- __be32 master_ip;
u16 rr_tx_counter;
struct ad_bond_info ad_info;
struct alb_bond_info alb_info;
@@ -378,6 +377,21 @@ static inline bool bond_is_slave_inactive(struct slave *slave)
return slave->inactive;
}
+static inline __be32 bond_confirm_addr(struct net_device *dev, __be32 dst, __be32 local)
+{
+ struct in_device *in_dev;
+ __be32 addr = 0;
+
+ rcu_read_lock();
+ in_dev = __in_dev_get_rcu(dev);
+
+ if (in_dev)
+ addr = inet_confirm_addr(in_dev, dst, local, RT_SCOPE_HOST);
+
+ rcu_read_unlock();
+ return addr;
+}
+
struct bond_net;
struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c
index 7b65716b8734..c95e7b5e2b85 100644
--- a/drivers/net/ethernet/broadcom/cnic.c
+++ b/drivers/net/ethernet/broadcom/cnic.c
@@ -47,6 +47,7 @@
#include "bnx2x/bnx2x_hsi.h"
#include "../../../scsi/bnx2i/57xx_iscsi_constants.h"
#include "../../../scsi/bnx2i/57xx_iscsi_hsi.h"
+#include "../../../scsi/bnx2fc/bnx2fc_constants.h"
#include "cnic.h"
#include "cnic_defs.h"
@@ -2547,7 +2548,7 @@ static void cnic_bnx2x_kwqe_err(struct cnic_dev *dev, struct kwqe *kwqe)
}
kcqe.kcqe_op_flag = kcqe_op << KCQE_FLAGS_OPCODE_SHIFT;
kcqe.kcqe_op_flag |= KCQE_FLAGS_LAYER_MASK_L5_FCOE;
- kcqe.kcqe_info1 = FCOE_KCQE_COMPLETION_STATUS_NIC_ERROR;
+ kcqe.kcqe_info1 = FCOE_KCQE_COMPLETION_STATUS_PARITY_ERROR;
kcqe.kcqe_info2 = cid;
kcqe.kcqe_info0 = l5_cid;
@@ -2558,7 +2559,7 @@ static void cnic_bnx2x_kwqe_err(struct cnic_dev *dev, struct kwqe *kwqe)
kcqe.kcqe_op_flag = (opcode + 0x10) << KCQE_FLAGS_OPCODE_SHIFT;
kcqe.kcqe_op_flag |= KCQE_FLAGS_LAYER_MASK_L5_ISCSI;
- kcqe.kcqe_info1 = ISCSI_KCQE_COMPLETION_STATUS_NIC_ERROR;
+ kcqe.kcqe_info1 = ISCSI_KCQE_COMPLETION_STATUS_PARITY_ERR;
kcqe.kcqe_info2 = cid;
cnic_get_l5_cid(cp, BNX2X_SW_CID(cid), &kcqe.kcqe_info0);
@@ -2577,7 +2578,7 @@ static void cnic_bnx2x_kwqe_err(struct cnic_dev *dev, struct kwqe *kwqe)
kcqe.kcqe_op_flag = (kcqe_op << KCQE_FLAGS_OPCODE_SHIFT) |
KCQE_FLAGS_LAYER_MASK_L4;
- l4kcqe->status = L4_KCQE_COMPLETION_STATUS_NIC_ERROR;
+ l4kcqe->status = L4_KCQE_COMPLETION_STATUS_PARITY_ERROR;
l4kcqe->cid = cid;
cnic_get_l5_cid(cp, BNX2X_SW_CID(cid), &l4kcqe->conn_id);
} else {
@@ -3933,7 +3934,8 @@ static void cnic_cm_process_kcqe(struct cnic_dev *dev, struct kcqe *kcqe)
case L4_KCQE_OPCODE_VALUE_CONNECT_COMPLETE:
if (l4kcqe->status == 0)
set_bit(SK_F_OFFLD_COMPLETE, &csk->flags);
- else if (l4kcqe->status == L4_KCQE_COMPLETION_STATUS_NIC_ERROR)
+ else if (l4kcqe->status ==
+ L4_KCQE_COMPLETION_STATUS_PARITY_ERROR)
set_bit(SK_F_HW_ERR, &csk->flags);
smp_mb__before_clear_bit();
@@ -3946,7 +3948,7 @@ static void cnic_cm_process_kcqe(struct cnic_dev *dev, struct kcqe *kcqe)
case L4_KCQE_OPCODE_VALUE_RESET_COMP:
case L5CM_RAMROD_CMD_ID_SEARCHER_DELETE:
case L5CM_RAMROD_CMD_ID_TERMINATE_OFFLOAD:
- if (l4kcqe->status == L4_KCQE_COMPLETION_STATUS_NIC_ERROR)
+ if (l4kcqe->status == L4_KCQE_COMPLETION_STATUS_PARITY_ERROR)
set_bit(SK_F_HW_ERR, &csk->flags);
cp->close_conn(csk, opcode);
diff --git a/drivers/net/ethernet/broadcom/cnic_defs.h b/drivers/net/ethernet/broadcom/cnic_defs.h
index 06ca00266d70..382c98b0cc0c 100644
--- a/drivers/net/ethernet/broadcom/cnic_defs.h
+++ b/drivers/net/ethernet/broadcom/cnic_defs.h
@@ -35,16 +35,6 @@
#define L5CM_RAMROD_CMD_ID_SEARCHER_DELETE (L5CM_RAMROD_CMD_ID_BASE + 14)
#define L5CM_RAMROD_CMD_ID_TERMINATE_OFFLOAD (L5CM_RAMROD_CMD_ID_BASE + 15)
-#define FCOE_KCQE_OPCODE_INIT_FUNC (0x10)
-#define FCOE_KCQE_OPCODE_DESTROY_FUNC (0x11)
-#define FCOE_KCQE_OPCODE_STAT_FUNC (0x12)
-#define FCOE_KCQE_OPCODE_OFFLOAD_CONN (0x15)
-#define FCOE_KCQE_OPCODE_ENABLE_CONN (0x16)
-#define FCOE_KCQE_OPCODE_DISABLE_CONN (0x17)
-#define FCOE_KCQE_OPCODE_DESTROY_CONN (0x18)
-#define FCOE_KCQE_OPCODE_CQ_EVENT_NOTIFICATION (0x20)
-#define FCOE_KCQE_OPCODE_FCOE_ERROR (0x21)
-
#define FCOE_RAMROD_CMD_ID_INIT_FUNC (FCOE_KCQE_OPCODE_INIT_FUNC)
#define FCOE_RAMROD_CMD_ID_DESTROY_FUNC (FCOE_KCQE_OPCODE_DESTROY_FUNC)
#define FCOE_RAMROD_CMD_ID_STAT_FUNC (FCOE_KCQE_OPCODE_STAT_FUNC)
@@ -54,23 +44,6 @@
#define FCOE_RAMROD_CMD_ID_DESTROY_CONN (FCOE_KCQE_OPCODE_DESTROY_CONN)
#define FCOE_RAMROD_CMD_ID_TERMINATE_CONN (0x81)
-#define FCOE_KWQE_OPCODE_INIT1 (0)
-#define FCOE_KWQE_OPCODE_INIT2 (1)
-#define FCOE_KWQE_OPCODE_INIT3 (2)
-#define FCOE_KWQE_OPCODE_OFFLOAD_CONN1 (3)
-#define FCOE_KWQE_OPCODE_OFFLOAD_CONN2 (4)
-#define FCOE_KWQE_OPCODE_OFFLOAD_CONN3 (5)
-#define FCOE_KWQE_OPCODE_OFFLOAD_CONN4 (6)
-#define FCOE_KWQE_OPCODE_ENABLE_CONN (7)
-#define FCOE_KWQE_OPCODE_DISABLE_CONN (8)
-#define FCOE_KWQE_OPCODE_DESTROY_CONN (9)
-#define FCOE_KWQE_OPCODE_DESTROY (10)
-#define FCOE_KWQE_OPCODE_STAT (11)
-
-#define FCOE_KCQE_COMPLETION_STATUS_ERROR (0x1)
-#define FCOE_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE (0x3)
-#define FCOE_KCQE_COMPLETION_STATUS_NIC_ERROR (0x5)
-
/* KCQ (kernel completion queue) response op codes */
#define L4_KCQE_OPCODE_VALUE_CLOSE_COMP (53)
#define L4_KCQE_OPCODE_VALUE_RESET_COMP (54)
@@ -87,6 +60,7 @@
/* KCQ (kernel completion queue) completion status */
#define L4_KCQE_COMPLETION_STATUS_SUCCESS (0)
#define L4_KCQE_COMPLETION_STATUS_NIC_ERROR (4)
+#define L4_KCQE_COMPLETION_STATUS_PARITY_ERROR (0x81)
#define L4_KCQE_COMPLETION_STATUS_TIMEOUT (0x93)
#define L4_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAIL (0x83)
diff --git a/drivers/net/ethernet/broadcom/cnic_if.h b/drivers/net/ethernet/broadcom/cnic_if.h
index 60deb84d36bd..289274e546be 100644
--- a/drivers/net/ethernet/broadcom/cnic_if.h
+++ b/drivers/net/ethernet/broadcom/cnic_if.h
@@ -12,8 +12,8 @@
#ifndef CNIC_IF_H
#define CNIC_IF_H
-#define CNIC_MODULE_VERSION "2.5.9"
-#define CNIC_MODULE_RELDATE "Feb 8, 2012"
+#define CNIC_MODULE_VERSION "2.5.10"
+#define CNIC_MODULE_RELDATE "March 21, 2012"
#define CNIC_ULP_RDMA 0
#define CNIC_ULP_ISCSI 1
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index b0657466041d..7b71387cf93c 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -89,10 +89,10 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
#define DRV_MODULE_NAME "tg3"
#define TG3_MAJ_NUM 3
-#define TG3_MIN_NUM 122
+#define TG3_MIN_NUM 123
#define DRV_MODULE_VERSION \
__stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE "December 7, 2011"
+#define DRV_MODULE_RELDATE "March 21, 2012"
#define RESET_KIND_SHUTDOWN 0
#define RESET_KIND_INIT 1
@@ -5953,8 +5953,10 @@ next_pkt_nopost:
tpr->rx_std_prod_idx = std_prod_idx & tp->rx_std_ring_mask;
tpr->rx_jmb_prod_idx = jmb_prod_idx & tp->rx_jmb_ring_mask;
- if (tnapi != &tp->napi[1])
+ if (tnapi != &tp->napi[1]) {
+ tp->rx_refill = true;
napi_schedule(&tp->napi[1].napi);
+ }
}
return received;
@@ -6134,6 +6136,7 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget)
u32 std_prod_idx = dpr->rx_std_prod_idx;
u32 jmb_prod_idx = dpr->rx_jmb_prod_idx;
+ tp->rx_refill = false;
for (i = 1; i < tp->irq_cnt; i++)
err |= tg3_rx_prodring_xfer(tp, dpr,
&tp->napi[i].prodring);
@@ -6197,9 +6200,25 @@ static int tg3_poll_msix(struct napi_struct *napi, int budget)
/* check for RX/TX work to do */
if (likely(sblk->idx[0].tx_consumer == tnapi->tx_cons &&
*(tnapi->rx_rcb_prod_idx) == tnapi->rx_rcb_ptr)) {
+
+ /* This test here is not race free, but will reduce
+ * the number of interrupts by looping again.
+ */
+ if (tnapi == &tp->napi[1] && tp->rx_refill)
+ continue;
+
napi_complete(napi);
/* Reenable interrupts. */
tw32_mailbox(tnapi->int_mbox, tnapi->last_tag << 24);
+
+ /* This test here is synchronized by napi_schedule()
+ * and napi_complete() to close the race condition.
+ */
+ if (unlikely(tnapi == &tp->napi[1] && tp->rx_refill)) {
+ tw32(HOSTCC_MODE, tp->coalesce_mode |
+ HOSTCC_MODE_ENABLE |
+ tnapi->coal_now);
+ }
mmiowb();
break;
}
diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h
index 66bcfca55261..93865f899a4f 100644
--- a/drivers/net/ethernet/broadcom/tg3.h
+++ b/drivers/net/ethernet/broadcom/tg3.h
@@ -3007,6 +3007,7 @@ struct tg3 {
u32 rx_std_max_post;
u32 rx_offset;
u32 rx_pkt_map_sz;
+ bool rx_refill;
/* begin "everything else" cacheline(s) section */
diff --git a/drivers/net/ethernet/cirrus/Kconfig b/drivers/net/ethernet/cirrus/Kconfig
index 1f8648f099c7..8388e36cf08f 100644
--- a/drivers/net/ethernet/cirrus/Kconfig
+++ b/drivers/net/ethernet/cirrus/Kconfig
@@ -5,8 +5,7 @@
config NET_VENDOR_CIRRUS
bool "Cirrus devices"
default y
- depends on ISA || EISA || MACH_IXDP2351 || ARCH_IXDP2X01 \
- || MACH_MX31ADS || MACH_QQ2440 || (ARM && ARCH_EP93XX) || MAC
+ depends on ISA || EISA || ARM || MAC
---help---
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
@@ -21,8 +20,7 @@ if NET_VENDOR_CIRRUS
config CS89x0
tristate "CS89x0 support"
- depends on (ISA || EISA || MACH_IXDP2351 \
- || ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440)
+ depends on ISA || EISA || ARM
---help---
Support for CS89x0 chipset based Ethernet cards. If you have a
network (Ethernet) card of this type, say Y and read the
@@ -33,10 +31,15 @@ config CS89x0
To compile this driver as a module, choose M here. The module
will be called cs89x0.
-config CS89x0_NONISA_IRQ
- def_bool y
- depends on CS89x0 != n
- depends on MACH_IXDP2351 || ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440
+config CS89x0_PLATFORM
+ bool "CS89x0 platform driver support"
+ depends on CS89x0
+ help
+ Say Y to compile the cs89x0 driver as a platform driver. This
+ makes this driver suitable for use on certain evaluation boards
+ such as the iMX21ADS.
+
+ If you are unsure, say N.
config EP93XX_ETH
tristate "EP93xx Ethernet support"
diff --git a/drivers/net/ethernet/cirrus/cs89x0.c b/drivers/net/ethernet/cirrus/cs89x0.c
index d5ff93653e4c..30fee428c489 100644
--- a/drivers/net/ethernet/cirrus/cs89x0.c
+++ b/drivers/net/ethernet/cirrus/cs89x0.c
@@ -100,9 +100,6 @@
*/
-/* Always include 'config.h' first in case the user wants to turn on
- or override something. */
-#include <linux/module.h>
/*
* Set this to zero to disable DMA code
@@ -131,9 +128,12 @@
*/
+#include <linux/module.h>
+#include <linux/printk.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
+#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fcntl.h>
@@ -151,6 +151,7 @@
#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h>
+#include <linux/atomic.h>
#if ALLOW_DMA
#include <asm/dma.h>
#endif
@@ -174,26 +175,20 @@ static char version[] __initdata =
them to system IRQ numbers. This mapping is card specific and is set to
the configuration of the Cirrus Eval board for this chip. */
#if defined(CONFIG_MACH_IXDP2351)
+#define CS89x0_NONISA_IRQ
static unsigned int netcard_portlist[] __used __initdata = {IXDP2351_VIRT_CS8900_BASE, 0};
static unsigned int cs8900_irq_map[] = {IRQ_IXDP2351_CS8900, 0, 0, 0};
#elif defined(CONFIG_ARCH_IXDP2X01)
+#define CS89x0_NONISA_IRQ
static unsigned int netcard_portlist[] __used __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0};
static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0};
-#elif defined(CONFIG_MACH_QQ2440)
-#include <mach/qq2440.h>
-static unsigned int netcard_portlist[] __used __initdata = { QQ2440_CS8900_VIRT_BASE + 0x300, 0 };
-static unsigned int cs8900_irq_map[] = { QQ2440_CS8900_IRQ, 0, 0, 0 };
-#elif defined(CONFIG_MACH_MX31ADS)
-#include <mach/board-mx31ads.h>
-static unsigned int netcard_portlist[] __used __initdata = {
- PBC_BASE_ADDRESS + PBC_CS8900A_IOBASE + 0x300, 0
-};
-static unsigned cs8900_irq_map[] = {EXPIO_INT_ENET_INT, 0, 0, 0};
#else
+#ifndef CONFIG_CS89x0_PLATFORM
static unsigned int netcard_portlist[] __used __initdata =
{ 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
static unsigned int cs8900_irq_map[] = {10,11,12,5};
#endif
+#endif
#if DEBUGGING
static unsigned int net_debug = DEBUGGING;
@@ -236,11 +231,16 @@ struct net_local {
unsigned char *end_dma_buff; /* points to the end of the buffer */
unsigned char *rx_dma_ptr; /* points to the next packet */
#endif
+#ifdef CONFIG_CS89x0_PLATFORM
+ void __iomem *virt_addr;/* Virtual address for accessing the CS89x0. */
+ unsigned long phys_addr;/* Physical address for accessing the CS89x0. */
+ unsigned long size; /* Length of CS89x0 memory region. */
+#endif
};
/* Index to functions, as function prototypes. */
-static int cs89x0_probe1(struct net_device *dev, int ioaddr, int modular);
+static int cs89x0_probe1(struct net_device *dev, unsigned long ioaddr, int modular);
static int net_open(struct net_device *dev);
static netdev_tx_t net_send_packet(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t net_interrupt(int irq, void *dev_id);
@@ -294,6 +294,7 @@ static int __init media_fn(char *str)
__setup("cs89x0_media=", media_fn);
+#ifndef CONFIG_CS89x0_PLATFORM
/* Check for a network adaptor of this type, and return '0' iff one exists.
If dev->base_addr == 0, probe all likely locations.
If dev->base_addr == 1, always return failure.
@@ -343,6 +344,7 @@ out:
return ERR_PTR(err);
}
#endif
+#endif
#if defined(CONFIG_MACH_IXDP2351)
static u16
@@ -504,7 +506,7 @@ static const struct net_device_ops net_ops = {
*/
static int __init
-cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
+cs89x0_probe1(struct net_device *dev, unsigned long ioaddr, int modular)
{
struct net_local *lp = netdev_priv(dev);
static unsigned version_printed;
@@ -529,15 +531,12 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
lp->force = g_cs89x0_media__force;
#endif
-#if defined(CONFIG_MACH_QQ2440)
- lp->force |= FORCE_RJ45 | FORCE_FULL;
-#endif
}
/* Grab the region so we can find another board if autoIRQ fails. */
/* WTF is going on here? */
if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, DRV_NAME)) {
- printk(KERN_ERR "%s: request_region(0x%x, 0x%x) failed\n",
+ printk(KERN_ERR "%s: request_region(0x%lx, 0x%x) failed\n",
DRV_NAME, ioaddr, NETCARD_IO_EXTENT);
retval = -EBUSY;
goto out1;
@@ -549,7 +548,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
will skip the test for the ADD_PORT. */
if (ioaddr & 1) {
if (net_debug > 1)
- printk(KERN_INFO "%s: odd ioaddr 0x%x\n", dev->name, ioaddr);
+ printk(KERN_INFO "%s: odd ioaddr 0x%lx\n", dev->name, ioaddr);
if ((ioaddr & 2) != 2)
if ((readword(ioaddr & ~3, ADD_PORT) & ADD_MASK) != ADD_SIG) {
printk(KERN_ERR "%s: bad signature 0x%x\n",
@@ -560,13 +559,13 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
}
ioaddr &= ~3;
- printk(KERN_DEBUG "PP_addr at %x[%x]: 0x%x\n",
+ printk(KERN_DEBUG "PP_addr at %lx[%x]: 0x%x\n",
ioaddr, ADD_PORT, readword(ioaddr, ADD_PORT));
writeword(ioaddr, ADD_PORT, PP_ChipID);
tmp = readword(ioaddr, DATA_PORT);
if (tmp != CHIP_EISA_ID_SIG) {
- printk(KERN_DEBUG "%s: incorrect signature at %x[%x]: 0x%x!="
+ printk(KERN_DEBUG "%s: incorrect signature at %lx[%x]: 0x%x!="
CHIP_EISA_ID_SIG_STR "\n",
dev->name, ioaddr, DATA_PORT, tmp);
retval = -ENODEV;
@@ -736,8 +735,9 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
dev->irq = i;
} else {
i = lp->isa_config & INT_NO_MASK;
+#ifndef CONFIG_CS89x0_PLATFORM
if (lp->chip_type == CS8900) {
-#ifdef CONFIG_CS89x0_NONISA_IRQ
+#ifdef CS89x0_NONISA_IRQ
i = cs8900_irq_map[0];
#else
/* Translate the IRQ using the IRQ mapping table. */
@@ -758,6 +758,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
}
#endif
}
+#endif
if (!dev->irq)
dev->irq = i;
}
@@ -1168,6 +1169,7 @@ write_irq(struct net_device *dev, int chip_type, int irq)
int i;
if (chip_type == CS8900) {
+#ifndef CONFIG_CS89x0_PLATFORM
/* Search the mapping table for the corresponding IRQ pin. */
for (i = 0; i != ARRAY_SIZE(cs8900_irq_map); i++)
if (cs8900_irq_map[i] == irq)
@@ -1175,6 +1177,10 @@ write_irq(struct net_device *dev, int chip_type, int irq)
/* Not found */
if (i == ARRAY_SIZE(cs8900_irq_map))
i = 3;
+#else
+ /* INTRQ0 pin is used for interrupt generation. */
+ i = 0;
+#endif
writereg(dev, PP_CS8900_ISAINT, i);
} else {
writereg(dev, PP_CS8920_ISAINT, irq);
@@ -1228,7 +1234,7 @@ net_open(struct net_device *dev)
}
else
{
-#ifndef CONFIG_CS89x0_NONISA_IRQ
+#if !defined(CS89x0_NONISA_IRQ) && !defined(CONFIG_CS89x0_PLATFORM)
if (((1 << dev->irq) & lp->irq_map) == 0) {
printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
dev->name, dev->irq, lp->irq_map);
@@ -1746,7 +1752,7 @@ static int set_mac_address(struct net_device *dev, void *p)
return 0;
}
-#ifdef MODULE
+#if defined(MODULE) && !defined(CONFIG_CS89x0_PLATFORM)
static struct net_device *dev_cs89x0;
@@ -1900,7 +1906,97 @@ cleanup_module(void)
release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT);
free_netdev(dev_cs89x0);
}
-#endif /* MODULE */
+#endif /* MODULE && !CONFIG_CS89x0_PLATFORM */
+
+#ifdef CONFIG_CS89x0_PLATFORM
+static int __init cs89x0_platform_probe(struct platform_device *pdev)
+{
+ struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
+ struct net_local *lp;
+ struct resource *mem_res;
+ int err;
+
+ if (!dev)
+ return -ENOMEM;
+
+ lp = netdev_priv(dev);
+
+ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ dev->irq = platform_get_irq(pdev, 0);
+ if (mem_res == NULL || dev->irq <= 0) {
+ dev_warn(&dev->dev, "memory/interrupt resource missing.\n");
+ err = -ENXIO;
+ goto free;
+ }
+
+ lp->phys_addr = mem_res->start;
+ lp->size = resource_size(mem_res);
+ if (!request_mem_region(lp->phys_addr, lp->size, DRV_NAME)) {
+ dev_warn(&dev->dev, "request_mem_region() failed.\n");
+ err = -EBUSY;
+ goto free;
+ }
+
+ lp->virt_addr = ioremap(lp->phys_addr, lp->size);
+ if (!lp->virt_addr) {
+ dev_warn(&dev->dev, "ioremap() failed.\n");
+ err = -ENOMEM;
+ goto release;
+ }
+
+ err = cs89x0_probe1(dev, (unsigned long)lp->virt_addr, 0);
+ if (err) {
+ dev_warn(&dev->dev, "no cs8900 or cs8920 detected.\n");
+ goto unmap;
+ }
+
+ platform_set_drvdata(pdev, dev);
+ return 0;
+
+unmap:
+ iounmap(lp->virt_addr);
+release:
+ release_mem_region(lp->phys_addr, lp->size);
+free:
+ free_netdev(dev);
+ return err;
+}
+
+static int cs89x0_platform_remove(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct net_local *lp = netdev_priv(dev);
+
+ unregister_netdev(dev);
+ iounmap(lp->virt_addr);
+ release_mem_region(lp->phys_addr, lp->size);
+ free_netdev(dev);
+ return 0;
+}
+
+static struct platform_driver cs89x0_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+ .remove = cs89x0_platform_remove,
+};
+
+static int __init cs89x0_init(void)
+{
+ return platform_driver_probe(&cs89x0_driver, cs89x0_platform_probe);
+}
+
+module_init(cs89x0_init);
+
+static void __exit cs89x0_cleanup(void)
+{
+ platform_driver_unregister(&cs89x0_driver);
+}
+
+module_exit(cs89x0_cleanup);
+
+#endif /* CONFIG_CS89x0_PLATFORM */
/*
* Local variables:
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index d9428f0e738a..e7bed5303997 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -968,7 +968,6 @@ static int gfar_probe(struct platform_device *ofdev)
struct gfar_private *priv = NULL;
struct gfar __iomem *regs = NULL;
int err = 0, i, grp_idx = 0;
- int len_devname;
u32 rstat = 0, tstat = 0, rqueue = 0, tqueue = 0;
u32 isrg = 0;
u32 __iomem *baddr;
@@ -1169,40 +1168,16 @@ static int gfar_probe(struct platform_device *ofdev)
priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
/* fill out IRQ number and name fields */
- len_devname = strlen(dev->name);
for (i = 0; i < priv->num_grps; i++) {
- strncpy(&priv->gfargrp[i].int_name_tx[0], dev->name,
- len_devname);
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
- strncpy(&priv->gfargrp[i].int_name_tx[len_devname],
- "_g", sizeof("_g"));
- priv->gfargrp[i].int_name_tx[
- strlen(priv->gfargrp[i].int_name_tx)] = i+48;
- strncpy(&priv->gfargrp[i].int_name_tx[strlen(
- priv->gfargrp[i].int_name_tx)],
- "_tx", sizeof("_tx") + 1);
-
- strncpy(&priv->gfargrp[i].int_name_rx[0], dev->name,
- len_devname);
- strncpy(&priv->gfargrp[i].int_name_rx[len_devname],
- "_g", sizeof("_g"));
- priv->gfargrp[i].int_name_rx[
- strlen(priv->gfargrp[i].int_name_rx)] = i+48;
- strncpy(&priv->gfargrp[i].int_name_rx[strlen(
- priv->gfargrp[i].int_name_rx)],
- "_rx", sizeof("_rx") + 1);
-
- strncpy(&priv->gfargrp[i].int_name_er[0], dev->name,
- len_devname);
- strncpy(&priv->gfargrp[i].int_name_er[len_devname],
- "_g", sizeof("_g"));
- priv->gfargrp[i].int_name_er[strlen(
- priv->gfargrp[i].int_name_er)] = i+48;
- strncpy(&priv->gfargrp[i].int_name_er[strlen(\
- priv->gfargrp[i].int_name_er)],
- "_er", sizeof("_er") + 1);
+ sprintf(priv->gfargrp[i].int_name_tx, "%s%s%c%s",
+ dev->name, "_g", '0' + i, "_tx");
+ sprintf(priv->gfargrp[i].int_name_rx, "%s%s%c%s",
+ dev->name, "_g", '0' + i, "_rx");
+ sprintf(priv->gfargrp[i].int_name_er, "%s%s%c%s",
+ dev->name, "_g", '0' + i, "_er");
} else
- priv->gfargrp[i].int_name_tx[len_devname] = '\0';
+ strcpy(priv->gfargrp[i].int_name_tx, dev->name);
}
/* Initialize the filer table */
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index fc2488adca36..4c9f8d487dbb 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -517,7 +517,7 @@ extern const char gfar_driver_version[];
#define RXFCB_PERR_MASK 0x000c
#define RXFCB_PERR_BADL3 0x0008
-#define GFAR_INT_NAME_MAX IFNAMSIZ + 4
+#define GFAR_INT_NAME_MAX (IFNAMSIZ + 6) /* '_g#_xx' */
struct txbd8
{
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 82c2c86a1951..423a1a2a702e 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -95,6 +95,10 @@ static int disable_msi = 0;
module_param(disable_msi, int, 0);
MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
+static int legacy_pme = 0;
+module_param(legacy_pme, int, 0);
+MODULE_PARM_DESC(legacy_pme, "Legacy power management");
+
static DEFINE_PCI_DEVICE_TABLE(sky2_id_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, /* SK-9Sxx */
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */
@@ -867,6 +871,13 @@ static void sky2_wol_init(struct sky2_port *sky2)
/* Disable PiG firmware */
sky2_write16(hw, B0_CTST, Y2_HW_WOL_OFF);
+ /* Needed by some broken BIOSes, use PCI rather than PCI-e for WOL */
+ if (legacy_pme) {
+ u32 reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
+ reg1 |= PCI_Y2_PME_LEGACY;
+ sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
+ }
+
/* block receiver */
sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
sky2_read32(hw, B0_CTST);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 2b5af22419a5..385a4d5c7c25 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -36,8 +36,8 @@
#define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 0
-#define _QLCNIC_LINUX_SUBVERSION 25
-#define QLCNIC_LINUX_VERSIONID "5.0.26"
+#define _QLCNIC_LINUX_SUBVERSION 27
+#define QLCNIC_LINUX_VERSIONID "5.0.27"
#define QLCNIC_DRV_IDC_VER 0x01
#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\
(_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 81bb1a69e69f..75c32e875fef 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -1458,8 +1458,10 @@ qlcnic_reset_context(struct qlcnic_adapter *adapter)
if (netif_running(netdev)) {
err = qlcnic_attach(adapter);
- if (!err)
+ if (!err) {
__qlcnic_up(adapter, netdev);
+ qlcnic_restore_indev_addr(netdev, NETDEV_UP);
+ }
}
netif_device_attach(netdev);
diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
index 1dc4fad593e7..fee449355014 100644
--- a/drivers/net/ethernet/smsc/smc91x.c
+++ b/drivers/net/ethernet/smsc/smc91x.c
@@ -2280,7 +2280,7 @@ static int __devinit smc_drv_probe(struct platform_device *pdev)
if (ret)
goto out_release_io;
#if defined(CONFIG_SA1100_ASSABET)
- NCR_0 |= NCR_ENET_OSC_EN;
+ neponset_ncr_set(NCR_ENET_OSC_EN);
#endif
platform_set_drvdata(pdev, ndev);
ret = smc_enable_device(pdev);
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index e535137eb2d0..468047866c8c 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -356,7 +356,7 @@ config VLSI_FIR
config SA1100_FIR
tristate "SA1100 Internal IR"
- depends on ARCH_SA1100 && IRDA
+ depends on ARCH_SA1100 && IRDA && DMA_SA11X0
config VIA_FIR
tristate "VIA VT8231/VT1211 SIR/MIR/FIR"
diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
index da2705061a60..a0d1913a58d3 100644
--- a/drivers/net/irda/sa1100_ir.c
+++ b/drivers/net/irda/sa1100_ir.c
@@ -15,7 +15,7 @@
* This driver takes one kernel command line parameter, sa1100ir=, with
* the following options:
* max_rate:baudrate - set the maximum baud rate
- * power_leve:level - set the transmitter power level
+ * power_level:level - set the transmitter power level
* tx_lpm:0|1 - set transmit low power mode
*/
#include <linux/module.h>
@@ -30,13 +30,13 @@
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/sa11x0-dma.h>
#include <net/irda/irda.h>
#include <net/irda/wrapper.h>
#include <net/irda/irda_device.h>
-#include <asm/irq.h>
-#include <mach/dma.h>
#include <mach/hardware.h>
#include <asm/mach/irda.h>
@@ -44,8 +44,15 @@ static int power_level = 3;
static int tx_lpm;
static int max_rate = 4000000;
+struct sa1100_buf {
+ struct device *dev;
+ struct sk_buff *skb;
+ struct scatterlist sg;
+ struct dma_chan *chan;
+ dma_cookie_t cookie;
+};
+
struct sa1100_irda {
- unsigned char hscr0;
unsigned char utcr4;
unsigned char power;
unsigned char open;
@@ -53,12 +60,8 @@ struct sa1100_irda {
int speed;
int newspeed;
- struct sk_buff *txskb;
- struct sk_buff *rxskb;
- dma_addr_t txbuf_dma;
- dma_addr_t rxbuf_dma;
- dma_regs_t *txdma;
- dma_regs_t *rxdma;
+ struct sa1100_buf dma_rx;
+ struct sa1100_buf dma_tx;
struct device *dev;
struct irda_platform_data *pdata;
@@ -67,23 +70,103 @@ struct sa1100_irda {
iobuff_t tx_buff;
iobuff_t rx_buff;
+
+ int (*tx_start)(struct sk_buff *, struct net_device *, struct sa1100_irda *);
+ irqreturn_t (*irq)(struct net_device *, struct sa1100_irda *);
};
+static int sa1100_irda_set_speed(struct sa1100_irda *, int);
+
#define IS_FIR(si) ((si)->speed >= 4000000)
#define HPSIR_MAX_RXLEN 2047
+static struct dma_slave_config sa1100_irda_sir_tx = {
+ .direction = DMA_TO_DEVICE,
+ .dst_addr = __PREG(Ser2UTDR),
+ .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
+ .dst_maxburst = 4,
+};
+
+static struct dma_slave_config sa1100_irda_fir_rx = {
+ .direction = DMA_FROM_DEVICE,
+ .src_addr = __PREG(Ser2HSDR),
+ .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
+ .src_maxburst = 8,
+};
+
+static struct dma_slave_config sa1100_irda_fir_tx = {
+ .direction = DMA_TO_DEVICE,
+ .dst_addr = __PREG(Ser2HSDR),
+ .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
+ .dst_maxburst = 8,
+};
+
+static unsigned sa1100_irda_dma_xferred(struct sa1100_buf *buf)
+{
+ struct dma_chan *chan = buf->chan;
+ struct dma_tx_state state;
+ enum dma_status status;
+
+ status = chan->device->device_tx_status(chan, buf->cookie, &state);
+ if (status != DMA_PAUSED)
+ return 0;
+
+ return sg_dma_len(&buf->sg) - state.residue;
+}
+
+static int sa1100_irda_dma_request(struct device *dev, struct sa1100_buf *buf,
+ const char *name, struct dma_slave_config *cfg)
+{
+ dma_cap_mask_t m;
+ int ret;
+
+ dma_cap_zero(m);
+ dma_cap_set(DMA_SLAVE, m);
+
+ buf->chan = dma_request_channel(m, sa11x0_dma_filter_fn, (void *)name);
+ if (!buf->chan) {
+ dev_err(dev, "unable to request DMA channel for %s\n",
+ name);
+ return -ENOENT;
+ }
+
+ ret = dmaengine_slave_config(buf->chan, cfg);
+ if (ret)
+ dev_warn(dev, "DMA slave_config for %s returned %d\n",
+ name, ret);
+
+ buf->dev = buf->chan->device->dev;
+
+ return 0;
+}
+
+static void sa1100_irda_dma_start(struct sa1100_buf *buf,
+ enum dma_transfer_direction dir, dma_async_tx_callback cb, void *cb_p)
+{
+ struct dma_async_tx_descriptor *desc;
+ struct dma_chan *chan = buf->chan;
+
+ desc = chan->device->device_prep_slave_sg(chan, &buf->sg, 1, dir,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (desc) {
+ desc->callback = cb;
+ desc->callback_param = cb_p;
+ buf->cookie = dmaengine_submit(desc);
+ dma_async_issue_pending(chan);
+ }
+}
+
/*
* Allocate and map the receive buffer, unless it is already allocated.
*/
static int sa1100_irda_rx_alloc(struct sa1100_irda *si)
{
- if (si->rxskb)
+ if (si->dma_rx.skb)
return 0;
- si->rxskb = alloc_skb(HPSIR_MAX_RXLEN + 1, GFP_ATOMIC);
-
- if (!si->rxskb) {
+ si->dma_rx.skb = alloc_skb(HPSIR_MAX_RXLEN + 1, GFP_ATOMIC);
+ if (!si->dma_rx.skb) {
printk(KERN_ERR "sa1100_ir: out of memory for RX SKB\n");
return -ENOMEM;
}
@@ -92,11 +175,14 @@ static int sa1100_irda_rx_alloc(struct sa1100_irda *si)
* Align any IP headers that may be contained
* within the frame.
*/
- skb_reserve(si->rxskb, 1);
+ skb_reserve(si->dma_rx.skb, 1);
+
+ sg_set_buf(&si->dma_rx.sg, si->dma_rx.skb->data, HPSIR_MAX_RXLEN);
+ if (dma_map_sg(si->dma_rx.dev, &si->dma_rx.sg, 1, DMA_FROM_DEVICE) == 0) {
+ dev_kfree_skb_any(si->dma_rx.skb);
+ return -ENOMEM;
+ }
- si->rxbuf_dma = dma_map_single(si->dev, si->rxskb->data,
- HPSIR_MAX_RXLEN,
- DMA_FROM_DEVICE);
return 0;
}
@@ -106,7 +192,7 @@ static int sa1100_irda_rx_alloc(struct sa1100_irda *si)
*/
static void sa1100_irda_rx_dma_start(struct sa1100_irda *si)
{
- if (!si->rxskb) {
+ if (!si->dma_rx.skb) {
printk(KERN_ERR "sa1100_ir: rx buffer went missing\n");
return;
}
@@ -114,254 +200,87 @@ static void sa1100_irda_rx_dma_start(struct sa1100_irda *si)
/*
* First empty receive FIFO
*/
- Ser2HSCR0 = si->hscr0 | HSCR0_HSSP;
+ Ser2HSCR0 = HSCR0_HSSP;
/*
* Enable the DMA, receiver and receive interrupt.
*/
- sa1100_clear_dma(si->rxdma);
- sa1100_start_dma(si->rxdma, si->rxbuf_dma, HPSIR_MAX_RXLEN);
- Ser2HSCR0 = si->hscr0 | HSCR0_HSSP | HSCR0_RXE;
+ dmaengine_terminate_all(si->dma_rx.chan);
+ sa1100_irda_dma_start(&si->dma_rx, DMA_DEV_TO_MEM, NULL, NULL);
+
+ Ser2HSCR0 = HSCR0_HSSP | HSCR0_RXE;
}
-/*
- * Set the IrDA communications speed.
- */
-static int sa1100_irda_set_speed(struct sa1100_irda *si, int speed)
+static void sa1100_irda_check_speed(struct sa1100_irda *si)
{
- unsigned long flags;
- int brd, ret = -EINVAL;
-
- switch (speed) {
- case 9600: case 19200: case 38400:
- case 57600: case 115200:
- brd = 3686400 / (16 * speed) - 1;
-
- /*
- * Stop the receive DMA.
- */
- if (IS_FIR(si))
- sa1100_stop_dma(si->rxdma);
-
- local_irq_save(flags);
-
- Ser2UTCR3 = 0;
- Ser2HSCR0 = HSCR0_UART;
-
- Ser2UTCR1 = brd >> 8;
- Ser2UTCR2 = brd;
-
- /*
- * Clear status register
- */
- Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID;
- Ser2UTCR3 = UTCR3_RIE | UTCR3_RXE | UTCR3_TXE;
-
- if (si->pdata->set_speed)
- si->pdata->set_speed(si->dev, speed);
-
- si->speed = speed;
-
- local_irq_restore(flags);
- ret = 0;
- break;
-
- case 4000000:
- local_irq_save(flags);
-
- si->hscr0 = 0;
-
- Ser2HSSR0 = 0xff;
- Ser2HSCR0 = si->hscr0 | HSCR0_HSSP;
- Ser2UTCR3 = 0;
-
- si->speed = speed;
-
- if (si->pdata->set_speed)
- si->pdata->set_speed(si->dev, speed);
-
- sa1100_irda_rx_alloc(si);
- sa1100_irda_rx_dma_start(si);
-
- local_irq_restore(flags);
-
- break;
-
- default:
- break;
+ if (si->newspeed) {
+ sa1100_irda_set_speed(si, si->newspeed);
+ si->newspeed = 0;
}
-
- return ret;
}
/*
- * Control the power state of the IrDA transmitter.
- * State:
- * 0 - off
- * 1 - short range, lowest power
- * 2 - medium range, medium power
- * 3 - maximum range, high power
- *
- * Currently, only assabet is known to support this.
+ * HP-SIR format support.
*/
-static int
-__sa1100_irda_set_power(struct sa1100_irda *si, unsigned int state)
+static void sa1100_irda_sirtxdma_irq(void *id)
{
- int ret = 0;
- if (si->pdata->set_power)
- ret = si->pdata->set_power(si->dev, state);
- return ret;
-}
-
-static inline int
-sa1100_set_power(struct sa1100_irda *si, unsigned int state)
-{
- int ret;
-
- ret = __sa1100_irda_set_power(si, state);
- if (ret == 0)
- si->power = state;
+ struct net_device *dev = id;
+ struct sa1100_irda *si = netdev_priv(dev);
- return ret;
-}
+ dma_unmap_sg(si->dma_tx.dev, &si->dma_tx.sg, 1, DMA_TO_DEVICE);
+ dev_kfree_skb(si->dma_tx.skb);
+ si->dma_tx.skb = NULL;
-static int sa1100_irda_startup(struct sa1100_irda *si)
-{
- int ret;
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += sg_dma_len(&si->dma_tx.sg);
- /*
- * Ensure that the ports for this device are setup correctly.
- */
- if (si->pdata->startup) {
- ret = si->pdata->startup(si->dev);
- if (ret)
- return ret;
- }
-
- /*
- * Configure PPC for IRDA - we want to drive TXD2 low.
- * We also want to drive this pin low during sleep.
- */
- PPSR &= ~PPC_TXD2;
- PSDR &= ~PPC_TXD2;
- PPDR |= PPC_TXD2;
-
- /*
- * Enable HP-SIR modulation, and ensure that the port is disabled.
- */
- Ser2UTCR3 = 0;
- Ser2HSCR0 = HSCR0_UART;
- Ser2UTCR4 = si->utcr4;
- Ser2UTCR0 = UTCR0_8BitData;
- Ser2HSCR2 = HSCR2_TrDataH | HSCR2_RcDataL;
+ /* We need to ensure that the transmitter has finished. */
+ do
+ rmb();
+ while (Ser2UTSR1 & UTSR1_TBY);
/*
- * Clear status register
+ * Ok, we've finished transmitting. Now enable the receiver.
+ * Sometimes we get a receive IRQ immediately after a transmit...
*/
Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID;
+ Ser2UTCR3 = UTCR3_RIE | UTCR3_RXE | UTCR3_TXE;
- ret = sa1100_irda_set_speed(si, si->speed = 9600);
- if (ret) {
- Ser2UTCR3 = 0;
- Ser2HSCR0 = 0;
-
- if (si->pdata->shutdown)
- si->pdata->shutdown(si->dev);
- }
-
- return ret;
-}
-
-static void sa1100_irda_shutdown(struct sa1100_irda *si)
-{
- /*
- * Stop all DMA activity.
- */
- sa1100_stop_dma(si->rxdma);
- sa1100_stop_dma(si->txdma);
-
- /* Disable the port. */
- Ser2UTCR3 = 0;
- Ser2HSCR0 = 0;
+ sa1100_irda_check_speed(si);
- if (si->pdata->shutdown)
- si->pdata->shutdown(si->dev);
+ /* I'm hungry! */
+ netif_wake_queue(dev);
}
-#ifdef CONFIG_PM
-/*
- * Suspend the IrDA interface.
- */
-static int sa1100_irda_suspend(struct platform_device *pdev, pm_message_t state)
+static int sa1100_irda_sir_tx_start(struct sk_buff *skb, struct net_device *dev,
+ struct sa1100_irda *si)
{
- struct net_device *dev = platform_get_drvdata(pdev);
- struct sa1100_irda *si;
-
- if (!dev)
- return 0;
-
- si = netdev_priv(dev);
- if (si->open) {
- /*
- * Stop the transmit queue
- */
- netif_device_detach(dev);
- disable_irq(dev->irq);
- sa1100_irda_shutdown(si);
- __sa1100_irda_set_power(si, 0);
+ si->tx_buff.data = si->tx_buff.head;
+ si->tx_buff.len = async_wrap_skb(skb, si->tx_buff.data,
+ si->tx_buff.truesize);
+
+ si->dma_tx.skb = skb;
+ sg_set_buf(&si->dma_tx.sg, si->tx_buff.data, si->tx_buff.len);
+ if (dma_map_sg(si->dma_tx.dev, &si->dma_tx.sg, 1, DMA_TO_DEVICE) == 0) {
+ si->dma_tx.skb = NULL;
+ netif_wake_queue(dev);
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
}
- return 0;
-}
-
-/*
- * Resume the IrDA interface.
- */
-static int sa1100_irda_resume(struct platform_device *pdev)
-{
- struct net_device *dev = platform_get_drvdata(pdev);
- struct sa1100_irda *si;
-
- if (!dev)
- return 0;
+ sa1100_irda_dma_start(&si->dma_tx, DMA_MEM_TO_DEV, sa1100_irda_sirtxdma_irq, dev);
- si = netdev_priv(dev);
- if (si->open) {
- /*
- * If we missed a speed change, initialise at the new speed
- * directly. It is debatable whether this is actually
- * required, but in the interests of continuing from where
- * we left off it is desirable. The converse argument is
- * that we should re-negotiate at 9600 baud again.
- */
- if (si->newspeed) {
- si->speed = si->newspeed;
- si->newspeed = 0;
- }
-
- sa1100_irda_startup(si);
- __sa1100_irda_set_power(si, si->power);
- enable_irq(dev->irq);
-
- /*
- * This automatically wakes up the queue
- */
- netif_device_attach(dev);
- }
+ /*
+ * The mean turn-around time is enforced by XBOF padding,
+ * so we don't have to do anything special here.
+ */
+ Ser2UTCR3 = UTCR3_TXE;
- return 0;
+ return NETDEV_TX_OK;
}
-#else
-#define sa1100_irda_suspend NULL
-#define sa1100_irda_resume NULL
-#endif
-/*
- * HP-SIR format interrupt service routines.
- */
-static void sa1100_irda_hpsir_irq(struct net_device *dev)
+static irqreturn_t sa1100_irda_sir_irq(struct net_device *dev, struct sa1100_irda *si)
{
- struct sa1100_irda *si = netdev_priv(dev);
int status;
status = Ser2UTSR0;
@@ -414,51 +333,96 @@ static void sa1100_irda_hpsir_irq(struct net_device *dev)
}
- if (status & UTSR0_TFS && si->tx_buff.len) {
- /*
- * Transmitter FIFO is not full
- */
- do {
- Ser2UTDR = *si->tx_buff.data++;
- si->tx_buff.len -= 1;
- } while (Ser2UTSR1 & UTSR1_TNF && si->tx_buff.len);
+ return IRQ_HANDLED;
+}
- if (si->tx_buff.len == 0) {
- dev->stats.tx_packets++;
- dev->stats.tx_bytes += si->tx_buff.data -
- si->tx_buff.head;
+/*
+ * FIR format support.
+ */
+static void sa1100_irda_firtxdma_irq(void *id)
+{
+ struct net_device *dev = id;
+ struct sa1100_irda *si = netdev_priv(dev);
+ struct sk_buff *skb;
- /*
- * We need to ensure that the transmitter has
- * finished.
- */
- do
- rmb();
- while (Ser2UTSR1 & UTSR1_TBY);
+ /*
+ * Wait for the transmission to complete. Unfortunately,
+ * the hardware doesn't give us an interrupt to indicate
+ * "end of frame".
+ */
+ do
+ rmb();
+ while (!(Ser2HSSR0 & HSSR0_TUR) || Ser2HSSR1 & HSSR1_TBY);
- /*
- * Ok, we've finished transmitting. Now enable
- * the receiver. Sometimes we get a receive IRQ
- * immediately after a transmit...
- */
- Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID;
- Ser2UTCR3 = UTCR3_RIE | UTCR3_RXE | UTCR3_TXE;
+ /*
+ * Clear the transmit underrun bit.
+ */
+ Ser2HSSR0 = HSSR0_TUR;
- if (si->newspeed) {
- sa1100_irda_set_speed(si, si->newspeed);
- si->newspeed = 0;
- }
+ /*
+ * Do we need to change speed? Note that we're lazy
+ * here - we don't free the old dma_rx.skb. We don't need
+ * to allocate a buffer either.
+ */
+ sa1100_irda_check_speed(si);
- /* I'm hungry! */
- netif_wake_queue(dev);
- }
+ /*
+ * Start reception. This disables the transmitter for
+ * us. This will be using the existing RX buffer.
+ */
+ sa1100_irda_rx_dma_start(si);
+
+ /* Account and free the packet. */
+ skb = si->dma_tx.skb;
+ if (skb) {
+ dma_unmap_sg(si->dma_tx.dev, &si->dma_tx.sg, 1,
+ DMA_TO_DEVICE);
+ dev->stats.tx_packets ++;
+ dev->stats.tx_bytes += skb->len;
+ dev_kfree_skb_irq(skb);
+ si->dma_tx.skb = NULL;
}
+
+ /*
+ * Make sure that the TX queue is available for sending
+ * (for retries). TX has priority over RX at all times.
+ */
+ netif_wake_queue(dev);
+}
+
+static int sa1100_irda_fir_tx_start(struct sk_buff *skb, struct net_device *dev,
+ struct sa1100_irda *si)
+{
+ int mtt = irda_get_mtt(skb);
+
+ si->dma_tx.skb = skb;
+ sg_set_buf(&si->dma_tx.sg, skb->data, skb->len);
+ if (dma_map_sg(si->dma_tx.dev, &si->dma_tx.sg, 1, DMA_TO_DEVICE) == 0) {
+ si->dma_tx.skb = NULL;
+ netif_wake_queue(dev);
+ dev->stats.tx_dropped++;
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ sa1100_irda_dma_start(&si->dma_tx, DMA_MEM_TO_DEV, sa1100_irda_firtxdma_irq, dev);
+
+ /*
+ * If we have a mean turn-around time, impose the specified
+ * specified delay. We could shorten this by timing from
+ * the point we received the packet.
+ */
+ if (mtt)
+ udelay(mtt);
+
+ Ser2HSCR0 = HSCR0_HSSP | HSCR0_TXE;
+
+ return NETDEV_TX_OK;
}
static void sa1100_irda_fir_error(struct sa1100_irda *si, struct net_device *dev)
{
- struct sk_buff *skb = si->rxskb;
- dma_addr_t dma_addr;
+ struct sk_buff *skb = si->dma_rx.skb;
unsigned int len, stat, data;
if (!skb) {
@@ -469,11 +433,10 @@ static void sa1100_irda_fir_error(struct sa1100_irda *si, struct net_device *dev
/*
* Get the current data position.
*/
- dma_addr = sa1100_get_dma_pos(si->rxdma);
- len = dma_addr - si->rxbuf_dma;
+ len = sa1100_irda_dma_xferred(&si->dma_rx);
if (len > HPSIR_MAX_RXLEN)
len = HPSIR_MAX_RXLEN;
- dma_unmap_single(si->dev, si->rxbuf_dma, len, DMA_FROM_DEVICE);
+ dma_unmap_sg(si->dma_rx.dev, &si->dma_rx.sg, 1, DMA_FROM_DEVICE);
do {
/*
@@ -501,7 +464,7 @@ static void sa1100_irda_fir_error(struct sa1100_irda *si, struct net_device *dev
} while (Ser2HSSR0 & HSSR0_EIF);
if (stat & HSSR1_EOF) {
- si->rxskb = NULL;
+ si->dma_rx.skb = NULL;
skb_put(skb, len);
skb->dev = dev;
@@ -518,28 +481,23 @@ static void sa1100_irda_fir_error(struct sa1100_irda *si, struct net_device *dev
netif_rx(skb);
} else {
/*
- * Remap the buffer.
+ * Remap the buffer - it was previously mapped, and we
+ * hope that this succeeds.
*/
- si->rxbuf_dma = dma_map_single(si->dev, si->rxskb->data,
- HPSIR_MAX_RXLEN,
- DMA_FROM_DEVICE);
+ dma_map_sg(si->dma_rx.dev, &si->dma_rx.sg, 1, DMA_FROM_DEVICE);
}
}
/*
- * FIR format interrupt service routine. We only have to
- * handle RX events; transmit events go via the TX DMA handler.
- *
- * No matter what, we disable RX, process, and the restart RX.
+ * We only have to handle RX events here; transmit events go via the TX
+ * DMA handler. We disable RX, process, and the restart RX.
*/
-static void sa1100_irda_fir_irq(struct net_device *dev)
+static irqreturn_t sa1100_irda_fir_irq(struct net_device *dev, struct sa1100_irda *si)
{
- struct sa1100_irda *si = netdev_priv(dev);
-
/*
* Stop RX DMA
*/
- sa1100_stop_dma(si->rxdma);
+ dmaengine_pause(si->dma_rx.chan);
/*
* Framing error - we throw away the packet completely.
@@ -555,7 +513,7 @@ static void sa1100_irda_fir_irq(struct net_device *dev)
/*
* Clear out the DMA...
*/
- Ser2HSCR0 = si->hscr0 | HSCR0_HSSP;
+ Ser2HSCR0 = HSCR0_HSSP;
/*
* Clear selected status bits now, so we
@@ -577,74 +535,124 @@ static void sa1100_irda_fir_irq(struct net_device *dev)
* No matter what happens, we must restart reception.
*/
sa1100_irda_rx_dma_start(si);
-}
-static irqreturn_t sa1100_irda_irq(int irq, void *dev_id)
-{
- struct net_device *dev = dev_id;
- if (IS_FIR(((struct sa1100_irda *)netdev_priv(dev))))
- sa1100_irda_fir_irq(dev);
- else
- sa1100_irda_hpsir_irq(dev);
return IRQ_HANDLED;
}
/*
- * TX DMA completion handler.
+ * Set the IrDA communications speed.
*/
-static void sa1100_irda_txdma_irq(void *id)
+static int sa1100_irda_set_speed(struct sa1100_irda *si, int speed)
{
- struct net_device *dev = id;
- struct sa1100_irda *si = netdev_priv(dev);
- struct sk_buff *skb = si->txskb;
+ unsigned long flags;
+ int brd, ret = -EINVAL;
- si->txskb = NULL;
+ switch (speed) {
+ case 9600: case 19200: case 38400:
+ case 57600: case 115200:
+ brd = 3686400 / (16 * speed) - 1;
- /*
- * Wait for the transmission to complete. Unfortunately,
- * the hardware doesn't give us an interrupt to indicate
- * "end of frame".
- */
- do
- rmb();
- while (!(Ser2HSSR0 & HSSR0_TUR) || Ser2HSSR1 & HSSR1_TBY);
+ /* Stop the receive DMA, and configure transmit. */
+ if (IS_FIR(si)) {
+ dmaengine_terminate_all(si->dma_rx.chan);
+ dmaengine_slave_config(si->dma_tx.chan,
+ &sa1100_irda_sir_tx);
+ }
- /*
- * Clear the transmit underrun bit.
- */
- Ser2HSSR0 = HSSR0_TUR;
+ local_irq_save(flags);
- /*
- * Do we need to change speed? Note that we're lazy
- * here - we don't free the old rxskb. We don't need
- * to allocate a buffer either.
- */
- if (si->newspeed) {
- sa1100_irda_set_speed(si, si->newspeed);
- si->newspeed = 0;
- }
+ Ser2UTCR3 = 0;
+ Ser2HSCR0 = HSCR0_UART;
- /*
- * Start reception. This disables the transmitter for
- * us. This will be using the existing RX buffer.
- */
- sa1100_irda_rx_dma_start(si);
+ Ser2UTCR1 = brd >> 8;
+ Ser2UTCR2 = brd;
- /*
- * Account and free the packet.
- */
- if (skb) {
- dma_unmap_single(si->dev, si->txbuf_dma, skb->len, DMA_TO_DEVICE);
- dev->stats.tx_packets ++;
- dev->stats.tx_bytes += skb->len;
- dev_kfree_skb_irq(skb);
+ /*
+ * Clear status register
+ */
+ Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID;
+ Ser2UTCR3 = UTCR3_RIE | UTCR3_RXE | UTCR3_TXE;
+
+ if (si->pdata->set_speed)
+ si->pdata->set_speed(si->dev, speed);
+
+ si->speed = speed;
+ si->tx_start = sa1100_irda_sir_tx_start;
+ si->irq = sa1100_irda_sir_irq;
+
+ local_irq_restore(flags);
+ ret = 0;
+ break;
+
+ case 4000000:
+ if (!IS_FIR(si))
+ dmaengine_slave_config(si->dma_tx.chan,
+ &sa1100_irda_fir_tx);
+
+ local_irq_save(flags);
+
+ Ser2HSSR0 = 0xff;
+ Ser2HSCR0 = HSCR0_HSSP;
+ Ser2UTCR3 = 0;
+
+ si->speed = speed;
+ si->tx_start = sa1100_irda_fir_tx_start;
+ si->irq = sa1100_irda_fir_irq;
+
+ if (si->pdata->set_speed)
+ si->pdata->set_speed(si->dev, speed);
+
+ sa1100_irda_rx_alloc(si);
+ sa1100_irda_rx_dma_start(si);
+
+ local_irq_restore(flags);
+
+ break;
+
+ default:
+ break;
}
- /*
- * Make sure that the TX queue is available for sending
- * (for retries). TX has priority over RX at all times.
- */
- netif_wake_queue(dev);
+ return ret;
+}
+
+/*
+ * Control the power state of the IrDA transmitter.
+ * State:
+ * 0 - off
+ * 1 - short range, lowest power
+ * 2 - medium range, medium power
+ * 3 - maximum range, high power
+ *
+ * Currently, only assabet is known to support this.
+ */
+static int
+__sa1100_irda_set_power(struct sa1100_irda *si, unsigned int state)
+{
+ int ret = 0;
+ if (si->pdata->set_power)
+ ret = si->pdata->set_power(si->dev, state);
+ return ret;
+}
+
+static inline int
+sa1100_set_power(struct sa1100_irda *si, unsigned int state)
+{
+ int ret;
+
+ ret = __sa1100_irda_set_power(si, state);
+ if (ret == 0)
+ si->power = state;
+
+ return ret;
+}
+
+static irqreturn_t sa1100_irda_irq(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct sa1100_irda *si = netdev_priv(dev);
+
+ return si->irq(dev, si);
}
static int sa1100_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -660,62 +668,19 @@ static int sa1100_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
if (speed != si->speed && speed != -1)
si->newspeed = speed;
- /*
- * If this is an empty frame, we can bypass a lot.
- */
+ /* If this is an empty frame, we can bypass a lot. */
if (skb->len == 0) {
- if (si->newspeed) {
- si->newspeed = 0;
- sa1100_irda_set_speed(si, speed);
- }
+ sa1100_irda_check_speed(si);
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
- if (!IS_FIR(si)) {
- netif_stop_queue(dev);
-
- si->tx_buff.data = si->tx_buff.head;
- si->tx_buff.len = async_wrap_skb(skb, si->tx_buff.data,
- si->tx_buff.truesize);
-
- /*
- * Set the transmit interrupt enable. This will fire
- * off an interrupt immediately. Note that we disable
- * the receiver so we won't get spurious characteres
- * received.
- */
- Ser2UTCR3 = UTCR3_TIE | UTCR3_TXE;
-
- dev_kfree_skb(skb);
- } else {
- int mtt = irda_get_mtt(skb);
-
- /*
- * We must not be transmitting...
- */
- BUG_ON(si->txskb);
-
- netif_stop_queue(dev);
-
- si->txskb = skb;
- si->txbuf_dma = dma_map_single(si->dev, skb->data,
- skb->len, DMA_TO_DEVICE);
-
- sa1100_start_dma(si->txdma, si->txbuf_dma, skb->len);
-
- /*
- * If we have a mean turn-around time, impose the specified
- * specified delay. We could shorten this by timing from
- * the point we received the packet.
- */
- if (mtt)
- udelay(mtt);
+ netif_stop_queue(dev);
- Ser2HSCR0 = si->hscr0 | HSCR0_HSSP | HSCR0_TXE;
- }
+ /* We must not already have a skb to transmit... */
+ BUG_ON(si->dma_tx.skb);
- return NETDEV_TX_OK;
+ return si->tx_start(skb, dev, si);
}
static int
@@ -762,6 +727,69 @@ sa1100_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
return ret;
}
+static int sa1100_irda_startup(struct sa1100_irda *si)
+{
+ int ret;
+
+ /*
+ * Ensure that the ports for this device are setup correctly.
+ */
+ if (si->pdata->startup) {
+ ret = si->pdata->startup(si->dev);
+ if (ret)
+ return ret;
+ }
+
+ /*
+ * Configure PPC for IRDA - we want to drive TXD2 low.
+ * We also want to drive this pin low during sleep.
+ */
+ PPSR &= ~PPC_TXD2;
+ PSDR &= ~PPC_TXD2;
+ PPDR |= PPC_TXD2;
+
+ /*
+ * Enable HP-SIR modulation, and ensure that the port is disabled.
+ */
+ Ser2UTCR3 = 0;
+ Ser2HSCR0 = HSCR0_UART;
+ Ser2UTCR4 = si->utcr4;
+ Ser2UTCR0 = UTCR0_8BitData;
+ Ser2HSCR2 = HSCR2_TrDataH | HSCR2_RcDataL;
+
+ /*
+ * Clear status register
+ */
+ Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID;
+
+ ret = sa1100_irda_set_speed(si, si->speed = 9600);
+ if (ret) {
+ Ser2UTCR3 = 0;
+ Ser2HSCR0 = 0;
+
+ if (si->pdata->shutdown)
+ si->pdata->shutdown(si->dev);
+ }
+
+ return ret;
+}
+
+static void sa1100_irda_shutdown(struct sa1100_irda *si)
+{
+ /*
+ * Stop all DMA activity.
+ */
+ dmaengine_terminate_all(si->dma_rx.chan);
+ dmaengine_terminate_all(si->dma_tx.chan);
+
+ /* Disable the port. */
+ Ser2UTCR3 = 0;
+ Ser2HSCR0 = 0;
+
+ if (si->pdata->shutdown)
+ si->pdata->shutdown(si->dev);
+}
+
static int sa1100_irda_start(struct net_device *dev)
{
struct sa1100_irda *si = netdev_priv(dev);
@@ -769,26 +797,17 @@ static int sa1100_irda_start(struct net_device *dev)
si->speed = 9600;
- err = request_irq(dev->irq, sa1100_irda_irq, 0, dev->name, dev);
- if (err)
- goto err_irq;
-
- err = sa1100_request_dma(DMA_Ser2HSSPRd, "IrDA receive",
- NULL, NULL, &si->rxdma);
+ err = sa1100_irda_dma_request(si->dev, &si->dma_rx, "Ser2ICPRc",
+ &sa1100_irda_fir_rx);
if (err)
goto err_rx_dma;
- err = sa1100_request_dma(DMA_Ser2HSSPWr, "IrDA transmit",
- sa1100_irda_txdma_irq, dev, &si->txdma);
+ err = sa1100_irda_dma_request(si->dev, &si->dma_tx, "Ser2ICPTr",
+ &sa1100_irda_sir_tx);
if (err)
goto err_tx_dma;
/*
- * The interrupt must remain disabled for now.
- */
- disable_irq(dev->irq);
-
- /*
* Setup the serial port for the specified speed.
*/
err = sa1100_irda_startup(si);
@@ -803,44 +822,60 @@ static int sa1100_irda_start(struct net_device *dev)
if (!si->irlap)
goto err_irlap;
+ err = request_irq(dev->irq, sa1100_irda_irq, 0, dev->name, dev);
+ if (err)
+ goto err_irq;
+
/*
* Now enable the interrupt and start the queue
*/
si->open = 1;
sa1100_set_power(si, power_level); /* low power mode */
- enable_irq(dev->irq);
+
netif_start_queue(dev);
return 0;
+err_irq:
+ irlap_close(si->irlap);
err_irlap:
si->open = 0;
sa1100_irda_shutdown(si);
err_startup:
- sa1100_free_dma(si->txdma);
+ dma_release_channel(si->dma_tx.chan);
err_tx_dma:
- sa1100_free_dma(si->rxdma);
+ dma_release_channel(si->dma_rx.chan);
err_rx_dma:
- free_irq(dev->irq, dev);
-err_irq:
return err;
}
static int sa1100_irda_stop(struct net_device *dev)
{
struct sa1100_irda *si = netdev_priv(dev);
+ struct sk_buff *skb;
+
+ netif_stop_queue(dev);
- disable_irq(dev->irq);
+ si->open = 0;
sa1100_irda_shutdown(si);
/*
- * If we have been doing DMA receive, make sure we
+ * If we have been doing any DMA activity, make sure we
* tidy that up cleanly.
*/
- if (si->rxskb) {
- dma_unmap_single(si->dev, si->rxbuf_dma, HPSIR_MAX_RXLEN,
- DMA_FROM_DEVICE);
- dev_kfree_skb(si->rxskb);
- si->rxskb = NULL;
+ skb = si->dma_rx.skb;
+ if (skb) {
+ dma_unmap_sg(si->dma_rx.dev, &si->dma_rx.sg, 1,
+ DMA_FROM_DEVICE);
+ dev_kfree_skb(skb);
+ si->dma_rx.skb = NULL;
+ }
+
+ skb = si->dma_tx.skb;
+ if (skb) {
+ dma_unmap_sg(si->dma_tx.dev, &si->dma_tx.sg, 1,
+ DMA_TO_DEVICE);
+ dev_kfree_skb(skb);
+ si->dma_tx.skb = NULL;
}
/* Stop IrLAP */
@@ -849,14 +884,11 @@ static int sa1100_irda_stop(struct net_device *dev)
si->irlap = NULL;
}
- netif_stop_queue(dev);
- si->open = 0;
-
/*
* Free resources
*/
- sa1100_free_dma(si->txdma);
- sa1100_free_dma(si->rxdma);
+ dma_release_channel(si->dma_tx.chan);
+ dma_release_channel(si->dma_rx.chan);
free_irq(dev->irq, dev);
sa1100_set_power(si, 0);
@@ -888,11 +920,15 @@ static int sa1100_irda_probe(struct platform_device *pdev)
struct net_device *dev;
struct sa1100_irda *si;
unsigned int baudrate_mask;
- int err;
+ int err, irq;
if (!pdev->dev.platform_data)
return -EINVAL;
+ irq = platform_get_irq(pdev, 0);
+ if (irq <= 0)
+ return irq < 0 ? irq : -ENXIO;
+
err = request_mem_region(__PREG(Ser2UTCR0), 0x24, "IrDA") ? 0 : -EBUSY;
if (err)
goto err_mem_1;
@@ -907,22 +943,27 @@ static int sa1100_irda_probe(struct platform_device *pdev)
if (!dev)
goto err_mem_4;
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
si = netdev_priv(dev);
si->dev = &pdev->dev;
si->pdata = pdev->dev.platform_data;
+ sg_init_table(&si->dma_rx.sg, 1);
+ sg_init_table(&si->dma_tx.sg, 1);
+
/*
* Initialise the HP-SIR buffers
*/
err = sa1100_irda_init_iobuf(&si->rx_buff, 14384);
if (err)
goto err_mem_5;
- err = sa1100_irda_init_iobuf(&si->tx_buff, 4000);
+ err = sa1100_irda_init_iobuf(&si->tx_buff, IRDA_SIR_MAX_FRAME);
if (err)
goto err_mem_5;
dev->netdev_ops = &sa1100_irda_netdev_ops;
- dev->irq = IRQ_Ser2ICP;
+ dev->irq = irq;
irda_init_max_qos_capabilies(&si->qos);
@@ -996,6 +1037,74 @@ static int sa1100_irda_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM
+/*
+ * Suspend the IrDA interface.
+ */
+static int sa1100_irda_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct sa1100_irda *si;
+
+ if (!dev)
+ return 0;
+
+ si = netdev_priv(dev);
+ if (si->open) {
+ /*
+ * Stop the transmit queue
+ */
+ netif_device_detach(dev);
+ disable_irq(dev->irq);
+ sa1100_irda_shutdown(si);
+ __sa1100_irda_set_power(si, 0);
+ }
+
+ return 0;
+}
+
+/*
+ * Resume the IrDA interface.
+ */
+static int sa1100_irda_resume(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct sa1100_irda *si;
+
+ if (!dev)
+ return 0;
+
+ si = netdev_priv(dev);
+ if (si->open) {
+ /*
+ * If we missed a speed change, initialise at the new speed
+ * directly. It is debatable whether this is actually
+ * required, but in the interests of continuing from where
+ * we left off it is desirable. The converse argument is
+ * that we should re-negotiate at 9600 baud again.
+ */
+ if (si->newspeed) {
+ si->speed = si->newspeed;
+ si->newspeed = 0;
+ }
+
+ sa1100_irda_startup(si);
+ __sa1100_irda_set_power(si, si->power);
+ enable_irq(dev->irq);
+
+ /*
+ * This automatically wakes up the queue
+ */
+ netif_device_attach(dev);
+ }
+
+ return 0;
+}
+#else
+#define sa1100_irda_suspend NULL
+#define sa1100_irda_resume NULL
+#endif
+
static struct platform_driver sa1100ir_driver = {
.probe = sa1100_irda_probe,
.remove = sa1100_irda_remove,
diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c
index 790cbdea7392..3886b30ed373 100644
--- a/drivers/net/usb/cdc-phonet.c
+++ b/drivers/net/usb/cdc-phonet.c
@@ -164,12 +164,14 @@ static void rx_complete(struct urb *req)
/* Can't use pskb_pull() on page in IRQ */
memcpy(skb_put(skb, 1), page_address(page), 1);
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
- page, 1, req->actual_length);
+ page, 1, req->actual_length,
+ req->actual_length);
page = NULL;
}
} else {
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
- page, 0, req->actual_length);
+ page, 0, req->actual_length,
+ req->actual_length);
page = NULL;
}
if (req->actual_length < PAGE_SIZE)
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index aac68f5195c0..552d24bf862e 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -409,6 +409,42 @@ static const struct usb_device_id products[] = {
.bInterfaceProtocol = 0xff,
.driver_info = (unsigned long)&qmi_wwan_force_int4,
},
+ { /* ZTE (Vodafone) K3565-Z */
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x19d2,
+ .idProduct = 0x0063,
+ .bInterfaceClass = 0xff,
+ .bInterfaceSubClass = 0xff,
+ .bInterfaceProtocol = 0xff,
+ .driver_info = (unsigned long)&qmi_wwan_force_int4,
+ },
+ { /* ZTE (Vodafone) K3570-Z */
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x19d2,
+ .idProduct = 0x1008,
+ .bInterfaceClass = 0xff,
+ .bInterfaceSubClass = 0xff,
+ .bInterfaceProtocol = 0xff,
+ .driver_info = (unsigned long)&qmi_wwan_force_int4,
+ },
+ { /* ZTE (Vodafone) K3571-Z */
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x19d2,
+ .idProduct = 0x1010,
+ .bInterfaceClass = 0xff,
+ .bInterfaceSubClass = 0xff,
+ .bInterfaceProtocol = 0xff,
+ .driver_info = (unsigned long)&qmi_wwan_force_int4,
+ },
+ { /* ZTE (Vodafone) K4505-Z */
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x19d2,
+ .idProduct = 0x0104,
+ .bInterfaceClass = 0xff,
+ .bInterfaceSubClass = 0xff,
+ .bInterfaceProtocol = 0xff,
+ .driver_info = (unsigned long)&qmi_wwan_force_int4,
+ },
{QMI_GOBI_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
{QMI_GOBI_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */
{QMI_GOBI_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 4b8b52ca09d8..b7b3f5b0d406 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -493,6 +493,7 @@ block:
if (netif_running (dev->net) &&
!test_bit (EVENT_RX_HALT, &dev->flags)) {
rx_submit (dev, urb, GFP_ATOMIC);
+ usb_mark_last_busy(dev->udev);
return;
}
usb_free_urb (urb);
@@ -589,6 +590,14 @@ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
entry = (struct skb_data *) skb->cb;
urb = entry->urb;
+ /*
+ * Get reference count of the URB to avoid it to be
+ * freed during usb_unlink_urb, which may trigger
+ * use-after-free problem inside usb_unlink_urb since
+ * usb_unlink_urb is always racing with .complete
+ * handler(include defer_bh).
+ */
+ usb_get_urb(urb);
spin_unlock_irqrestore(&q->lock, flags);
// during some PM-driven resume scenarios,
// these (async) unlinks complete immediately
@@ -597,6 +606,7 @@ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
netdev_dbg(dev->net, "unlink urb err, %d\n", retval);
else
count++;
+ usb_put_urb(urb);
spin_lock_irqsave(&q->lock, flags);
}
spin_unlock_irqrestore (&q->lock, flags);
@@ -1028,7 +1038,6 @@ static void tx_complete (struct urb *urb)
}
usb_autopm_put_interface_async(dev->intf);
- urb->dev = NULL;
entry->state = tx_done;
defer_bh(dev, skb, &dev->txq);
}
diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c
index c5b1d199e0bc..b25c01be0d90 100644
--- a/drivers/net/wireless/iwlegacy/3945.c
+++ b/drivers/net/wireless/iwlegacy/3945.c
@@ -499,7 +499,8 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
le32_to_cpu(rx_end->status), stats);
skb_add_rx_frag(skb, 0, rxb->page,
- (void *)rx_hdr->payload - (void *)pkt, len);
+ (void *)rx_hdr->payload - (void *)pkt, len,
+ len);
il_update_stats(il, false, fc, len);
memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index 7b54dbb338be..17f1c6853182 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -596,7 +596,8 @@ il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr,
return;
}
- skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
+ skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len,
+ len);
il_update_stats(il, false, fc, len);
memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
index 44c6f712b77d..f4b84d1596e3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
@@ -796,7 +796,7 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
offset = (void *)hdr - rxb_addr(rxb);
p = rxb_steal_page(rxb);
- skb_add_rx_frag(skb, 0, p, offset, len);
+ skb_add_rx_frag(skb, 0, p, offset, len, len);
iwl_update_stats(priv, false, fc, len);
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index b16175032327..663b32c2e931 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -47,6 +47,7 @@
#include <xen/xenbus.h>
#include <xen/events.h>
#include <xen/page.h>
+#include <xen/platform_pci.h>
#include <xen/grant_table.h>
#include <xen/interface/io/netif.h>
@@ -1964,6 +1965,9 @@ static int __init netif_init(void)
if (xen_initial_domain())
return 0;
+ if (!xen_platform_pci_unplug)
+ return -ENODEV;
+
printk(KERN_INFO "Initialising Xen virtual ethernet driver.\n");
return xenbus_register_frontend(&netfront_driver);