forked from Minki/linux
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (94 commits) pkt_sched: Prevent livelock in TX queue running. Revert "pkt_sched: Add BH protection for qdisc_stab_lock." Revert "pkt_sched: Protect gen estimators under est_lock." pkt_sched: remove bogus block (cleanup) nf_nat: use secure_ipv4_port_ephemeral() for NAT port randomization netfilter: ctnetlink: sleepable allocation with spin lock bh netfilter: ctnetlink: fix sleep in read-side lock section netfilter: ctnetlink: fix double helper assignation for NAT'ed conntracks netfilter: ipt_addrtype: Fix matching of inverted destination address type dccp: Fix panic caused by too early termination of retransmission mechanism pkt_sched: Don't hold qdisc lock over qdisc_destroy(). pkt_sched: Add lockdep annotation for qdisc locks pkt_sched: Never schedule non-root qdiscs. removed unused #include <version.h> rt2x00: Fix txdone_entry_desc_flags b43: Fix for another Bluetooth Coexistence SPROM Programming error for BCM4306 mac80211: remove kdoc references to IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE p54u: reset skb's data/tail pointer on requeue p54: move p54_vdcf_init to the right place. iwlwifi: fix printk newlines ...
This commit is contained in:
commit
4309e09242
@ -363,6 +363,11 @@ This rule exists because users of the rfkill subsystem expect to get (and set,
|
||||
when possible) the overall transmitter rfkill state, not of a particular rfkill
|
||||
line.
|
||||
|
||||
5. During suspend, the rfkill class will attempt to soft-block the radio
|
||||
through a call to rfkill->toggle_radio, and will try to restore its previous
|
||||
state during resume. After a rfkill class is suspended, it will *not* call
|
||||
rfkill->toggle_radio until it is resumed.
|
||||
|
||||
Example of a WLAN wireless driver connected to the rfkill subsystem:
|
||||
--------------------------------------------------------------------
|
||||
|
||||
|
91
MAINTAINERS
91
MAINTAINERS
@ -942,96 +942,21 @@ M: joern@lazybastard.org
|
||||
L: linux-mtd@lists.infradead.org
|
||||
S: Maintained
|
||||
|
||||
BLUETOOTH DRIVERS
|
||||
P: Marcel Holtmann
|
||||
M: marcel@holtmann.org
|
||||
L: linux-bluetooth@vger.kernel.org
|
||||
W: http://www.bluez.org/
|
||||
S: Maintained
|
||||
|
||||
BLUETOOTH SUBSYSTEM
|
||||
P: Marcel Holtmann
|
||||
M: marcel@holtmann.org
|
||||
P: Maxim Krasnyansky
|
||||
M: maxk@qualcomm.com
|
||||
L: linux-bluetooth@vger.kernel.org
|
||||
W: http://bluez.sf.net
|
||||
W: http://www.bluez.org
|
||||
W: http://www.holtmann.org/linux/bluetooth/
|
||||
W: http://www.bluez.org/
|
||||
T: git kernel.org:/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6.git
|
||||
S: Maintained
|
||||
|
||||
BLUETOOTH RFCOMM LAYER
|
||||
P: Marcel Holtmann
|
||||
M: marcel@holtmann.org
|
||||
P: Maxim Krasnyansky
|
||||
M: maxk@qualcomm.com
|
||||
S: Maintained
|
||||
|
||||
BLUETOOTH BNEP LAYER
|
||||
P: Marcel Holtmann
|
||||
M: marcel@holtmann.org
|
||||
P: Maxim Krasnyansky
|
||||
M: maxk@qualcomm.com
|
||||
S: Maintained
|
||||
|
||||
BLUETOOTH CMTP LAYER
|
||||
P: Marcel Holtmann
|
||||
M: marcel@holtmann.org
|
||||
S: Maintained
|
||||
|
||||
BLUETOOTH HIDP LAYER
|
||||
P: Marcel Holtmann
|
||||
M: marcel@holtmann.org
|
||||
S: Maintained
|
||||
|
||||
BLUETOOTH HCI UART DRIVER
|
||||
P: Marcel Holtmann
|
||||
M: marcel@holtmann.org
|
||||
P: Maxim Krasnyansky
|
||||
M: maxk@qualcomm.com
|
||||
S: Maintained
|
||||
|
||||
BLUETOOTH HCI USB DRIVER
|
||||
P: Marcel Holtmann
|
||||
M: marcel@holtmann.org
|
||||
P: Maxim Krasnyansky
|
||||
M: maxk@qualcomm.com
|
||||
S: Maintained
|
||||
|
||||
BLUETOOTH HCI BCM203X DRIVER
|
||||
P: Marcel Holtmann
|
||||
M: marcel@holtmann.org
|
||||
S: Maintained
|
||||
|
||||
BLUETOOTH HCI BPA10X DRIVER
|
||||
P: Marcel Holtmann
|
||||
M: marcel@holtmann.org
|
||||
S: Maintained
|
||||
|
||||
BLUETOOTH HCI BFUSB DRIVER
|
||||
P: Marcel Holtmann
|
||||
M: marcel@holtmann.org
|
||||
S: Maintained
|
||||
|
||||
BLUETOOTH HCI DTL1 DRIVER
|
||||
P: Marcel Holtmann
|
||||
M: marcel@holtmann.org
|
||||
S: Maintained
|
||||
|
||||
BLUETOOTH HCI BLUECARD DRIVER
|
||||
P: Marcel Holtmann
|
||||
M: marcel@holtmann.org
|
||||
S: Maintained
|
||||
|
||||
BLUETOOTH HCI BT3C DRIVER
|
||||
P: Marcel Holtmann
|
||||
M: marcel@holtmann.org
|
||||
S: Maintained
|
||||
|
||||
BLUETOOTH HCI BTUART DRIVER
|
||||
P: Marcel Holtmann
|
||||
M: marcel@holtmann.org
|
||||
S: Maintained
|
||||
|
||||
BLUETOOTH HCI VHCI DRIVER
|
||||
P: Maxim Krasnyansky
|
||||
M: maxk@qualcomm.com
|
||||
S: Maintained
|
||||
|
||||
BONDING DRIVER
|
||||
P: Jay Vosburgh
|
||||
M: fubar@us.ibm.com
|
||||
|
@ -3,8 +3,8 @@ menu "Bluetooth device drivers"
|
||||
depends on BT
|
||||
|
||||
config BT_HCIUSB
|
||||
tristate "HCI USB driver"
|
||||
depends on USB
|
||||
tristate "HCI USB driver (old version)"
|
||||
depends on USB && BT_HCIBTUSB=n
|
||||
help
|
||||
Bluetooth HCI USB driver.
|
||||
This driver is required if you want to use Bluetooth devices with
|
||||
@ -23,15 +23,13 @@ config BT_HCIUSB_SCO
|
||||
Say Y here to compile support for SCO over HCI USB.
|
||||
|
||||
config BT_HCIBTUSB
|
||||
tristate "HCI USB driver (alternate version)"
|
||||
depends on USB && EXPERIMENTAL && BT_HCIUSB=n
|
||||
tristate "HCI USB driver"
|
||||
depends on USB
|
||||
help
|
||||
Bluetooth HCI USB driver.
|
||||
This driver is required if you want to use Bluetooth devices with
|
||||
USB interface.
|
||||
|
||||
This driver is still experimental and has no SCO support.
|
||||
|
||||
Say Y here to compile support for Bluetooth USB devices into the
|
||||
kernel or say M to compile it as module (btusb).
|
||||
|
||||
|
@ -60,7 +60,7 @@
|
||||
/* ======================== Module parameters ======================== */
|
||||
|
||||
|
||||
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>, Jose Orlando Pereira <jop@di.uminho.pt>");
|
||||
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
||||
MODULE_DESCRIPTION("Bluetooth driver for the 3Com Bluetooth PCMCIA card");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_FIRMWARE("BT3CPCC.bin");
|
||||
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* Generic Bluetooth USB driver
|
||||
*
|
||||
* Copyright (C) 2005-2007 Marcel Holtmann <marcel@holtmann.org>
|
||||
* Copyright (C) 2005-2008 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@ -41,7 +41,7 @@
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
#define VERSION "0.2"
|
||||
#define VERSION "0.3"
|
||||
|
||||
static int ignore_dga;
|
||||
static int ignore_csr;
|
||||
@ -160,12 +160,16 @@ static struct usb_device_id blacklist_table[] = {
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
#define BTUSB_MAX_ISOC_FRAMES 10
|
||||
|
||||
#define BTUSB_INTR_RUNNING 0
|
||||
#define BTUSB_BULK_RUNNING 1
|
||||
#define BTUSB_ISOC_RUNNING 2
|
||||
|
||||
struct btusb_data {
|
||||
struct hci_dev *hdev;
|
||||
struct usb_device *udev;
|
||||
struct usb_interface *isoc;
|
||||
|
||||
spinlock_t lock;
|
||||
|
||||
@ -176,10 +180,15 @@ struct btusb_data {
|
||||
struct usb_anchor tx_anchor;
|
||||
struct usb_anchor intr_anchor;
|
||||
struct usb_anchor bulk_anchor;
|
||||
struct usb_anchor isoc_anchor;
|
||||
|
||||
struct usb_endpoint_descriptor *intr_ep;
|
||||
struct usb_endpoint_descriptor *bulk_tx_ep;
|
||||
struct usb_endpoint_descriptor *bulk_rx_ep;
|
||||
struct usb_endpoint_descriptor *isoc_tx_ep;
|
||||
struct usb_endpoint_descriptor *isoc_rx_ep;
|
||||
|
||||
int isoc_altsetting;
|
||||
};
|
||||
|
||||
static void btusb_intr_complete(struct urb *urb)
|
||||
@ -195,6 +204,8 @@ static void btusb_intr_complete(struct urb *urb)
|
||||
return;
|
||||
|
||||
if (urb->status == 0) {
|
||||
hdev->stat.byte_rx += urb->actual_length;
|
||||
|
||||
if (hci_recv_fragment(hdev, HCI_EVENT_PKT,
|
||||
urb->transfer_buffer,
|
||||
urb->actual_length) < 0) {
|
||||
@ -216,7 +227,7 @@ static void btusb_intr_complete(struct urb *urb)
|
||||
}
|
||||
}
|
||||
|
||||
static inline int btusb_submit_intr_urb(struct hci_dev *hdev)
|
||||
static int btusb_submit_intr_urb(struct hci_dev *hdev)
|
||||
{
|
||||
struct btusb_data *data = hdev->driver_data;
|
||||
struct urb *urb;
|
||||
@ -226,6 +237,9 @@ static inline int btusb_submit_intr_urb(struct hci_dev *hdev)
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
if (!data->intr_ep)
|
||||
return -ENODEV;
|
||||
|
||||
urb = usb_alloc_urb(0, GFP_ATOMIC);
|
||||
if (!urb)
|
||||
return -ENOMEM;
|
||||
@ -274,6 +288,8 @@ static void btusb_bulk_complete(struct urb *urb)
|
||||
return;
|
||||
|
||||
if (urb->status == 0) {
|
||||
hdev->stat.byte_rx += urb->actual_length;
|
||||
|
||||
if (hci_recv_fragment(hdev, HCI_ACLDATA_PKT,
|
||||
urb->transfer_buffer,
|
||||
urb->actual_length) < 0) {
|
||||
@ -295,7 +311,7 @@ static void btusb_bulk_complete(struct urb *urb)
|
||||
}
|
||||
}
|
||||
|
||||
static inline int btusb_submit_bulk_urb(struct hci_dev *hdev)
|
||||
static int btusb_submit_bulk_urb(struct hci_dev *hdev)
|
||||
{
|
||||
struct btusb_data *data = hdev->driver_data;
|
||||
struct urb *urb;
|
||||
@ -305,6 +321,9 @@ static inline int btusb_submit_bulk_urb(struct hci_dev *hdev)
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
if (!data->bulk_rx_ep)
|
||||
return -ENODEV;
|
||||
|
||||
urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!urb)
|
||||
return -ENOMEM;
|
||||
@ -339,6 +358,127 @@ static inline int btusb_submit_bulk_urb(struct hci_dev *hdev)
|
||||
return err;
|
||||
}
|
||||
|
||||
static void btusb_isoc_complete(struct urb *urb)
|
||||
{
|
||||
struct hci_dev *hdev = urb->context;
|
||||
struct btusb_data *data = hdev->driver_data;
|
||||
int i, err;
|
||||
|
||||
BT_DBG("%s urb %p status %d count %d", hdev->name,
|
||||
urb, urb->status, urb->actual_length);
|
||||
|
||||
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
||||
return;
|
||||
|
||||
if (urb->status == 0) {
|
||||
for (i = 0; i < urb->number_of_packets; i++) {
|
||||
unsigned int offset = urb->iso_frame_desc[i].offset;
|
||||
unsigned int length = urb->iso_frame_desc[i].actual_length;
|
||||
|
||||
if (urb->iso_frame_desc[i].status)
|
||||
continue;
|
||||
|
||||
hdev->stat.byte_rx += length;
|
||||
|
||||
if (hci_recv_fragment(hdev, HCI_SCODATA_PKT,
|
||||
urb->transfer_buffer + offset,
|
||||
length) < 0) {
|
||||
BT_ERR("%s corrupted SCO packet", hdev->name);
|
||||
hdev->stat.err_rx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!test_bit(BTUSB_ISOC_RUNNING, &data->flags))
|
||||
return;
|
||||
|
||||
usb_anchor_urb(urb, &data->isoc_anchor);
|
||||
|
||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (err < 0) {
|
||||
BT_ERR("%s urb %p failed to resubmit (%d)",
|
||||
hdev->name, urb, -err);
|
||||
usb_unanchor_urb(urb);
|
||||
}
|
||||
}
|
||||
|
||||
static void inline __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
|
||||
{
|
||||
int i, offset = 0;
|
||||
|
||||
BT_DBG("len %d mtu %d", len, mtu);
|
||||
|
||||
for (i = 0; i < BTUSB_MAX_ISOC_FRAMES && len >= mtu;
|
||||
i++, offset += mtu, len -= mtu) {
|
||||
urb->iso_frame_desc[i].offset = offset;
|
||||
urb->iso_frame_desc[i].length = mtu;
|
||||
}
|
||||
|
||||
if (len && i < BTUSB_MAX_ISOC_FRAMES) {
|
||||
urb->iso_frame_desc[i].offset = offset;
|
||||
urb->iso_frame_desc[i].length = len;
|
||||
i++;
|
||||
}
|
||||
|
||||
urb->number_of_packets = i;
|
||||
}
|
||||
|
||||
static int btusb_submit_isoc_urb(struct hci_dev *hdev)
|
||||
{
|
||||
struct btusb_data *data = hdev->driver_data;
|
||||
struct urb *urb;
|
||||
unsigned char *buf;
|
||||
unsigned int pipe;
|
||||
int err, size;
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
if (!data->isoc_rx_ep)
|
||||
return -ENODEV;
|
||||
|
||||
urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_KERNEL);
|
||||
if (!urb)
|
||||
return -ENOMEM;
|
||||
|
||||
size = le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize) *
|
||||
BTUSB_MAX_ISOC_FRAMES;
|
||||
|
||||
buf = kmalloc(size, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
usb_free_urb(urb);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pipe = usb_rcvisocpipe(data->udev, data->isoc_rx_ep->bEndpointAddress);
|
||||
|
||||
urb->dev = data->udev;
|
||||
urb->pipe = pipe;
|
||||
urb->context = hdev;
|
||||
urb->complete = btusb_isoc_complete;
|
||||
urb->interval = data->isoc_rx_ep->bInterval;
|
||||
|
||||
urb->transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP;
|
||||
urb->transfer_buffer = buf;
|
||||
urb->transfer_buffer_length = size;
|
||||
|
||||
__fill_isoc_descriptor(urb, size,
|
||||
le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize));
|
||||
|
||||
usb_anchor_urb(urb, &data->isoc_anchor);
|
||||
|
||||
err = usb_submit_urb(urb, GFP_KERNEL);
|
||||
if (err < 0) {
|
||||
BT_ERR("%s urb %p submission failed (%d)",
|
||||
hdev->name, urb, -err);
|
||||
usb_unanchor_urb(urb);
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
usb_free_urb(urb);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void btusb_tx_complete(struct urb *urb)
|
||||
{
|
||||
struct sk_buff *skb = urb->context;
|
||||
@ -392,6 +532,9 @@ static int btusb_close(struct hci_dev *hdev)
|
||||
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
|
||||
return 0;
|
||||
|
||||
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
|
||||
usb_kill_anchored_urbs(&data->intr_anchor);
|
||||
|
||||
clear_bit(BTUSB_BULK_RUNNING, &data->flags);
|
||||
usb_kill_anchored_urbs(&data->bulk_anchor);
|
||||
|
||||
@ -453,6 +596,9 @@ static int btusb_send_frame(struct sk_buff *skb)
|
||||
break;
|
||||
|
||||
case HCI_ACLDATA_PKT:
|
||||
if (!data->bulk_tx_ep || hdev->conn_hash.acl_num < 1)
|
||||
return -ENODEV;
|
||||
|
||||
urb = usb_alloc_urb(0, GFP_ATOMIC);
|
||||
if (!urb)
|
||||
return -ENOMEM;
|
||||
@ -467,9 +613,31 @@ static int btusb_send_frame(struct sk_buff *skb)
|
||||
break;
|
||||
|
||||
case HCI_SCODATA_PKT:
|
||||
if (!data->isoc_tx_ep || hdev->conn_hash.sco_num < 1)
|
||||
return -ENODEV;
|
||||
|
||||
urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_ATOMIC);
|
||||
if (!urb)
|
||||
return -ENOMEM;
|
||||
|
||||
pipe = usb_sndisocpipe(data->udev,
|
||||
data->isoc_tx_ep->bEndpointAddress);
|
||||
|
||||
urb->dev = data->udev;
|
||||
urb->pipe = pipe;
|
||||
urb->context = skb;
|
||||
urb->complete = btusb_tx_complete;
|
||||
urb->interval = data->isoc_tx_ep->bInterval;
|
||||
|
||||
urb->transfer_flags = URB_ISO_ASAP;
|
||||
urb->transfer_buffer = skb->data;
|
||||
urb->transfer_buffer_length = skb->len;
|
||||
|
||||
__fill_isoc_descriptor(urb, skb->len,
|
||||
le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
|
||||
|
||||
hdev->stat.sco_tx++;
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EILSEQ;
|
||||
@ -508,22 +676,86 @@ static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
|
||||
schedule_work(&data->work);
|
||||
}
|
||||
|
||||
static int inline __set_isoc_interface(struct hci_dev *hdev, int altsetting)
|
||||
{
|
||||
struct btusb_data *data = hdev->driver_data;
|
||||
struct usb_interface *intf = data->isoc;
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int i, err;
|
||||
|
||||
if (!data->isoc)
|
||||
return -ENODEV;
|
||||
|
||||
err = usb_set_interface(data->udev, 1, altsetting);
|
||||
if (err < 0) {
|
||||
BT_ERR("%s setting interface failed (%d)", hdev->name, -err);
|
||||
return err;
|
||||
}
|
||||
|
||||
data->isoc_altsetting = altsetting;
|
||||
|
||||
data->isoc_tx_ep = NULL;
|
||||
data->isoc_rx_ep = NULL;
|
||||
|
||||
for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
|
||||
ep_desc = &intf->cur_altsetting->endpoint[i].desc;
|
||||
|
||||
if (!data->isoc_tx_ep && usb_endpoint_is_isoc_out(ep_desc)) {
|
||||
data->isoc_tx_ep = ep_desc;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!data->isoc_rx_ep && usb_endpoint_is_isoc_in(ep_desc)) {
|
||||
data->isoc_rx_ep = ep_desc;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!data->isoc_tx_ep || !data->isoc_rx_ep) {
|
||||
BT_ERR("%s invalid SCO descriptors", hdev->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void btusb_work(struct work_struct *work)
|
||||
{
|
||||
struct btusb_data *data = container_of(work, struct btusb_data, work);
|
||||
struct hci_dev *hdev = data->hdev;
|
||||
|
||||
if (hdev->conn_hash.acl_num == 0) {
|
||||
if (hdev->conn_hash.acl_num > 0) {
|
||||
if (!test_and_set_bit(BTUSB_BULK_RUNNING, &data->flags)) {
|
||||
if (btusb_submit_bulk_urb(hdev) < 0)
|
||||
clear_bit(BTUSB_BULK_RUNNING, &data->flags);
|
||||
else
|
||||
btusb_submit_bulk_urb(hdev);
|
||||
}
|
||||
} else {
|
||||
clear_bit(BTUSB_BULK_RUNNING, &data->flags);
|
||||
usb_kill_anchored_urbs(&data->bulk_anchor);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!test_and_set_bit(BTUSB_BULK_RUNNING, &data->flags)) {
|
||||
if (btusb_submit_bulk_urb(hdev) < 0)
|
||||
clear_bit(BTUSB_BULK_RUNNING, &data->flags);
|
||||
else
|
||||
btusb_submit_bulk_urb(hdev);
|
||||
if (hdev->conn_hash.sco_num > 0) {
|
||||
if (data->isoc_altsetting != 2) {
|
||||
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
|
||||
usb_kill_anchored_urbs(&data->isoc_anchor);
|
||||
|
||||
if (__set_isoc_interface(hdev, 2) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
|
||||
if (btusb_submit_isoc_urb(hdev) < 0)
|
||||
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
|
||||
else
|
||||
btusb_submit_isoc_urb(hdev);
|
||||
}
|
||||
} else {
|
||||
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
|
||||
usb_kill_anchored_urbs(&data->isoc_anchor);
|
||||
|
||||
__set_isoc_interface(hdev, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -597,6 +829,7 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
init_usb_anchor(&data->tx_anchor);
|
||||
init_usb_anchor(&data->intr_anchor);
|
||||
init_usb_anchor(&data->bulk_anchor);
|
||||
init_usb_anchor(&data->isoc_anchor);
|
||||
|
||||
hdev = hci_alloc_dev();
|
||||
if (!hdev) {
|
||||
@ -620,6 +853,9 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
|
||||
hdev->owner = THIS_MODULE;
|
||||
|
||||
/* interface numbers are hardcoded in the spec */
|
||||
data->isoc = usb_ifnum_to_if(data->udev, 1);
|
||||
|
||||
if (reset || id->driver_info & BTUSB_RESET)
|
||||
set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks);
|
||||
|
||||
@ -628,11 +864,16 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks);
|
||||
}
|
||||
|
||||
if (id->driver_info & BTUSB_BROKEN_ISOC)
|
||||
data->isoc = NULL;
|
||||
|
||||
if (id->driver_info & BTUSB_SNIFFER) {
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
struct usb_device *udev = data->udev;
|
||||
|
||||
if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997)
|
||||
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
|
||||
|
||||
data->isoc = NULL;
|
||||
}
|
||||
|
||||
if (id->driver_info & BTUSB_BCM92035) {
|
||||
@ -646,6 +887,16 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
}
|
||||
}
|
||||
|
||||
if (data->isoc) {
|
||||
err = usb_driver_claim_interface(&btusb_driver,
|
||||
data->isoc, NULL);
|
||||
if (err < 0) {
|
||||
hci_free_dev(hdev);
|
||||
kfree(data);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
err = hci_register_dev(hdev);
|
||||
if (err < 0) {
|
||||
hci_free_dev(hdev);
|
||||
@ -670,6 +921,9 @@ static void btusb_disconnect(struct usb_interface *intf)
|
||||
|
||||
hdev = data->hdev;
|
||||
|
||||
if (data->isoc)
|
||||
usb_driver_release_interface(&btusb_driver, data->isoc);
|
||||
|
||||
usb_set_intfdata(intf, NULL);
|
||||
|
||||
hci_unregister_dev(hdev);
|
||||
|
@ -577,7 +577,7 @@ module_exit(hci_uart_exit);
|
||||
module_param(reset, bool, 0644);
|
||||
MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
|
||||
|
||||
MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
|
||||
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
||||
MODULE_DESCRIPTION("Bluetooth HCI UART driver ver " VERSION);
|
||||
MODULE_VERSION(VERSION);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -1130,7 +1130,7 @@ module_param(isoc, int, 0644);
|
||||
MODULE_PARM_DESC(isoc, "Set isochronous transfers for SCO over HCI support");
|
||||
#endif
|
||||
|
||||
MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
|
||||
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
||||
MODULE_DESCRIPTION("Bluetooth HCI USB driver ver " VERSION);
|
||||
MODULE_VERSION(VERSION);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -377,7 +377,7 @@ module_exit(vhci_exit);
|
||||
module_param(minor, int, 0444);
|
||||
MODULE_PARM_DESC(minor, "Miscellaneous minor device number");
|
||||
|
||||
MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
|
||||
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
||||
MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION);
|
||||
MODULE_VERSION(VERSION);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -1571,6 +1571,7 @@ u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
|
||||
|
||||
return half_md4_transform(hash, keyptr->secret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral);
|
||||
|
||||
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||
u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
|
||||
|
@ -1172,7 +1172,7 @@ config ETH16I
|
||||
|
||||
config NE2000
|
||||
tristate "NE2000/NE1000 support"
|
||||
depends on NET_ISA || (Q40 && m) || M32R || TOSHIBA_RBTX4927 || TOSHIBA_RBTX4938
|
||||
depends on NET_ISA || (Q40 && m) || M32R || MACH_TX49XX
|
||||
select CRC32
|
||||
---help---
|
||||
If you have a network (Ethernet) card of this type, say Y and read
|
||||
|
@ -52,7 +52,6 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ioport.h>
|
||||
|
@ -551,7 +551,7 @@ static int eth_poll(struct napi_struct *napi, int budget)
|
||||
if ((skb = netdev_alloc_skb(dev, RX_BUFF_SIZE))) {
|
||||
phys = dma_map_single(&dev->dev, skb->data,
|
||||
RX_BUFF_SIZE, DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(phys)) {
|
||||
if (dma_mapping_error(&dev->dev, phys)) {
|
||||
dev_kfree_skb(skb);
|
||||
skb = NULL;
|
||||
}
|
||||
@ -698,7 +698,7 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
#endif
|
||||
|
||||
phys = dma_map_single(&dev->dev, mem, bytes, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(phys)) {
|
||||
if (dma_mapping_error(&dev->dev, phys)) {
|
||||
#ifdef __ARMEB__
|
||||
dev_kfree_skb(skb);
|
||||
#else
|
||||
@ -883,7 +883,7 @@ static int init_queues(struct port *port)
|
||||
desc->buf_len = MAX_MRU;
|
||||
desc->data = dma_map_single(&port->netdev->dev, data,
|
||||
RX_BUFF_SIZE, DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(desc->data)) {
|
||||
if (dma_mapping_error(&port->netdev->dev, desc->data)) {
|
||||
free_buffer(buff);
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -355,7 +355,7 @@ static int atl1e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
|
||||
struct atl1e_adapter *adapter = netdev_priv(netdev);
|
||||
|
||||
if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE |
|
||||
WAKE_MCAST | WAKE_BCAST | WAKE_MCAST))
|
||||
WAKE_UCAST | WAKE_MCAST | WAKE_BCAST))
|
||||
return -EOPNOTSUPP;
|
||||
/* these settings will always override what we currently have */
|
||||
adapter->wol = 0;
|
||||
|
@ -807,7 +807,7 @@ err_out:
|
||||
static int au1000_init(struct net_device *dev)
|
||||
{
|
||||
struct au1000_private *aup = (struct au1000_private *) dev->priv;
|
||||
u32 flags;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
u32 control;
|
||||
|
||||
|
@ -554,7 +554,7 @@ static int ax_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
||||
|
||||
spin_lock_irqsave(&ax->mii_lock, flags);
|
||||
mii_ethtool_gset(&ax->mii, cmd);
|
||||
spin_lock_irqsave(&ax->mii_lock, flags);
|
||||
spin_unlock_irqrestore(&ax->mii_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -567,7 +567,7 @@ static int ax_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
||||
|
||||
spin_lock_irqsave(&ax->mii_lock, flags);
|
||||
rc = mii_ethtool_sset(&ax->mii, cmd);
|
||||
spin_lock_irqsave(&ax->mii_lock, flags);
|
||||
spin_unlock_irqrestore(&ax->mii_lock, flags);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -35,8 +35,8 @@
|
||||
#include <linux/time.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/mii.h>
|
||||
#ifdef NETIF_F_HW_VLAN_TX
|
||||
#include <linux/if_vlan.h>
|
||||
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
|
||||
#define BCM_VLAN 1
|
||||
#endif
|
||||
#include <net/ip.h>
|
||||
@ -57,8 +57,8 @@
|
||||
|
||||
#define DRV_MODULE_NAME "bnx2"
|
||||
#define PFX DRV_MODULE_NAME ": "
|
||||
#define DRV_MODULE_VERSION "1.7.9"
|
||||
#define DRV_MODULE_RELDATE "July 18, 2008"
|
||||
#define DRV_MODULE_VERSION "1.8.0"
|
||||
#define DRV_MODULE_RELDATE "Aug 14, 2008"
|
||||
|
||||
#define RUN_AT(x) (jiffies + (x))
|
||||
|
||||
@ -2876,6 +2876,8 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
|
||||
struct sw_bd *rx_buf;
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t dma_addr;
|
||||
u16 vtag = 0;
|
||||
int hw_vlan __maybe_unused = 0;
|
||||
|
||||
sw_ring_cons = RX_RING_IDX(sw_cons);
|
||||
sw_ring_prod = RX_RING_IDX(sw_prod);
|
||||
@ -2919,7 +2921,7 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
|
||||
if (len <= bp->rx_copy_thresh) {
|
||||
struct sk_buff *new_skb;
|
||||
|
||||
new_skb = netdev_alloc_skb(bp->dev, len + 2);
|
||||
new_skb = netdev_alloc_skb(bp->dev, len + 6);
|
||||
if (new_skb == NULL) {
|
||||
bnx2_reuse_rx_skb(bp, rxr, skb, sw_ring_cons,
|
||||
sw_ring_prod);
|
||||
@ -2928,9 +2930,9 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
|
||||
|
||||
/* aligned copy */
|
||||
skb_copy_from_linear_data_offset(skb,
|
||||
BNX2_RX_OFFSET - 2,
|
||||
new_skb->data, len + 2);
|
||||
skb_reserve(new_skb, 2);
|
||||
BNX2_RX_OFFSET - 6,
|
||||
new_skb->data, len + 6);
|
||||
skb_reserve(new_skb, 6);
|
||||
skb_put(new_skb, len);
|
||||
|
||||
bnx2_reuse_rx_skb(bp, rxr, skb,
|
||||
@ -2941,6 +2943,25 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
|
||||
dma_addr, (sw_ring_cons << 16) | sw_ring_prod)))
|
||||
goto next_rx;
|
||||
|
||||
if ((status & L2_FHDR_STATUS_L2_VLAN_TAG) &&
|
||||
!(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG)) {
|
||||
vtag = rx_hdr->l2_fhdr_vlan_tag;
|
||||
#ifdef BCM_VLAN
|
||||
if (bp->vlgrp)
|
||||
hw_vlan = 1;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
struct vlan_ethhdr *ve = (struct vlan_ethhdr *)
|
||||
__skb_push(skb, 4);
|
||||
|
||||
memmove(ve, skb->data + 4, ETH_ALEN * 2);
|
||||
ve->h_vlan_proto = htons(ETH_P_8021Q);
|
||||
ve->h_vlan_TCI = htons(vtag);
|
||||
len += 4;
|
||||
}
|
||||
}
|
||||
|
||||
skb->protocol = eth_type_trans(skb, bp->dev);
|
||||
|
||||
if ((len > (bp->dev->mtu + ETH_HLEN)) &&
|
||||
@ -2962,10 +2983,8 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
|
||||
}
|
||||
|
||||
#ifdef BCM_VLAN
|
||||
if ((status & L2_FHDR_STATUS_L2_VLAN_TAG) && bp->vlgrp) {
|
||||
vlan_hwaccel_receive_skb(skb, bp->vlgrp,
|
||||
rx_hdr->l2_fhdr_vlan_tag);
|
||||
}
|
||||
if (hw_vlan)
|
||||
vlan_hwaccel_receive_skb(skb, bp->vlgrp, vtag);
|
||||
else
|
||||
#endif
|
||||
netif_receive_skb(skb);
|
||||
@ -3237,10 +3256,10 @@ bnx2_set_rx_mode(struct net_device *dev)
|
||||
BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG);
|
||||
sort_mode = 1 | BNX2_RPM_SORT_USER0_BC_EN;
|
||||
#ifdef BCM_VLAN
|
||||
if (!bp->vlgrp && !(bp->flags & BNX2_FLAG_ASF_ENABLE))
|
||||
if (!bp->vlgrp && (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN))
|
||||
rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
|
||||
#else
|
||||
if (!(bp->flags & BNX2_FLAG_ASF_ENABLE))
|
||||
if (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN)
|
||||
rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
|
||||
#endif
|
||||
if (dev->flags & IFF_PROMISC) {
|
||||
@ -5963,10 +5982,12 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
vlan_tag_flags |= TX_BD_FLAGS_TCP_UDP_CKSUM;
|
||||
}
|
||||
|
||||
#ifdef BCM_VLAN
|
||||
if (bp->vlgrp && vlan_tx_tag_present(skb)) {
|
||||
vlan_tag_flags |=
|
||||
(TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16));
|
||||
}
|
||||
#endif
|
||||
if ((mss = skb_shinfo(skb)->gso_size)) {
|
||||
u32 tcp_opt_len, ip_tcp_len;
|
||||
struct iphdr *iph;
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include "bnx2x_reg.h"
|
||||
#include "bnx2x_fw_defs.h"
|
||||
|
@ -44,7 +44,6 @@
|
||||
#include <net/ip.h>
|
||||
#include <net/tcp.h>
|
||||
#include <net/checksum.h>
|
||||
#include <linux/version.h>
|
||||
#include <net/ip6_checksum.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/crc32.h>
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
|
@ -389,7 +389,7 @@
|
||||
|
||||
/* Interrupt Cause Set */
|
||||
#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */
|
||||
#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
|
||||
#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */
|
||||
#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */
|
||||
|
||||
/* Transmit Descriptor Control */
|
||||
|
@ -326,6 +326,7 @@ struct e1000_info {
|
||||
#define FLAG_RX_CSUM_ENABLED (1 << 28)
|
||||
#define FLAG_TSO_FORCE (1 << 29)
|
||||
#define FLAG_RX_RESTART_NOW (1 << 30)
|
||||
#define FLAG_MSI_TEST_FAILED (1 << 31)
|
||||
|
||||
#define E1000_RX_DESC_PS(R, i) \
|
||||
(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
|
||||
|
@ -177,7 +177,7 @@ static u32 e1000_get_link(struct net_device *netdev)
|
||||
u32 status;
|
||||
|
||||
status = er32(STATUS);
|
||||
return (status & E1000_STATUS_LU);
|
||||
return (status & E1000_STATUS_LU) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
|
||||
|
@ -510,9 +510,12 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
|
||||
netdev_alloc_skb(netdev, length + NET_IP_ALIGN);
|
||||
if (new_skb) {
|
||||
skb_reserve(new_skb, NET_IP_ALIGN);
|
||||
memcpy(new_skb->data - NET_IP_ALIGN,
|
||||
skb->data - NET_IP_ALIGN,
|
||||
length + NET_IP_ALIGN);
|
||||
skb_copy_to_linear_data_offset(new_skb,
|
||||
-NET_IP_ALIGN,
|
||||
(skb->data -
|
||||
NET_IP_ALIGN),
|
||||
(length +
|
||||
NET_IP_ALIGN));
|
||||
/* save the skb in buffer_info as good */
|
||||
buffer_info->skb = skb;
|
||||
skb = new_skb;
|
||||
@ -1233,26 +1236,36 @@ static irqreturn_t e1000_intr(int irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_request_irq - initialize interrupts
|
||||
*
|
||||
* Attempts to configure interrupts using the best available
|
||||
* capabilities of the hardware and kernel.
|
||||
**/
|
||||
static int e1000_request_irq(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
irq_handler_t handler = e1000_intr;
|
||||
int irq_flags = IRQF_SHARED;
|
||||
int err;
|
||||
|
||||
if (!pci_enable_msi(adapter->pdev)) {
|
||||
adapter->flags |= FLAG_MSI_ENABLED;
|
||||
handler = e1000_intr_msi;
|
||||
irq_flags = 0;
|
||||
if (!(adapter->flags & FLAG_MSI_TEST_FAILED)) {
|
||||
err = pci_enable_msi(adapter->pdev);
|
||||
if (!err) {
|
||||
adapter->flags |= FLAG_MSI_ENABLED;
|
||||
irq_flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name,
|
||||
netdev);
|
||||
err = request_irq(adapter->pdev->irq,
|
||||
((adapter->flags & FLAG_MSI_ENABLED) ?
|
||||
&e1000_intr_msi : &e1000_intr),
|
||||
irq_flags, netdev->name, netdev);
|
||||
if (err) {
|
||||
e_err("Unable to allocate %s interrupt (return: %d)\n",
|
||||
adapter->flags & FLAG_MSI_ENABLED ? "MSI":"INTx", err);
|
||||
if (adapter->flags & FLAG_MSI_ENABLED)
|
||||
if (adapter->flags & FLAG_MSI_ENABLED) {
|
||||
pci_disable_msi(adapter->pdev);
|
||||
adapter->flags &= ~FLAG_MSI_ENABLED;
|
||||
}
|
||||
e_err("Unable to allocate interrupt, Error: %d\n", err);
|
||||
}
|
||||
|
||||
return err;
|
||||
@ -2591,6 +2604,135 @@ err:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_intr_msi_test - Interrupt Handler
|
||||
* @irq: interrupt number
|
||||
* @data: pointer to a network interface device structure
|
||||
**/
|
||||
static irqreturn_t e1000_intr_msi_test(int irq, void *data)
|
||||
{
|
||||
struct net_device *netdev = data;
|
||||
struct e1000_adapter *adapter = netdev_priv(netdev);
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
u32 icr = er32(ICR);
|
||||
|
||||
e_dbg("%s: icr is %08X\n", netdev->name, icr);
|
||||
if (icr & E1000_ICR_RXSEQ) {
|
||||
adapter->flags &= ~FLAG_MSI_TEST_FAILED;
|
||||
wmb();
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_test_msi_interrupt - Returns 0 for successful test
|
||||
* @adapter: board private struct
|
||||
*
|
||||
* code flow taken from tg3.c
|
||||
**/
|
||||
static int e1000_test_msi_interrupt(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
int err;
|
||||
|
||||
/* poll_enable hasn't been called yet, so don't need disable */
|
||||
/* clear any pending events */
|
||||
er32(ICR);
|
||||
|
||||
/* free the real vector and request a test handler */
|
||||
e1000_free_irq(adapter);
|
||||
|
||||
/* Assume that the test fails, if it succeeds then the test
|
||||
* MSI irq handler will unset this flag */
|
||||
adapter->flags |= FLAG_MSI_TEST_FAILED;
|
||||
|
||||
err = pci_enable_msi(adapter->pdev);
|
||||
if (err)
|
||||
goto msi_test_failed;
|
||||
|
||||
err = request_irq(adapter->pdev->irq, &e1000_intr_msi_test, 0,
|
||||
netdev->name, netdev);
|
||||
if (err) {
|
||||
pci_disable_msi(adapter->pdev);
|
||||
goto msi_test_failed;
|
||||
}
|
||||
|
||||
wmb();
|
||||
|
||||
e1000_irq_enable(adapter);
|
||||
|
||||
/* fire an unusual interrupt on the test handler */
|
||||
ew32(ICS, E1000_ICS_RXSEQ);
|
||||
e1e_flush();
|
||||
msleep(50);
|
||||
|
||||
e1000_irq_disable(adapter);
|
||||
|
||||
rmb();
|
||||
|
||||
if (adapter->flags & FLAG_MSI_TEST_FAILED) {
|
||||
err = -EIO;
|
||||
e_info("MSI interrupt test failed!\n");
|
||||
}
|
||||
|
||||
free_irq(adapter->pdev->irq, netdev);
|
||||
pci_disable_msi(adapter->pdev);
|
||||
|
||||
if (err == -EIO)
|
||||
goto msi_test_failed;
|
||||
|
||||
/* okay so the test worked, restore settings */
|
||||
e_dbg("%s: MSI interrupt test succeeded!\n", netdev->name);
|
||||
msi_test_failed:
|
||||
/* restore the original vector, even if it failed */
|
||||
e1000_request_irq(adapter);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_test_msi - Returns 0 if MSI test succeeds or INTx mode is restored
|
||||
* @adapter: board private struct
|
||||
*
|
||||
* code flow taken from tg3.c, called with e1000 interrupts disabled.
|
||||
**/
|
||||
static int e1000_test_msi(struct e1000_adapter *adapter)
|
||||
{
|
||||
int err;
|
||||
u16 pci_cmd;
|
||||
|
||||
if (!(adapter->flags & FLAG_MSI_ENABLED))
|
||||
return 0;
|
||||
|
||||
/* disable SERR in case the MSI write causes a master abort */
|
||||
pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd);
|
||||
pci_write_config_word(adapter->pdev, PCI_COMMAND,
|
||||
pci_cmd & ~PCI_COMMAND_SERR);
|
||||
|
||||
err = e1000_test_msi_interrupt(adapter);
|
||||
|
||||
/* restore previous setting of command word */
|
||||
pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd);
|
||||
|
||||
/* success ! */
|
||||
if (!err)
|
||||
return 0;
|
||||
|
||||
/* EIO means MSI test failed */
|
||||
if (err != -EIO)
|
||||
return err;
|
||||
|
||||
/* back to INTx mode */
|
||||
e_warn("MSI interrupt test failed, using legacy interrupt.\n");
|
||||
|
||||
e1000_free_irq(adapter);
|
||||
|
||||
err = e1000_request_irq(adapter);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_open - Called when a network interface is made active
|
||||
* @netdev: network interface device structure
|
||||
@ -2649,6 +2791,19 @@ static int e1000_open(struct net_device *netdev)
|
||||
if (err)
|
||||
goto err_req_irq;
|
||||
|
||||
/*
|
||||
* Work around PCIe errata with MSI interrupts causing some chipsets to
|
||||
* ignore e1000e MSI messages, which means we need to test our MSI
|
||||
* interrupt now
|
||||
*/
|
||||
{
|
||||
err = e1000_test_msi(adapter);
|
||||
if (err) {
|
||||
e_err("Interrupt allocation failed\n");
|
||||
goto err_req_irq;
|
||||
}
|
||||
}
|
||||
|
||||
/* From here on the code is the same as e1000e_up() */
|
||||
clear_bit(__E1000_DOWN, &adapter->state);
|
||||
|
||||
@ -3055,7 +3210,7 @@ static void e1000_watchdog_task(struct work_struct *work)
|
||||
case SPEED_10:
|
||||
txb2b = 0;
|
||||
netdev->tx_queue_len = 10;
|
||||
adapter->tx_timeout_factor = 14;
|
||||
adapter->tx_timeout_factor = 16;
|
||||
break;
|
||||
case SPEED_100:
|
||||
txb2b = 0;
|
||||
@ -3721,7 +3876,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
|
||||
struct e1000_adapter *adapter = netdev_priv(netdev);
|
||||
int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
|
||||
|
||||
if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
|
||||
if ((new_mtu < ETH_ZLEN + ETH_FCS_LEN + VLAN_HLEN) ||
|
||||
(max_frame > MAX_JUMBO_FRAME_SIZE)) {
|
||||
e_err("Invalid MTU setting\n");
|
||||
return -EINVAL;
|
||||
|
@ -324,14 +324,27 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
|
||||
adapter->itr = 20000;
|
||||
break;
|
||||
default:
|
||||
e1000_validate_option(&adapter->itr, &opt,
|
||||
adapter);
|
||||
/*
|
||||
* save the setting, because the dynamic bits
|
||||
* change itr. clear the lower two bits
|
||||
* because they are used as control
|
||||
* Save the setting, because the dynamic bits
|
||||
* change itr.
|
||||
*/
|
||||
adapter->itr_setting = adapter->itr & ~3;
|
||||
if (e1000_validate_option(&adapter->itr, &opt,
|
||||
adapter) &&
|
||||
(adapter->itr == 3)) {
|
||||
/*
|
||||
* In case of invalid user value,
|
||||
* default to conservative mode.
|
||||
*/
|
||||
adapter->itr_setting = adapter->itr;
|
||||
adapter->itr = 20000;
|
||||
} else {
|
||||
/*
|
||||
* Clear the lower two bits because
|
||||
* they are used as control.
|
||||
*/
|
||||
adapter->itr_setting =
|
||||
adapter->itr & ~3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
@ -134,9 +134,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int l
|
||||
static void gfar_vlan_rx_register(struct net_device *netdev,
|
||||
struct vlan_group *grp);
|
||||
void gfar_halt(struct net_device *dev);
|
||||
#ifdef CONFIG_PM
|
||||
static void gfar_halt_nodisable(struct net_device *dev);
|
||||
#endif
|
||||
void gfar_start(struct net_device *dev);
|
||||
static void gfar_clear_exact_match(struct net_device *dev);
|
||||
static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr);
|
||||
@ -631,7 +629,6 @@ static void init_registers(struct net_device *dev)
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
/* Halt the receive and transmit queues */
|
||||
static void gfar_halt_nodisable(struct net_device *dev)
|
||||
{
|
||||
@ -657,7 +654,6 @@ static void gfar_halt_nodisable(struct net_device *dev)
|
||||
cpu_relax();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Halt the receive and transmit queues */
|
||||
void gfar_halt(struct net_device *dev)
|
||||
@ -666,6 +662,8 @@ void gfar_halt(struct net_device *dev)
|
||||
struct gfar __iomem *regs = priv->regs;
|
||||
u32 tempval;
|
||||
|
||||
gfar_halt_nodisable(dev);
|
||||
|
||||
/* Disable Rx and Tx */
|
||||
tempval = gfar_read(®s->maccfg1);
|
||||
tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN);
|
||||
|
@ -33,7 +33,6 @@
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include "gianfar.h"
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
#ifndef __LINUX_IPG_H
|
||||
#define __LINUX_IPG_H
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/kernel.h>
|
||||
@ -21,7 +20,6 @@
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/version.h>
|
||||
#include <asm/bitops.h>
|
||||
|
||||
/*
|
||||
|
@ -190,6 +190,7 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
|
||||
case IXGBE_DEV_ID_82598AF_DUAL_PORT:
|
||||
case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
|
||||
case IXGBE_DEV_ID_82598EB_CX4:
|
||||
case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
|
||||
media_type = ixgbe_media_type_fiber;
|
||||
break;
|
||||
case IXGBE_DEV_ID_82598AT_DUAL_PORT:
|
||||
|
@ -48,7 +48,7 @@ char ixgbe_driver_name[] = "ixgbe";
|
||||
static const char ixgbe_driver_string[] =
|
||||
"Intel(R) 10 Gigabit PCI Express Network Driver";
|
||||
|
||||
#define DRV_VERSION "1.3.18-k2"
|
||||
#define DRV_VERSION "1.3.18-k4"
|
||||
const char ixgbe_driver_version[] = DRV_VERSION;
|
||||
static const char ixgbe_copyright[] =
|
||||
"Copyright (c) 1999-2007 Intel Corporation.";
|
||||
@ -72,6 +72,8 @@ static struct pci_device_id ixgbe_pci_tbl[] = {
|
||||
board_82598 },
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_CX4),
|
||||
board_82598 },
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_CX4_DUAL_PORT),
|
||||
board_82598 },
|
||||
|
||||
/* required last entry */
|
||||
{0, }
|
||||
|
@ -39,6 +39,7 @@
|
||||
#define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7
|
||||
#define IXGBE_DEV_ID_82598AT_DUAL_PORT 0x10C8
|
||||
#define IXGBE_DEV_ID_82598EB_CX4 0x10DD
|
||||
#define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC
|
||||
|
||||
/* General Registers */
|
||||
#define IXGBE_CTRL 0x00000
|
||||
|
@ -64,68 +64,6 @@ struct pcpu_lstats {
|
||||
unsigned long bytes;
|
||||
};
|
||||
|
||||
/* KISS: just allocate small chunks and copy bits.
|
||||
*
|
||||
* So, in fact, this is documentation, explaining what we expect
|
||||
* of largesending device modulo TCP checksum, which is ignored for loopback.
|
||||
*/
|
||||
|
||||
#ifdef LOOPBACK_TSO
|
||||
static void emulate_large_send_offload(struct sk_buff *skb)
|
||||
{
|
||||
struct iphdr *iph = ip_hdr(skb);
|
||||
struct tcphdr *th = (struct tcphdr *)(skb_network_header(skb) +
|
||||
(iph->ihl * 4));
|
||||
unsigned int doffset = (iph->ihl + th->doff) * 4;
|
||||
unsigned int mtu = skb_shinfo(skb)->gso_size + doffset;
|
||||
unsigned int offset = 0;
|
||||
u32 seq = ntohl(th->seq);
|
||||
u16 id = ntohs(iph->id);
|
||||
|
||||
while (offset + doffset < skb->len) {
|
||||
unsigned int frag_size = min(mtu, skb->len - offset) - doffset;
|
||||
struct sk_buff *nskb = alloc_skb(mtu + 32, GFP_ATOMIC);
|
||||
|
||||
if (!nskb)
|
||||
break;
|
||||
skb_reserve(nskb, 32);
|
||||
skb_set_mac_header(nskb, -ETH_HLEN);
|
||||
skb_reset_network_header(nskb);
|
||||
iph = ip_hdr(nskb);
|
||||
skb_copy_to_linear_data(nskb, skb_network_header(skb),
|
||||
doffset);
|
||||
if (skb_copy_bits(skb,
|
||||
doffset + offset,
|
||||
nskb->data + doffset,
|
||||
frag_size))
|
||||
BUG();
|
||||
skb_put(nskb, doffset + frag_size);
|
||||
nskb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
nskb->dev = skb->dev;
|
||||
nskb->priority = skb->priority;
|
||||
nskb->protocol = skb->protocol;
|
||||
nskb->dst = dst_clone(skb->dst);
|
||||
memcpy(nskb->cb, skb->cb, sizeof(skb->cb));
|
||||
nskb->pkt_type = skb->pkt_type;
|
||||
|
||||
th = (struct tcphdr *)(skb_network_header(nskb) + iph->ihl * 4);
|
||||
iph->tot_len = htons(frag_size + doffset);
|
||||
iph->id = htons(id);
|
||||
iph->check = 0;
|
||||
iph->check = ip_fast_csum((unsigned char *) iph, iph->ihl);
|
||||
th->seq = htonl(seq);
|
||||
if (offset + doffset + frag_size < skb->len)
|
||||
th->fin = th->psh = 0;
|
||||
netif_rx(nskb);
|
||||
offset += frag_size;
|
||||
seq += frag_size;
|
||||
id++;
|
||||
}
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
#endif /* LOOPBACK_TSO */
|
||||
|
||||
/*
|
||||
* The higher levels take care of making this non-reentrant (it's
|
||||
* called with bh's disabled).
|
||||
@ -137,9 +75,6 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
skb_orphan(skb);
|
||||
|
||||
skb->protocol = eth_type_trans(skb,dev);
|
||||
#ifndef LOOPBACK_MUST_CHECKSUM
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
#endif
|
||||
|
||||
#ifdef LOOPBACK_TSO
|
||||
if (skb_is_gso(skb)) {
|
||||
@ -234,9 +169,7 @@ static void loopback_setup(struct net_device *dev)
|
||||
dev->type = ARPHRD_LOOPBACK; /* 0x0001*/
|
||||
dev->flags = IFF_LOOPBACK;
|
||||
dev->features = NETIF_F_SG | NETIF_F_FRAGLIST
|
||||
#ifdef LOOPBACK_TSO
|
||||
| NETIF_F_TSO
|
||||
#endif
|
||||
| NETIF_F_NO_CSUM
|
||||
| NETIF_F_HIGHDMA
|
||||
| NETIF_F_LLTX
|
||||
|
@ -3548,7 +3548,11 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp)
|
||||
|
||||
/* try to load the slice aware rss firmware */
|
||||
old_fw = mgp->fw_name;
|
||||
if (old_fw == myri10ge_fw_aligned)
|
||||
if (myri10ge_fw_name != NULL) {
|
||||
dev_info(&mgp->pdev->dev, "overriding rss firmware to %s\n",
|
||||
myri10ge_fw_name);
|
||||
mgp->fw_name = myri10ge_fw_name;
|
||||
} else if (old_fw == myri10ge_fw_aligned)
|
||||
mgp->fw_name = myri10ge_fw_rss_aligned;
|
||||
else
|
||||
mgp->fw_name = myri10ge_fw_rss_unaligned;
|
||||
|
@ -118,7 +118,7 @@ bad_clone_list[] __initdata = {
|
||||
{"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
|
||||
{"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */
|
||||
{"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */
|
||||
#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
|
||||
#ifdef CONFIG_MACH_TX49XX
|
||||
{"RBHMA4X00-RTL8019", "RBHMA4X00/RTL8019", {0x00, 0x60, 0x0a}}, /* Toshiba built-in */
|
||||
#endif
|
||||
{"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */
|
||||
@ -142,7 +142,7 @@ bad_clone_list[] __initdata = {
|
||||
#if defined(CONFIG_PLAT_MAPPI)
|
||||
# define DCR_VAL 0x4b
|
||||
#elif defined(CONFIG_PLAT_OAKS32R) || \
|
||||
defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
|
||||
defined(CONFIG_MACH_TX49XX)
|
||||
# define DCR_VAL 0x48 /* 8-bit mode */
|
||||
#else
|
||||
# define DCR_VAL 0x49
|
||||
|
@ -66,8 +66,8 @@
|
||||
|
||||
#define _NETXEN_NIC_LINUX_MAJOR 4
|
||||
#define _NETXEN_NIC_LINUX_MINOR 0
|
||||
#define _NETXEN_NIC_LINUX_SUBVERSION 0
|
||||
#define NETXEN_NIC_LINUX_VERSIONID "4.0.0"
|
||||
#define _NETXEN_NIC_LINUX_SUBVERSION 11
|
||||
#define NETXEN_NIC_LINUX_VERSIONID "4.0.11"
|
||||
|
||||
#define NETXEN_VERSION_CODE(a, b, c) (((a) << 16) + ((b) << 8) + (c))
|
||||
|
||||
@ -1615,7 +1615,8 @@ dma_watchdog_wakeup(struct netxen_adapter *adapter)
|
||||
|
||||
|
||||
int netxen_is_flash_supported(struct netxen_adapter *adapter);
|
||||
int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 mac[]);
|
||||
int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 *mac);
|
||||
int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac);
|
||||
extern void netxen_change_ringparam(struct netxen_adapter *adapter);
|
||||
extern int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr,
|
||||
int *valp);
|
||||
|
@ -733,31 +733,56 @@ static int netxen_get_flash_block(struct netxen_adapter *adapter, int base,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 mac[])
|
||||
int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 *mac)
|
||||
{
|
||||
__le32 *pmac = (__le32 *) & mac[0];
|
||||
__le32 *pmac = (__le32 *) mac;
|
||||
u32 offset;
|
||||
|
||||
if (netxen_get_flash_block(adapter,
|
||||
NETXEN_USER_START +
|
||||
offsetof(struct netxen_new_user_info,
|
||||
mac_addr),
|
||||
FLASH_NUM_PORTS * sizeof(u64), pmac) == -1) {
|
||||
offset = NETXEN_USER_START +
|
||||
offsetof(struct netxen_new_user_info, mac_addr) +
|
||||
adapter->portnum * sizeof(u64);
|
||||
|
||||
if (netxen_get_flash_block(adapter, offset, sizeof(u64), pmac) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*mac == cpu_to_le64(~0ULL)) {
|
||||
|
||||
offset = NETXEN_USER_START_OLD +
|
||||
offsetof(struct netxen_user_old_info, mac_addr) +
|
||||
adapter->portnum * sizeof(u64);
|
||||
|
||||
if (netxen_get_flash_block(adapter,
|
||||
NETXEN_USER_START_OLD +
|
||||
offsetof(struct netxen_user_old_info,
|
||||
mac_addr),
|
||||
FLASH_NUM_PORTS * sizeof(u64),
|
||||
pmac) == -1)
|
||||
offset, sizeof(u64), pmac) == -1)
|
||||
return -1;
|
||||
|
||||
if (*mac == cpu_to_le64(~0ULL))
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac)
|
||||
{
|
||||
uint32_t crbaddr, mac_hi, mac_lo;
|
||||
int pci_func = adapter->ahw.pci_func;
|
||||
|
||||
crbaddr = CRB_MAC_BLOCK_START +
|
||||
(4 * ((pci_func/2) * 3)) + (4 * (pci_func & 1));
|
||||
|
||||
adapter->hw_read_wx(adapter, crbaddr, &mac_lo, 4);
|
||||
adapter->hw_read_wx(adapter, crbaddr+4, &mac_hi, 4);
|
||||
|
||||
mac_hi = cpu_to_le32(mac_hi);
|
||||
mac_lo = cpu_to_le32(mac_lo);
|
||||
|
||||
if (pci_func & 1)
|
||||
*mac = ((mac_lo >> 16) | ((u64)mac_hi << 16));
|
||||
else
|
||||
*mac = ((mac_lo) | ((u64)mac_hi << 32));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CRB_WIN_LOCK_TIMEOUT 100000000
|
||||
|
||||
static int crb_win_lock(struct netxen_adapter *adapter)
|
||||
@ -2183,10 +2208,10 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
|
||||
if (adapter->portnum == 0) {
|
||||
get_brd_name_by_type(board_info->board_type, brd_name);
|
||||
|
||||
printk("NetXen %s Board S/N %s Chip id 0x%x\n",
|
||||
brd_name, serial_num, board_info->chip_id);
|
||||
printk("NetXen Firmware version %d.%d.%d\n", fw_major,
|
||||
fw_minor, fw_build);
|
||||
printk(KERN_INFO "NetXen %s Board S/N %s Chip rev 0x%x\n",
|
||||
brd_name, serial_num, adapter->ahw.revision_id);
|
||||
printk(KERN_INFO "NetXen Firmware version %d.%d.%d\n",
|
||||
fw_major, fw_minor, fw_build);
|
||||
}
|
||||
|
||||
if (NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build) <
|
||||
|
@ -1079,10 +1079,12 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
|
||||
|
||||
void netxen_free_adapter_offload(struct netxen_adapter *adapter)
|
||||
{
|
||||
int i;
|
||||
int i = 100;
|
||||
|
||||
if (adapter->dummy_dma.addr) {
|
||||
i = 100;
|
||||
if (!adapter->dummy_dma.addr)
|
||||
return;
|
||||
|
||||
if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
|
||||
do {
|
||||
if (dma_watchdog_shutdown_request(adapter) == 1)
|
||||
break;
|
||||
@ -1090,17 +1092,17 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter)
|
||||
if (dma_watchdog_shutdown_poll_result(adapter) == 1)
|
||||
break;
|
||||
} while (--i);
|
||||
}
|
||||
|
||||
if (i) {
|
||||
pci_free_consistent(adapter->pdev,
|
||||
NETXEN_HOST_DUMMY_DMA_SIZE,
|
||||
adapter->dummy_dma.addr,
|
||||
adapter->dummy_dma.phys_addr);
|
||||
adapter->dummy_dma.addr = NULL;
|
||||
} else {
|
||||
printk(KERN_ERR "%s: dma_watchdog_shutdown failed\n",
|
||||
adapter->netdev->name);
|
||||
}
|
||||
if (i) {
|
||||
pci_free_consistent(adapter->pdev,
|
||||
NETXEN_HOST_DUMMY_DMA_SIZE,
|
||||
adapter->dummy_dma.addr,
|
||||
adapter->dummy_dma.phys_addr);
|
||||
adapter->dummy_dma.addr = NULL;
|
||||
} else {
|
||||
printk(KERN_ERR "%s: dma_watchdog_shutdown failed\n",
|
||||
adapter->netdev->name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,76 +149,18 @@ static uint32_t msi_tgt_status[8] = {
|
||||
|
||||
static struct netxen_legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG;
|
||||
|
||||
static void netxen_nic_disable_int(struct netxen_adapter *adapter)
|
||||
static inline void netxen_nic_disable_int(struct netxen_adapter *adapter)
|
||||
{
|
||||
u32 mask = 0x7ff;
|
||||
int retries = 32;
|
||||
int pci_fn = adapter->ahw.pci_func;
|
||||
|
||||
if (adapter->msi_mode != MSI_MODE_MULTIFUNC)
|
||||
adapter->pci_write_normalize(adapter,
|
||||
adapter->crb_intr_mask, 0);
|
||||
|
||||
if (adapter->intr_scheme != -1 &&
|
||||
adapter->intr_scheme != INTR_SCHEME_PERPORT)
|
||||
adapter->pci_write_immediate(adapter, ISR_INT_MASK, mask);
|
||||
|
||||
if (!NETXEN_IS_MSI_FAMILY(adapter)) {
|
||||
do {
|
||||
adapter->pci_write_immediate(adapter,
|
||||
adapter->legacy_intr.tgt_status_reg,
|
||||
0xffffffff);
|
||||
mask = adapter->pci_read_immediate(adapter,
|
||||
ISR_INT_VECTOR);
|
||||
if (!(mask & 0x80))
|
||||
break;
|
||||
udelay(10);
|
||||
} while (--retries);
|
||||
|
||||
if (!retries) {
|
||||
printk(KERN_NOTICE "%s: Failed to disable interrupt\n",
|
||||
netxen_nic_driver_name);
|
||||
}
|
||||
} else {
|
||||
if (adapter->msi_mode == MSI_MODE_MULTIFUNC) {
|
||||
adapter->pci_write_immediate(adapter,
|
||||
msi_tgt_status[pci_fn], 0xffffffff);
|
||||
}
|
||||
}
|
||||
adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0);
|
||||
}
|
||||
|
||||
static void netxen_nic_enable_int(struct netxen_adapter *adapter)
|
||||
static inline void netxen_nic_enable_int(struct netxen_adapter *adapter)
|
||||
{
|
||||
u32 mask;
|
||||
|
||||
if (adapter->intr_scheme != -1 &&
|
||||
adapter->intr_scheme != INTR_SCHEME_PERPORT) {
|
||||
switch (adapter->ahw.board_type) {
|
||||
case NETXEN_NIC_GBE:
|
||||
mask = 0x77b;
|
||||
break;
|
||||
case NETXEN_NIC_XGBE:
|
||||
mask = 0x77f;
|
||||
break;
|
||||
default:
|
||||
mask = 0x7ff;
|
||||
break;
|
||||
}
|
||||
|
||||
adapter->pci_write_immediate(adapter, ISR_INT_MASK, mask);
|
||||
}
|
||||
|
||||
adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0x1);
|
||||
|
||||
if (!NETXEN_IS_MSI_FAMILY(adapter)) {
|
||||
mask = 0xbff;
|
||||
if (adapter->intr_scheme == INTR_SCHEME_PERPORT)
|
||||
adapter->pci_write_immediate(adapter,
|
||||
adapter->legacy_intr.tgt_mask_reg, mask);
|
||||
else
|
||||
adapter->pci_write_normalize(adapter,
|
||||
CRB_INT_VECTOR, 0);
|
||||
}
|
||||
if (!NETXEN_IS_MSI_FAMILY(adapter))
|
||||
adapter->pci_write_immediate(adapter,
|
||||
adapter->legacy_intr.tgt_mask_reg, 0xfbff);
|
||||
}
|
||||
|
||||
static int nx_set_dma_mask(struct netxen_adapter *adapter, uint8_t revision_id)
|
||||
@ -501,6 +443,44 @@ static void netxen_init_msix_entries(struct netxen_adapter *adapter)
|
||||
adapter->msix_entries[i].entry = i;
|
||||
}
|
||||
|
||||
static int
|
||||
netxen_read_mac_addr(struct netxen_adapter *adapter)
|
||||
{
|
||||
int i;
|
||||
unsigned char *p;
|
||||
__le64 mac_addr;
|
||||
DECLARE_MAC_BUF(mac);
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
|
||||
if (netxen_is_flash_supported(adapter) != 0)
|
||||
return -EIO;
|
||||
|
||||
if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
|
||||
if (netxen_p3_get_mac_addr(adapter, &mac_addr) != 0)
|
||||
return -EIO;
|
||||
} else {
|
||||
if (netxen_get_flash_mac_addr(adapter, &mac_addr) != 0)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
p = (unsigned char *)&mac_addr;
|
||||
for (i = 0; i < 6; i++)
|
||||
netdev->dev_addr[i] = *(p + 5 - i);
|
||||
|
||||
memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len);
|
||||
|
||||
/* set station address */
|
||||
|
||||
if (!is_valid_ether_addr(netdev->perm_addr)) {
|
||||
dev_warn(&pdev->dev, "Bad MAC address %s.\n",
|
||||
print_mac(mac, netdev->dev_addr));
|
||||
} else
|
||||
adapter->macaddr_set(adapter, netdev->dev_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* netxen_nic_probe()
|
||||
*
|
||||
@ -529,10 +509,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
unsigned long mem_base, mem_len, db_base, db_len, pci_len0 = 0;
|
||||
int i = 0, err;
|
||||
int first_driver, first_boot;
|
||||
__le64 mac_addr[FLASH_NUM_PORTS + 1];
|
||||
u32 val;
|
||||
int pci_func_id = PCI_FUNC(pdev->devfn);
|
||||
DECLARE_MAC_BUF(mac);
|
||||
struct netxen_legacy_intr_set *legacy_intrp;
|
||||
uint8_t revision_id;
|
||||
|
||||
@ -545,6 +523,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (pdev->revision >= NX_P3_A0 && pdev->revision < NX_P3_B1) {
|
||||
printk(KERN_WARNING "NetXen chip revisions between 0x%x-0x%x"
|
||||
"will not be enabled.\n",
|
||||
NX_P3_A0, NX_P3_B1);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if ((err = pci_enable_device(pdev)))
|
||||
return err;
|
||||
|
||||
@ -898,34 +883,14 @@ request_msi:
|
||||
goto err_out_disable_msi;
|
||||
|
||||
init_timer(&adapter->watchdog_timer);
|
||||
adapter->ahw.linkup = 0;
|
||||
adapter->watchdog_timer.function = &netxen_watchdog;
|
||||
adapter->watchdog_timer.data = (unsigned long)adapter;
|
||||
INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task);
|
||||
INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task);
|
||||
|
||||
if (netxen_is_flash_supported(adapter) == 0 &&
|
||||
netxen_get_flash_mac_addr(adapter, mac_addr) == 0) {
|
||||
unsigned char *p;
|
||||
|
||||
p = (unsigned char *)&mac_addr[adapter->portnum];
|
||||
netdev->dev_addr[0] = *(p + 5);
|
||||
netdev->dev_addr[1] = *(p + 4);
|
||||
netdev->dev_addr[2] = *(p + 3);
|
||||
netdev->dev_addr[3] = *(p + 2);
|
||||
netdev->dev_addr[4] = *(p + 1);
|
||||
netdev->dev_addr[5] = *(p + 0);
|
||||
|
||||
memcpy(netdev->perm_addr, netdev->dev_addr,
|
||||
netdev->addr_len);
|
||||
if (!is_valid_ether_addr(netdev->perm_addr)) {
|
||||
printk(KERN_ERR "%s: Bad MAC address %s.\n",
|
||||
netxen_nic_driver_name,
|
||||
print_mac(mac, netdev->dev_addr));
|
||||
} else {
|
||||
adapter->macaddr_set(adapter, netdev->dev_addr);
|
||||
}
|
||||
}
|
||||
err = netxen_read_mac_addr(adapter);
|
||||
if (err)
|
||||
dev_warn(&pdev->dev, "failed to read mac addr\n");
|
||||
|
||||
netif_carrier_off(netdev);
|
||||
netif_stop_queue(netdev);
|
||||
@ -1000,6 +965,7 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
|
||||
|
||||
if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
|
||||
netxen_free_hw_resources(adapter);
|
||||
netxen_release_rx_buffers(adapter);
|
||||
netxen_free_sw_resources(adapter);
|
||||
}
|
||||
|
||||
@ -1069,6 +1035,15 @@ static int netxen_nic_open(struct net_device *netdev)
|
||||
goto err_out_free_sw;
|
||||
}
|
||||
|
||||
if ((adapter->msi_mode != MSI_MODE_MULTIFUNC) ||
|
||||
(adapter->intr_scheme != INTR_SCHEME_PERPORT)) {
|
||||
printk(KERN_ERR "%s: Firmware interrupt scheme is "
|
||||
"incompatible with driver\n",
|
||||
netdev->name);
|
||||
adapter->driver_mismatch = 1;
|
||||
goto err_out_free_hw;
|
||||
}
|
||||
|
||||
if (adapter->fw_major < 4) {
|
||||
adapter->crb_addr_cmd_producer =
|
||||
crb_cmd_producer[adapter->portnum];
|
||||
@ -1094,7 +1069,7 @@ static int netxen_nic_open(struct net_device *netdev)
|
||||
flags, netdev->name, adapter);
|
||||
if (err) {
|
||||
printk(KERN_ERR "request_irq failed with: %d\n", err);
|
||||
goto err_out_free_hw;
|
||||
goto err_out_free_rxbuf;
|
||||
}
|
||||
|
||||
adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
|
||||
@ -1116,6 +1091,7 @@ static int netxen_nic_open(struct net_device *netdev)
|
||||
if (adapter->set_mtu)
|
||||
adapter->set_mtu(adapter, netdev->mtu);
|
||||
|
||||
adapter->ahw.linkup = 0;
|
||||
mod_timer(&adapter->watchdog_timer, jiffies);
|
||||
|
||||
napi_enable(&adapter->napi);
|
||||
@ -1127,6 +1103,8 @@ static int netxen_nic_open(struct net_device *netdev)
|
||||
|
||||
err_out_free_irq:
|
||||
free_irq(adapter->irq, adapter);
|
||||
err_out_free_rxbuf:
|
||||
netxen_release_rx_buffers(adapter);
|
||||
err_out_free_hw:
|
||||
netxen_free_hw_resources(adapter);
|
||||
err_out_free_sw:
|
||||
@ -1152,10 +1130,8 @@ static int netxen_nic_close(struct net_device *netdev)
|
||||
|
||||
netxen_release_tx_buffers(adapter);
|
||||
|
||||
if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
|
||||
FLUSH_SCHEDULED_WORK();
|
||||
del_timer_sync(&adapter->watchdog_timer);
|
||||
}
|
||||
FLUSH_SCHEDULED_WORK();
|
||||
del_timer_sync(&adapter->watchdog_timer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1458,7 +1434,8 @@ void netxen_watchdog_task(struct work_struct *work)
|
||||
|
||||
netxen_nic_handle_phy_intr(adapter);
|
||||
|
||||
mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
|
||||
if (netif_running(adapter->netdev))
|
||||
mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
|
||||
}
|
||||
|
||||
static void netxen_tx_timeout(struct net_device *netdev)
|
||||
@ -1518,18 +1495,9 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
|
||||
return stats;
|
||||
}
|
||||
|
||||
static inline void
|
||||
netxen_handle_int(struct netxen_adapter *adapter)
|
||||
{
|
||||
netxen_nic_disable_int(adapter);
|
||||
napi_schedule(&adapter->napi);
|
||||
}
|
||||
|
||||
static irqreturn_t netxen_intr(int irq, void *data)
|
||||
{
|
||||
struct netxen_adapter *adapter = data;
|
||||
u32 our_int = 0;
|
||||
|
||||
u32 status = 0;
|
||||
|
||||
status = adapter->pci_read_immediate(adapter, ISR_INT_VECTOR);
|
||||
@ -1544,22 +1512,32 @@ static irqreturn_t netxen_intr(int irq, void *data)
|
||||
if (!ISR_LEGACY_INT_TRIGGERED(status))
|
||||
return IRQ_NONE;
|
||||
|
||||
} else if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
|
||||
} else {
|
||||
unsigned long our_int = 0;
|
||||
|
||||
our_int = adapter->pci_read_normalize(adapter, CRB_INT_VECTOR);
|
||||
|
||||
/* not our interrupt */
|
||||
if ((our_int & (0x80 << adapter->portnum)) == 0)
|
||||
if (!test_and_clear_bit((7 + adapter->portnum), &our_int))
|
||||
return IRQ_NONE;
|
||||
|
||||
if (adapter->intr_scheme == INTR_SCHEME_PERPORT) {
|
||||
/* claim interrupt */
|
||||
adapter->pci_write_normalize(adapter,
|
||||
CRB_INT_VECTOR,
|
||||
our_int & ~((u32)(0x80 << adapter->portnum)));
|
||||
}
|
||||
/* claim interrupt */
|
||||
adapter->pci_write_normalize(adapter,
|
||||
CRB_INT_VECTOR, (our_int & 0xffffffff));
|
||||
}
|
||||
|
||||
netxen_handle_int(adapter);
|
||||
/* clear interrupt */
|
||||
if (adapter->fw_major < 4)
|
||||
netxen_nic_disable_int(adapter);
|
||||
|
||||
adapter->pci_write_immediate(adapter,
|
||||
adapter->legacy_intr.tgt_status_reg,
|
||||
0xffffffff);
|
||||
/* read twice to ensure write is flushed */
|
||||
adapter->pci_read_immediate(adapter, ISR_INT_VECTOR);
|
||||
adapter->pci_read_immediate(adapter, ISR_INT_VECTOR);
|
||||
|
||||
napi_schedule(&adapter->napi);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -1568,7 +1546,11 @@ static irqreturn_t netxen_msi_intr(int irq, void *data)
|
||||
{
|
||||
struct netxen_adapter *adapter = data;
|
||||
|
||||
netxen_handle_int(adapter);
|
||||
/* clear interrupt */
|
||||
adapter->pci_write_immediate(adapter,
|
||||
msi_tgt_status[adapter->ahw.pci_func], 0xffffffff);
|
||||
|
||||
napi_schedule(&adapter->napi);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -125,6 +125,8 @@
|
||||
#define CRB_SW_INT_MASK_2 NETXEN_NIC_REG(0x1e4)
|
||||
#define CRB_SW_INT_MASK_3 NETXEN_NIC_REG(0x1e8)
|
||||
|
||||
#define CRB_MAC_BLOCK_START NETXEN_CAM_RAM(0x1c0)
|
||||
|
||||
/*
|
||||
* capabilities register, can be used to selectively enable/disable features
|
||||
* for backward compability
|
||||
|
@ -46,7 +46,6 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -61,7 +61,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/list.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/timer.h>
|
||||
|
@ -20,7 +20,6 @@
|
||||
* the file called "COPYING".
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/etherdevice.h>
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
@ -666,11 +665,16 @@ static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port)
|
||||
|
||||
if (hw->chip_id != CHIP_ID_YUKON_EC) {
|
||||
if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
|
||||
ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
|
||||
/* select page 2 to access MAC control register */
|
||||
gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2);
|
||||
|
||||
ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
|
||||
/* enable Power Down */
|
||||
ctrl |= PHY_M_PC_POW_D_ENA;
|
||||
gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
|
||||
|
||||
/* set page register back to 0 */
|
||||
gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0);
|
||||
}
|
||||
|
||||
/* set IEEE compatible Power Down Mode (dev. #4.99) */
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
@ -66,8 +66,8 @@
|
||||
|
||||
#define DRV_MODULE_NAME "tg3"
|
||||
#define PFX DRV_MODULE_NAME ": "
|
||||
#define DRV_MODULE_VERSION "3.93"
|
||||
#define DRV_MODULE_RELDATE "May 22, 2008"
|
||||
#define DRV_MODULE_VERSION "3.94"
|
||||
#define DRV_MODULE_RELDATE "August 14, 2008"
|
||||
|
||||
#define TG3_DEF_MAC_MODE 0
|
||||
#define TG3_DEF_RX_MODE 0
|
||||
@ -536,6 +536,7 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum)
|
||||
return 0;
|
||||
|
||||
switch (locknum) {
|
||||
case TG3_APE_LOCK_GRC:
|
||||
case TG3_APE_LOCK_MEM:
|
||||
break;
|
||||
default:
|
||||
@ -573,6 +574,7 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum)
|
||||
return;
|
||||
|
||||
switch (locknum) {
|
||||
case TG3_APE_LOCK_GRC:
|
||||
case TG3_APE_LOCK_MEM:
|
||||
break;
|
||||
default:
|
||||
@ -1017,16 +1019,44 @@ static void tg3_mdio_fini(struct tg3 *tp)
|
||||
}
|
||||
}
|
||||
|
||||
/* tp->lock is held. */
|
||||
static inline void tg3_generate_fw_event(struct tg3 *tp)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = tr32(GRC_RX_CPU_EVENT);
|
||||
val |= GRC_RX_CPU_DRIVER_EVENT;
|
||||
tw32_f(GRC_RX_CPU_EVENT, val);
|
||||
|
||||
tp->last_event_jiffies = jiffies;
|
||||
}
|
||||
|
||||
#define TG3_FW_EVENT_TIMEOUT_USEC 2500
|
||||
|
||||
/* tp->lock is held. */
|
||||
static void tg3_wait_for_event_ack(struct tg3 *tp)
|
||||
{
|
||||
int i;
|
||||
unsigned int delay_cnt;
|
||||
long time_remain;
|
||||
|
||||
/* Wait for up to 2.5 milliseconds */
|
||||
for (i = 0; i < 250000; i++) {
|
||||
/* If enough time has passed, no wait is necessary. */
|
||||
time_remain = (long)(tp->last_event_jiffies + 1 +
|
||||
usecs_to_jiffies(TG3_FW_EVENT_TIMEOUT_USEC)) -
|
||||
(long)jiffies;
|
||||
if (time_remain < 0)
|
||||
return;
|
||||
|
||||
/* Check if we can shorten the wait time. */
|
||||
delay_cnt = jiffies_to_usecs(time_remain);
|
||||
if (delay_cnt > TG3_FW_EVENT_TIMEOUT_USEC)
|
||||
delay_cnt = TG3_FW_EVENT_TIMEOUT_USEC;
|
||||
delay_cnt = (delay_cnt >> 3) + 1;
|
||||
|
||||
for (i = 0; i < delay_cnt; i++) {
|
||||
if (!(tr32(GRC_RX_CPU_EVENT) & GRC_RX_CPU_DRIVER_EVENT))
|
||||
break;
|
||||
udelay(10);
|
||||
udelay(8);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1075,9 +1105,7 @@ static void tg3_ump_link_report(struct tg3 *tp)
|
||||
val = 0;
|
||||
tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val);
|
||||
|
||||
val = tr32(GRC_RX_CPU_EVENT);
|
||||
val |= GRC_RX_CPU_DRIVER_EVENT;
|
||||
tw32_f(GRC_RX_CPU_EVENT, val);
|
||||
tg3_generate_fw_event(tp);
|
||||
}
|
||||
|
||||
static void tg3_link_report(struct tg3 *tp)
|
||||
@ -2124,6 +2152,13 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
|
||||
(tp->tg3_flags & TG3_FLAG_WOL_ENABLE))
|
||||
mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE;
|
||||
|
||||
if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
|
||||
mac_mode |= tp->mac_mode &
|
||||
(MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN);
|
||||
if (mac_mode & MAC_MODE_APE_TX_EN)
|
||||
mac_mode |= MAC_MODE_TDE_ENABLE;
|
||||
}
|
||||
|
||||
tw32_f(MAC_MODE, mac_mode);
|
||||
udelay(100);
|
||||
|
||||
@ -5493,7 +5528,7 @@ static void tg3_ape_send_event(struct tg3 *tp, u32 event)
|
||||
return;
|
||||
|
||||
apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
|
||||
if (apedata != APE_FW_STATUS_READY)
|
||||
if (!(apedata & APE_FW_STATUS_READY))
|
||||
return;
|
||||
|
||||
/* Wait for up to 1 millisecond for APE to service previous event. */
|
||||
@ -5760,6 +5795,8 @@ static int tg3_chip_reset(struct tg3 *tp)
|
||||
|
||||
tg3_mdio_stop(tp);
|
||||
|
||||
tg3_ape_lock(tp, TG3_APE_LOCK_GRC);
|
||||
|
||||
/* No matching tg3_nvram_unlock() after this because
|
||||
* chip reset below will undo the nvram lock.
|
||||
*/
|
||||
@ -5908,12 +5945,19 @@ static int tg3_chip_reset(struct tg3 *tp)
|
||||
} else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
|
||||
tp->mac_mode = MAC_MODE_PORT_MODE_GMII;
|
||||
tw32_f(MAC_MODE, tp->mac_mode);
|
||||
} else if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
|
||||
tp->mac_mode &= (MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN);
|
||||
if (tp->mac_mode & MAC_MODE_APE_TX_EN)
|
||||
tp->mac_mode |= MAC_MODE_TDE_ENABLE;
|
||||
tw32_f(MAC_MODE, tp->mac_mode);
|
||||
} else
|
||||
tw32_f(MAC_MODE, 0);
|
||||
udelay(40);
|
||||
|
||||
tg3_mdio_start(tp);
|
||||
|
||||
tg3_ape_unlock(tp, TG3_APE_LOCK_GRC);
|
||||
|
||||
err = tg3_poll_fw(tp);
|
||||
if (err)
|
||||
return err;
|
||||
@ -5935,6 +5979,7 @@ static int tg3_chip_reset(struct tg3 *tp)
|
||||
tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
|
||||
if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
|
||||
tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
|
||||
tp->last_event_jiffies = jiffies;
|
||||
if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
|
||||
tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE;
|
||||
}
|
||||
@ -5948,15 +5993,12 @@ static void tg3_stop_fw(struct tg3 *tp)
|
||||
{
|
||||
if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
|
||||
!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) {
|
||||
u32 val;
|
||||
|
||||
/* Wait for RX cpu to ACK the previous event. */
|
||||
tg3_wait_for_event_ack(tp);
|
||||
|
||||
tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW);
|
||||
val = tr32(GRC_RX_CPU_EVENT);
|
||||
val |= GRC_RX_CPU_DRIVER_EVENT;
|
||||
tw32(GRC_RX_CPU_EVENT, val);
|
||||
|
||||
tg3_generate_fw_event(tp);
|
||||
|
||||
/* Wait for RX cpu to ACK this event. */
|
||||
tg3_wait_for_event_ack(tp);
|
||||
@ -7406,7 +7448,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
|
||||
if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
|
||||
tp->mac_mode &= MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
|
||||
else
|
||||
tp->mac_mode = 0;
|
||||
tp->mac_mode |= MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
|
||||
MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
|
||||
if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
|
||||
!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
|
||||
@ -7840,9 +7886,8 @@ static void tg3_timer(unsigned long __opaque)
|
||||
* resets.
|
||||
*/
|
||||
if (!--tp->asf_counter) {
|
||||
if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
|
||||
u32 val;
|
||||
|
||||
if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
|
||||
!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) {
|
||||
tg3_wait_for_event_ack(tp);
|
||||
|
||||
tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX,
|
||||
@ -7850,9 +7895,8 @@ static void tg3_timer(unsigned long __opaque)
|
||||
tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
|
||||
/* 5 seconds timeout */
|
||||
tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
|
||||
val = tr32(GRC_RX_CPU_EVENT);
|
||||
val |= GRC_RX_CPU_DRIVER_EVENT;
|
||||
tw32_f(GRC_RX_CPU_EVENT, val);
|
||||
|
||||
tg3_generate_fw_event(tp);
|
||||
}
|
||||
tp->asf_counter = tp->asf_multiplier;
|
||||
}
|
||||
@ -8422,6 +8466,11 @@ static inline unsigned long get_stat64(tg3_stat64_t *val)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline u64 get_estat64(tg3_stat64_t *val)
|
||||
{
|
||||
return ((u64)val->high << 32) | ((u64)val->low);
|
||||
}
|
||||
|
||||
static unsigned long calc_crc_errors(struct tg3 *tp)
|
||||
{
|
||||
struct tg3_hw_stats *hw_stats = tp->hw_stats;
|
||||
@ -8450,7 +8499,7 @@ static unsigned long calc_crc_errors(struct tg3 *tp)
|
||||
|
||||
#define ESTAT_ADD(member) \
|
||||
estats->member = old_estats->member + \
|
||||
get_stat64(&hw_stats->member)
|
||||
get_estat64(&hw_stats->member)
|
||||
|
||||
static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *tp)
|
||||
{
|
||||
@ -12416,6 +12465,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
|
||||
tp->misc_host_ctrl);
|
||||
}
|
||||
|
||||
/* Preserve the APE MAC_MODE bits */
|
||||
if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
|
||||
tp->mac_mode = tr32(MAC_MODE) |
|
||||
MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
|
||||
else
|
||||
tp->mac_mode = TG3_DEF_MAC_MODE;
|
||||
|
||||
/* these are limited to 10/100 only */
|
||||
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
|
||||
(grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) ||
|
||||
@ -13275,7 +13331,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
|
||||
tp->pdev = pdev;
|
||||
tp->dev = dev;
|
||||
tp->pm_cap = pm_cap;
|
||||
tp->mac_mode = TG3_DEF_MAC_MODE;
|
||||
tp->rx_mode = TG3_DEF_RX_MODE;
|
||||
tp->tx_mode = TG3_DEF_TX_MODE;
|
||||
|
||||
|
@ -325,6 +325,8 @@
|
||||
#define MAC_MODE_TDE_ENABLE 0x00200000
|
||||
#define MAC_MODE_RDE_ENABLE 0x00400000
|
||||
#define MAC_MODE_FHDE_ENABLE 0x00800000
|
||||
#define MAC_MODE_APE_RX_EN 0x08000000
|
||||
#define MAC_MODE_APE_TX_EN 0x10000000
|
||||
#define MAC_STATUS 0x00000404
|
||||
#define MAC_STATUS_PCS_SYNCED 0x00000001
|
||||
#define MAC_STATUS_SIGNAL_DET 0x00000002
|
||||
@ -1889,6 +1891,7 @@
|
||||
#define APE_EVENT_STATUS_EVENT_PENDING 0x80000000
|
||||
|
||||
/* APE convenience enumerations. */
|
||||
#define TG3_APE_LOCK_GRC 1
|
||||
#define TG3_APE_LOCK_MEM 4
|
||||
|
||||
#define TG3_EEPROM_SB_F1R2_MBA_OFF 0x10
|
||||
@ -2429,7 +2432,10 @@ struct tg3 {
|
||||
struct tg3_ethtool_stats estats;
|
||||
struct tg3_ethtool_stats estats_prev;
|
||||
|
||||
union {
|
||||
unsigned long phy_crc_errors;
|
||||
unsigned long last_event_jiffies;
|
||||
};
|
||||
|
||||
u32 rx_offset;
|
||||
u32 tg3_flags;
|
||||
|
@ -360,8 +360,8 @@ TLan_GetSKB( const struct tlan_list_tag *tag)
|
||||
{
|
||||
unsigned long addr;
|
||||
|
||||
addr = tag->buffer[8].address;
|
||||
addr |= (tag->buffer[9].address << 16) << 16;
|
||||
addr = tag->buffer[9].address;
|
||||
addr |= (tag->buffer[8].address << 16) << 16;
|
||||
return (struct sk_buff *) addr;
|
||||
}
|
||||
|
||||
@ -1984,7 +1984,6 @@ static void TLan_ResetLists( struct net_device *dev )
|
||||
TLanList *list;
|
||||
dma_addr_t list_phys;
|
||||
struct sk_buff *skb;
|
||||
void *t = NULL;
|
||||
|
||||
priv->txHead = 0;
|
||||
priv->txTail = 0;
|
||||
@ -2022,7 +2021,8 @@ static void TLan_ResetLists( struct net_device *dev )
|
||||
}
|
||||
|
||||
skb_reserve( skb, NET_IP_ALIGN );
|
||||
list->buffer[0].address = pci_map_single(priv->pciDev, t,
|
||||
list->buffer[0].address = pci_map_single(priv->pciDev,
|
||||
skb->data,
|
||||
TLAN_MAX_FRAME_SIZE,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
TLan_StoreSKB(list, skb);
|
||||
|
@ -358,6 +358,66 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
|
||||
return mask;
|
||||
}
|
||||
|
||||
/* prepad is the amount to reserve at front. len is length after that.
|
||||
* linear is a hint as to how much to copy (usually headers). */
|
||||
static struct sk_buff *tun_alloc_skb(size_t prepad, size_t len, size_t linear,
|
||||
gfp_t gfp)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
unsigned int i;
|
||||
|
||||
skb = alloc_skb(prepad + len, gfp|__GFP_NOWARN);
|
||||
if (skb) {
|
||||
skb_reserve(skb, prepad);
|
||||
skb_put(skb, len);
|
||||
return skb;
|
||||
}
|
||||
|
||||
/* Under a page? Don't bother with paged skb. */
|
||||
if (prepad + len < PAGE_SIZE)
|
||||
return NULL;
|
||||
|
||||
/* Start with a normal skb, and add pages. */
|
||||
skb = alloc_skb(prepad + linear, gfp);
|
||||
if (!skb)
|
||||
return NULL;
|
||||
|
||||
skb_reserve(skb, prepad);
|
||||
skb_put(skb, linear);
|
||||
|
||||
len -= linear;
|
||||
|
||||
for (i = 0; i < MAX_SKB_FRAGS; i++) {
|
||||
skb_frag_t *f = &skb_shinfo(skb)->frags[i];
|
||||
|
||||
f->page = alloc_page(gfp|__GFP_ZERO);
|
||||
if (!f->page)
|
||||
break;
|
||||
|
||||
f->page_offset = 0;
|
||||
f->size = PAGE_SIZE;
|
||||
|
||||
skb->data_len += PAGE_SIZE;
|
||||
skb->len += PAGE_SIZE;
|
||||
skb->truesize += PAGE_SIZE;
|
||||
skb_shinfo(skb)->nr_frags++;
|
||||
|
||||
if (len < PAGE_SIZE) {
|
||||
len = 0;
|
||||
break;
|
||||
}
|
||||
len -= PAGE_SIZE;
|
||||
}
|
||||
|
||||
/* Too large, or alloc fail? */
|
||||
if (unlikely(len)) {
|
||||
kfree_skb(skb);
|
||||
skb = NULL;
|
||||
}
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
/* Get packet from user space buffer */
|
||||
static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv, size_t count)
|
||||
{
|
||||
@ -391,14 +451,12 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!(skb = alloc_skb(len + align, GFP_KERNEL))) {
|
||||
if (!(skb = tun_alloc_skb(align, len, gso.hdr_len, GFP_KERNEL))) {
|
||||
tun->dev->stats.rx_dropped++;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (align)
|
||||
skb_reserve(skb, align);
|
||||
if (memcpy_fromiovec(skb_put(skb, len), iv, len)) {
|
||||
if (skb_copy_datagram_from_iovec(skb, 0, iv, len)) {
|
||||
tun->dev->stats.rx_dropped++;
|
||||
kfree_skb(skb);
|
||||
return -EFAULT;
|
||||
@ -748,6 +806,36 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr)
|
||||
{
|
||||
struct tun_struct *tun = file->private_data;
|
||||
|
||||
if (!tun)
|
||||
return -EBADFD;
|
||||
|
||||
DBG(KERN_INFO "%s: tun_get_iff\n", tun->dev->name);
|
||||
|
||||
strcpy(ifr->ifr_name, tun->dev->name);
|
||||
|
||||
ifr->ifr_flags = 0;
|
||||
|
||||
if (ifr->ifr_flags & TUN_TUN_DEV)
|
||||
ifr->ifr_flags |= IFF_TUN;
|
||||
else
|
||||
ifr->ifr_flags |= IFF_TAP;
|
||||
|
||||
if (tun->flags & TUN_NO_PI)
|
||||
ifr->ifr_flags |= IFF_NO_PI;
|
||||
|
||||
if (tun->flags & TUN_ONE_QUEUE)
|
||||
ifr->ifr_flags |= IFF_ONE_QUEUE;
|
||||
|
||||
if (tun->flags & TUN_VNET_HDR)
|
||||
ifr->ifr_flags |= IFF_VNET_HDR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is like a cut-down ethtool ops, except done via tun fd so no
|
||||
* privs required. */
|
||||
static int set_offload(struct net_device *dev, unsigned long arg)
|
||||
@ -833,6 +921,15 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
|
||||
DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd);
|
||||
|
||||
switch (cmd) {
|
||||
case TUNGETIFF:
|
||||
ret = tun_get_iff(current->nsproxy->net_ns, file, &ifr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (copy_to_user(argp, &ifr, sizeof(ifr)))
|
||||
return -EFAULT;
|
||||
break;
|
||||
|
||||
case TUNSETNOCSUM:
|
||||
/* Disable/Enable checksum */
|
||||
if (arg)
|
||||
|
@ -128,7 +128,6 @@ static const int multicast_filter_limit = 32;
|
||||
#include <asm/io.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/in6.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include "typhoon.h"
|
||||
|
@ -154,17 +154,6 @@ config USB_NET_AX8817X
|
||||
This driver creates an interface named "ethX", where X depends on
|
||||
what other networking devices you have in use.
|
||||
|
||||
config USB_HSO
|
||||
tristate "Option USB High Speed Mobile Devices"
|
||||
depends on USB && RFKILL
|
||||
default n
|
||||
help
|
||||
Choose this option if you have an Option HSDPA/HSUPA card.
|
||||
These cards support downlink speeds of 7.2Mbps or greater.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called hso.
|
||||
|
||||
config USB_NET_CDCETHER
|
||||
tristate "CDC Ethernet support (smart devices such as cable modems)"
|
||||
depends on USB_USBNET
|
||||
@ -337,5 +326,15 @@ config USB_NET_ZAURUS
|
||||
really need this non-conformant variant of CDC Ethernet (or in
|
||||
some cases CDC MDLM) protocol, not "g_ether".
|
||||
|
||||
config USB_HSO
|
||||
tristate "Option USB High Speed Mobile Devices"
|
||||
depends on USB && RFKILL
|
||||
default n
|
||||
help
|
||||
Choose this option if you have an Option HSDPA/HSUPA card.
|
||||
These cards support downlink speeds of 7.2Mbps or greater.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called hso.
|
||||
|
||||
endmenu
|
||||
|
@ -102,8 +102,12 @@
|
||||
|
||||
#define MAX_RX_URBS 2
|
||||
|
||||
#define get_serial_by_tty(x) \
|
||||
(x ? (struct hso_serial *)x->driver_data : NULL)
|
||||
static inline struct hso_serial *get_serial_by_tty(struct tty_struct *tty)
|
||||
{
|
||||
if (tty)
|
||||
return tty->driver_data;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Debugging functions */
|
||||
@ -294,24 +298,25 @@ static int hso_get_activity(struct hso_device *hso_dev);
|
||||
|
||||
/* #define DEBUG */
|
||||
|
||||
#define dev2net(x) (x->port_data.dev_net)
|
||||
#define dev2ser(x) (x->port_data.dev_serial)
|
||||
static inline struct hso_net *dev2net(struct hso_device *hso_dev)
|
||||
{
|
||||
return hso_dev->port_data.dev_net;
|
||||
}
|
||||
|
||||
static inline struct hso_serial *dev2ser(struct hso_device *hso_dev)
|
||||
{
|
||||
return hso_dev->port_data.dev_serial;
|
||||
}
|
||||
|
||||
/* Debugging functions */
|
||||
#ifdef DEBUG
|
||||
static void dbg_dump(int line_count, const char *func_name, unsigned char *buf,
|
||||
unsigned int len)
|
||||
{
|
||||
u8 i = 0;
|
||||
static char name[255];
|
||||
|
||||
printk(KERN_DEBUG "[%d:%s]: len %d", line_count, func_name, len);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (!(i % 16))
|
||||
printk("\n 0x%03x: ", i);
|
||||
printk("%02x ", (unsigned char)buf[i]);
|
||||
}
|
||||
printk("\n");
|
||||
sprintf(name, "hso[%d:%s]", line_count, func_name);
|
||||
print_hex_dump_bytes(name, DUMP_PREFIX_NONE, buf, len);
|
||||
}
|
||||
|
||||
#define DUMP(buf_, len_) \
|
||||
@ -528,13 +533,12 @@ static struct hso_serial *get_serial_by_shared_int_and_type(
|
||||
|
||||
static struct hso_serial *get_serial_by_index(unsigned index)
|
||||
{
|
||||
struct hso_serial *serial;
|
||||
struct hso_serial *serial = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
if (!serial_table[index])
|
||||
return NULL;
|
||||
spin_lock_irqsave(&serial_table_lock, flags);
|
||||
serial = dev2ser(serial_table[index]);
|
||||
if (serial_table[index])
|
||||
serial = dev2ser(serial_table[index]);
|
||||
spin_unlock_irqrestore(&serial_table_lock, flags);
|
||||
|
||||
return serial;
|
||||
@ -561,6 +565,7 @@ static int get_free_serial_index(void)
|
||||
static void set_serial_by_index(unsigned index, struct hso_serial *serial)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&serial_table_lock, flags);
|
||||
if (serial)
|
||||
serial_table[index] = serial->parent;
|
||||
@ -569,7 +574,7 @@ static void set_serial_by_index(unsigned index, struct hso_serial *serial)
|
||||
spin_unlock_irqrestore(&serial_table_lock, flags);
|
||||
}
|
||||
|
||||
/* log a meaningfull explanation of an USB status */
|
||||
/* log a meaningful explanation of an USB status */
|
||||
static void log_usb_status(int status, const char *function)
|
||||
{
|
||||
char *explanation;
|
||||
@ -1103,8 +1108,8 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp)
|
||||
/* reset the rts and dtr */
|
||||
/* do the actual close */
|
||||
serial->open_count--;
|
||||
kref_put(&serial->parent->ref, hso_serial_ref_free);
|
||||
if (serial->open_count <= 0) {
|
||||
kref_put(&serial->parent->ref, hso_serial_ref_free);
|
||||
serial->open_count = 0;
|
||||
if (serial->tty) {
|
||||
serial->tty->driver_data = NULL;
|
||||
@ -1467,7 +1472,8 @@ static void hso_std_serial_write_bulk_callback(struct urb *urb)
|
||||
return;
|
||||
}
|
||||
hso_put_activity(serial->parent);
|
||||
tty_wakeup(serial->tty);
|
||||
if (serial->tty)
|
||||
tty_wakeup(serial->tty);
|
||||
hso_kick_transmit(serial);
|
||||
|
||||
D1(" ");
|
||||
@ -1538,7 +1544,8 @@ static void ctrl_callback(struct urb *urb)
|
||||
clear_bit(HSO_SERIAL_FLAG_RX_SENT, &serial->flags);
|
||||
} else {
|
||||
hso_put_activity(serial->parent);
|
||||
tty_wakeup(serial->tty);
|
||||
if (serial->tty)
|
||||
tty_wakeup(serial->tty);
|
||||
/* response to a write command */
|
||||
hso_kick_transmit(serial);
|
||||
}
|
||||
@ -2652,7 +2659,7 @@ static void hso_free_interface(struct usb_interface *interface)
|
||||
hso_stop_net_device(network_table[i]);
|
||||
cancel_work_sync(&network_table[i]->async_put_intf);
|
||||
cancel_work_sync(&network_table[i]->async_get_intf);
|
||||
if(rfk)
|
||||
if (rfk)
|
||||
rfkill_unregister(rfk);
|
||||
hso_free_net_device(network_table[i]);
|
||||
}
|
||||
@ -2723,7 +2730,7 @@ static int hso_mux_submit_intr_urb(struct hso_shared_int *shared_int,
|
||||
}
|
||||
|
||||
/* operations setup of the serial interface */
|
||||
static struct tty_operations hso_serial_ops = {
|
||||
static const struct tty_operations hso_serial_ops = {
|
||||
.open = hso_serial_open,
|
||||
.close = hso_serial_close,
|
||||
.write = hso_serial_write,
|
||||
|
@ -40,7 +40,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/hardirq.h>
|
||||
@ -587,7 +586,6 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
ath5k_stop_hw(sc);
|
||||
|
||||
free_irq(pdev->irq, sc);
|
||||
pci_disable_msi(pdev);
|
||||
pci_save_state(pdev);
|
||||
pci_disable_device(pdev);
|
||||
pci_set_power_state(pdev, PCI_D3hot);
|
||||
@ -616,12 +614,10 @@ ath5k_pci_resume(struct pci_dev *pdev)
|
||||
*/
|
||||
pci_write_config_byte(pdev, 0x41, 0);
|
||||
|
||||
pci_enable_msi(pdev);
|
||||
|
||||
err = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
|
||||
if (err) {
|
||||
ATH5K_ERR(sc, "request_irq failed\n");
|
||||
goto err_msi;
|
||||
goto err_no_irq;
|
||||
}
|
||||
|
||||
err = ath5k_init(sc);
|
||||
@ -642,8 +638,7 @@ ath5k_pci_resume(struct pci_dev *pdev)
|
||||
return 0;
|
||||
err_irq:
|
||||
free_irq(pdev->irq, sc);
|
||||
err_msi:
|
||||
pci_disable_msi(pdev);
|
||||
err_no_irq:
|
||||
pci_disable_device(pdev);
|
||||
return err;
|
||||
}
|
||||
|
@ -5017,7 +5017,11 @@ static void ath9k_hw_spur_mitigate(struct ath_hal *ah,
|
||||
|
||||
for (i = 0; i < 123; i++) {
|
||||
if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
|
||||
if ((abs(cur_vit_mask - bin)) < 75)
|
||||
|
||||
/* workaround for gcc bug #37014 */
|
||||
volatile int tmp = abs(cur_vit_mask - bin);
|
||||
|
||||
if (tmp < 75)
|
||||
mask_amt = 1;
|
||||
else
|
||||
mask_amt = 0;
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/wireless.h>
|
||||
#include <linux/workqueue.h>
|
||||
@ -4615,7 +4614,9 @@ static void b43_sprom_fixup(struct ssb_bus *bus)
|
||||
if (bus->bustype == SSB_BUSTYPE_PCI) {
|
||||
pdev = bus->host_pci;
|
||||
if (IS_PDEV(pdev, BROADCOM, 0x4318, ASUSTEK, 0x100F) ||
|
||||
IS_PDEV(pdev, BROADCOM, 0x4320, DELL, 0x0003) ||
|
||||
IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0015) ||
|
||||
IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0014) ||
|
||||
IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0013))
|
||||
bus->sprom.boardflags_lo &= ~B43_BFL_BTCOEXIST;
|
||||
}
|
||||
|
@ -157,7 +157,6 @@ that only one external action is invoked at a time.
|
||||
#include <linux/stringify.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/acpi.h>
|
||||
|
@ -31,7 +31,6 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "ipw2200.h"
|
||||
#include <linux/version.h>
|
||||
|
||||
|
||||
#ifndef KBUILD_EXTMOD
|
||||
|
@ -26,7 +26,6 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
@ -26,7 +26,6 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
@ -967,7 +966,7 @@ static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel,
|
||||
|
||||
s = iwl4965_get_sub_band(priv, channel);
|
||||
if (s >= EEPROM_TX_POWER_BANDS) {
|
||||
IWL_ERROR("Tx Power can not find channel %d ", channel);
|
||||
IWL_ERROR("Tx Power can not find channel %d\n", channel);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
@ -29,7 +29,6 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
@ -28,7 +28,6 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
struct iwl_priv; /* FIXME: remove */
|
||||
|
@ -63,7 +63,6 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <net/mac80211.h>
|
||||
@ -146,7 +145,7 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv)
|
||||
{
|
||||
u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
|
||||
if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) {
|
||||
IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp);
|
||||
IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x\n", gp);
|
||||
return -ENOENT;
|
||||
}
|
||||
return 0;
|
||||
@ -227,7 +226,7 @@ int iwl_eeprom_init(struct iwl_priv *priv)
|
||||
|
||||
ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv);
|
||||
if (ret < 0) {
|
||||
IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp);
|
||||
IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x\n", gp);
|
||||
ret = -ENOENT;
|
||||
goto err;
|
||||
}
|
||||
@ -254,7 +253,7 @@ int iwl_eeprom_init(struct iwl_priv *priv)
|
||||
}
|
||||
|
||||
if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) {
|
||||
IWL_ERROR("Time out reading EEPROM[%d]", addr);
|
||||
IWL_ERROR("Time out reading EEPROM[%d]\n", addr);
|
||||
ret = -ETIMEDOUT;
|
||||
goto done;
|
||||
}
|
||||
|
@ -28,7 +28,6 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-dev.h" /* FIXME: remove */
|
||||
|
@ -29,7 +29,6 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <net/mac80211.h>
|
||||
|
@ -207,7 +207,7 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
|
||||
case WLAN_HT_CAP_MIMO_PS_DISABLED:
|
||||
break;
|
||||
default:
|
||||
IWL_WARNING("Invalid MIMO PS mode %d", mimo_ps_mode);
|
||||
IWL_WARNING("Invalid MIMO PS mode %d\n", mimo_ps_mode);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -969,7 +969,7 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
|
||||
return priv->hw_params.bcast_sta_id;
|
||||
|
||||
default:
|
||||
IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode);
|
||||
IWL_WARNING("Unknown mode of operation: %d\n", priv->iw_mode);
|
||||
return priv->hw_params.bcast_sta_id;
|
||||
}
|
||||
}
|
||||
|
@ -493,7 +493,7 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
|
||||
/* Alloc keep-warm buffer */
|
||||
ret = iwl_kw_alloc(priv);
|
||||
if (ret) {
|
||||
IWL_ERROR("Keep Warm allocation failed");
|
||||
IWL_ERROR("Keep Warm allocation failed\n");
|
||||
goto error_kw;
|
||||
}
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
@ -1463,7 +1463,7 @@ void iwl_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
|
||||
|
||||
if (scd_flow >= priv->hw_params.max_txq_num) {
|
||||
IWL_ERROR("BUG_ON scd_flow is bigger than number of queues");
|
||||
IWL_ERROR("BUG_ON scd_flow is bigger than number of queues\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,6 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
@ -1558,7 +1557,7 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv)
|
||||
BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE);
|
||||
|
||||
if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) {
|
||||
IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp);
|
||||
IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x\n", gp);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@ -1583,7 +1582,7 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv)
|
||||
}
|
||||
|
||||
if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) {
|
||||
IWL_ERROR("Time out reading EEPROM[%d]", addr);
|
||||
IWL_ERROR("Time out reading EEPROM[%d]\n", addr);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
|
||||
@ -2507,7 +2506,7 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
|
||||
return priv->hw_setting.bcast_sta_id;
|
||||
|
||||
default:
|
||||
IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode);
|
||||
IWL_WARNING("Unknown mode of operation: %d\n", priv->iw_mode);
|
||||
return priv->hw_setting.bcast_sta_id;
|
||||
}
|
||||
}
|
||||
|
@ -413,12 +413,12 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
|
||||
last_addr = range->end_addr;
|
||||
__skb_unlink(entry, &priv->tx_queue);
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
priv->tx_stats[skb_get_queue_mapping(skb)].len--;
|
||||
entry_hdr = (struct p54_control_hdr *) entry->data;
|
||||
entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data;
|
||||
if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0)
|
||||
pad = entry_data->align[0];
|
||||
|
||||
priv->tx_stats[entry_data->hw_queue - 4].len--;
|
||||
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
|
||||
if (!(payload->status & 0x01))
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
@ -557,6 +557,7 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
|
||||
struct p54_tx_control_allocdata *txhdr;
|
||||
size_t padding, len;
|
||||
u8 rate;
|
||||
u8 cts_rate = 0x20;
|
||||
|
||||
current_queue = &priv->tx_stats[skb_get_queue_mapping(skb)];
|
||||
if (unlikely(current_queue->len > current_queue->limit))
|
||||
@ -581,28 +582,28 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
|
||||
hdr->type = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? 0 : cpu_to_le16(1);
|
||||
hdr->retry1 = hdr->retry2 = info->control.retry_limit;
|
||||
|
||||
memset(txhdr->wep_key, 0x0, 16);
|
||||
txhdr->padding = 0;
|
||||
txhdr->padding2 = 0;
|
||||
|
||||
/* TODO: add support for alternate retry TX rates */
|
||||
rate = ieee80211_get_tx_rate(dev, info)->hw_value;
|
||||
if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE)
|
||||
if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) {
|
||||
rate |= 0x10;
|
||||
if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
|
||||
cts_rate |= 0x10;
|
||||
}
|
||||
if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
|
||||
rate |= 0x40;
|
||||
else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
|
||||
cts_rate |= ieee80211_get_rts_cts_rate(dev, info)->hw_value;
|
||||
} else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
|
||||
rate |= 0x20;
|
||||
cts_rate |= ieee80211_get_rts_cts_rate(dev, info)->hw_value;
|
||||
}
|
||||
memset(txhdr->rateset, rate, 8);
|
||||
txhdr->wep_key_present = 0;
|
||||
txhdr->wep_key_len = 0;
|
||||
txhdr->frame_type = cpu_to_le32(skb_get_queue_mapping(skb) + 4);
|
||||
txhdr->magic4 = 0;
|
||||
txhdr->antenna = (info->antenna_sel_tx == 0) ?
|
||||
txhdr->key_type = 0;
|
||||
txhdr->key_len = 0;
|
||||
txhdr->hw_queue = skb_get_queue_mapping(skb) + 4;
|
||||
txhdr->tx_antenna = (info->antenna_sel_tx == 0) ?
|
||||
2 : info->antenna_sel_tx - 1;
|
||||
txhdr->output_power = 0x7f; // HW Maximum
|
||||
txhdr->magic5 = (info->flags & IEEE80211_TX_CTL_NO_ACK) ?
|
||||
0 : ((rate > 0x3) ? cpu_to_le32(0x33) : cpu_to_le32(0x23));
|
||||
txhdr->cts_rate = (info->flags & IEEE80211_TX_CTL_NO_ACK) ?
|
||||
0 : cts_rate;
|
||||
if (padding)
|
||||
txhdr->align[0] = padding;
|
||||
|
||||
@ -836,10 +837,21 @@ static int p54_start(struct ieee80211_hw *dev)
|
||||
struct p54_common *priv = dev->priv;
|
||||
int err;
|
||||
|
||||
if (!priv->cached_vdcf) {
|
||||
priv->cached_vdcf = kzalloc(sizeof(struct p54_tx_control_vdcf)+
|
||||
priv->tx_hdr_len + sizeof(struct p54_control_hdr),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!priv->cached_vdcf)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
err = priv->open(dev);
|
||||
if (!err)
|
||||
priv->mode = IEEE80211_IF_TYPE_MNTR;
|
||||
|
||||
p54_init_vdcf(dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1019,15 +1031,6 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
|
||||
dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 +
|
||||
sizeof(struct p54_tx_control_allocdata);
|
||||
|
||||
priv->cached_vdcf = kzalloc(sizeof(struct p54_tx_control_vdcf) +
|
||||
priv->tx_hdr_len + sizeof(struct p54_control_hdr), GFP_KERNEL);
|
||||
|
||||
if (!priv->cached_vdcf) {
|
||||
ieee80211_free_hw(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p54_init_vdcf(dev);
|
||||
mutex_init(&priv->conf_mutex);
|
||||
|
||||
return dev;
|
||||
|
@ -183,16 +183,16 @@ struct p54_frame_sent_hdr {
|
||||
|
||||
struct p54_tx_control_allocdata {
|
||||
u8 rateset[8];
|
||||
u16 padding;
|
||||
u8 wep_key_present;
|
||||
u8 wep_key_len;
|
||||
u8 wep_key[16];
|
||||
__le32 frame_type;
|
||||
u32 padding2;
|
||||
__le16 magic4;
|
||||
u8 antenna;
|
||||
u8 unalloc0[2];
|
||||
u8 key_type;
|
||||
u8 key_len;
|
||||
u8 key[16];
|
||||
u8 hw_queue;
|
||||
u8 unalloc1[9];
|
||||
u8 tx_antenna;
|
||||
u8 output_power;
|
||||
__le32 magic5;
|
||||
u8 cts_rate;
|
||||
u8 unalloc2[3];
|
||||
u8 align[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
@ -109,7 +109,17 @@ static void p54u_rx_cb(struct urb *urb)
|
||||
urb->context = skb;
|
||||
skb_queue_tail(&priv->rx_queue, skb);
|
||||
} else {
|
||||
if (!priv->hw_type)
|
||||
skb_push(skb, sizeof(struct net2280_tx_hdr));
|
||||
|
||||
skb_reset_tail_pointer(skb);
|
||||
skb_trim(skb, 0);
|
||||
if (urb->transfer_buffer != skb_tail_pointer(skb)) {
|
||||
/* this should not happen */
|
||||
WARN_ON(1);
|
||||
urb->transfer_buffer = skb_tail_pointer(skb);
|
||||
}
|
||||
|
||||
skb_queue_tail(&priv->rx_queue, skb);
|
||||
}
|
||||
|
||||
|
@ -173,10 +173,10 @@ struct rxdone_entry_desc {
|
||||
* frame transmission failed due to excessive retries.
|
||||
*/
|
||||
enum txdone_entry_desc_flags {
|
||||
TXDONE_UNKNOWN = 1 << 0,
|
||||
TXDONE_SUCCESS = 1 << 1,
|
||||
TXDONE_FAILURE = 1 << 2,
|
||||
TXDONE_EXCESSIVE_RETRY = 1 << 3,
|
||||
TXDONE_UNKNOWN,
|
||||
TXDONE_SUCCESS,
|
||||
TXDONE_FAILURE,
|
||||
TXDONE_EXCESSIVE_RETRY,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -181,6 +181,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
|
||||
* (Only indirectly by looking at the failed TX counters
|
||||
* in the register).
|
||||
*/
|
||||
txdesc.flags = 0;
|
||||
if (!urb->status)
|
||||
__set_bit(TXDONE_UNKNOWN, &txdesc.flags);
|
||||
else
|
||||
|
@ -40,6 +40,7 @@ static struct usb_device_id rtl8187_table[] __devinitdata = {
|
||||
/* Netgear */
|
||||
{USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187},
|
||||
{USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187},
|
||||
{USB_DEVICE(0x0846, 0x4260), .driver_info = DEVICE_RTL8187B},
|
||||
/* HP */
|
||||
{USB_DEVICE(0x03f0, 0xca02), .driver_info = DEVICE_RTL8187},
|
||||
/* Sitecom */
|
||||
|
@ -1165,15 +1165,19 @@ EXPORT_SYMBOL(ssb_dma_translation);
|
||||
|
||||
int ssb_dma_set_mask(struct ssb_device *dev, u64 mask)
|
||||
{
|
||||
#ifdef CONFIG_SSB_PCIHOST
|
||||
int err;
|
||||
#endif
|
||||
|
||||
switch (dev->bus->bustype) {
|
||||
case SSB_BUSTYPE_PCI:
|
||||
#ifdef CONFIG_SSB_PCIHOST
|
||||
err = pci_set_dma_mask(dev->bus->host_pci, mask);
|
||||
if (err)
|
||||
return err;
|
||||
err = pci_set_consistent_dma_mask(dev->bus->host_pci, mask);
|
||||
return err;
|
||||
#endif
|
||||
case SSB_BUSTYPE_SSB:
|
||||
return dma_set_mask(dev->dev, mask);
|
||||
default:
|
||||
@ -1188,6 +1192,7 @@ void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size,
|
||||
{
|
||||
switch (dev->bus->bustype) {
|
||||
case SSB_BUSTYPE_PCI:
|
||||
#ifdef CONFIG_SSB_PCIHOST
|
||||
if (gfp_flags & GFP_DMA) {
|
||||
/* Workaround: The PCI API does not support passing
|
||||
* a GFP flag. */
|
||||
@ -1195,6 +1200,7 @@ void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size,
|
||||
size, dma_handle, gfp_flags);
|
||||
}
|
||||
return pci_alloc_consistent(dev->bus->host_pci, size, dma_handle);
|
||||
#endif
|
||||
case SSB_BUSTYPE_SSB:
|
||||
return dma_alloc_coherent(dev->dev, size, dma_handle, gfp_flags);
|
||||
default:
|
||||
@ -1210,6 +1216,7 @@ void ssb_dma_free_consistent(struct ssb_device *dev, size_t size,
|
||||
{
|
||||
switch (dev->bus->bustype) {
|
||||
case SSB_BUSTYPE_PCI:
|
||||
#ifdef CONFIG_SSB_PCIHOST
|
||||
if (gfp_flags & GFP_DMA) {
|
||||
/* Workaround: The PCI API does not support passing
|
||||
* a GFP flag. */
|
||||
@ -1220,6 +1227,7 @@ void ssb_dma_free_consistent(struct ssb_device *dev, size_t size,
|
||||
pci_free_consistent(dev->bus->host_pci, size,
|
||||
vaddr, dma_handle);
|
||||
return;
|
||||
#endif
|
||||
case SSB_BUSTYPE_SSB:
|
||||
dma_free_coherent(dev->dev, size, vaddr, dma_handle);
|
||||
return;
|
||||
|
@ -45,6 +45,7 @@
|
||||
#define TUNGETFEATURES _IOR('T', 207, unsigned int)
|
||||
#define TUNSETOFFLOAD _IOW('T', 208, unsigned int)
|
||||
#define TUNSETTXFILTER _IOW('T', 209, unsigned int)
|
||||
#define TUNGETIFF _IOR('T', 210, unsigned int)
|
||||
|
||||
/* TUNSETIFF ifr flags */
|
||||
#define IFF_TUN 0x0001
|
||||
|
@ -1452,6 +1452,10 @@ extern int skb_copy_datagram_iovec(const struct sk_buff *from,
|
||||
extern int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
|
||||
int hlen,
|
||||
struct iovec *iov);
|
||||
extern int skb_copy_datagram_from_iovec(struct sk_buff *skb,
|
||||
int offset,
|
||||
struct iovec *from,
|
||||
int len);
|
||||
extern void skb_free_datagram(struct sock *sk, struct sk_buff *skb);
|
||||
extern int skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
|
||||
unsigned int flags);
|
||||
|
@ -80,7 +80,8 @@ extern struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net,
|
||||
struct net_device *dev,
|
||||
int strict);
|
||||
|
||||
extern int ipv6_dev_get_saddr(struct net_device *dev,
|
||||
extern int ipv6_dev_get_saddr(struct net *net,
|
||||
struct net_device *dev,
|
||||
const struct in6_addr *daddr,
|
||||
unsigned int srcprefs,
|
||||
struct in6_addr *saddr);
|
||||
|
@ -107,6 +107,7 @@ struct rt6_rtnl_dump_arg
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct netlink_callback *cb;
|
||||
struct net *net;
|
||||
};
|
||||
|
||||
extern int rt6_dump_route(struct rt6_info *rt, void *p_arg);
|
||||
|
@ -708,10 +708,7 @@ enum ieee80211_tkip_key_type {
|
||||
* rely on the host system for such buffering. This option is used
|
||||
* to configure the IEEE 802.11 upper layer to buffer broadcast and
|
||||
* multicast frames when there are power saving stations so that
|
||||
* the driver can fetch them with ieee80211_get_buffered_bc(). Note
|
||||
* that not setting this flag works properly only when the
|
||||
* %IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE is also not set because
|
||||
* otherwise the stack will not know when the DTIM beacon was sent.
|
||||
* the driver can fetch them with ieee80211_get_buffered_bc().
|
||||
*
|
||||
* @IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE:
|
||||
* Hardware is not capable of short slot operation on the 2.4 GHz band.
|
||||
@ -1099,10 +1096,8 @@ enum ieee80211_ampdu_mlme_action {
|
||||
* See the section "Frame filtering" for more information.
|
||||
* This callback must be implemented and atomic.
|
||||
*
|
||||
* @set_tim: Set TIM bit. If the hardware/firmware takes care of beacon
|
||||
* generation (that is, %IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE is set)
|
||||
* mac80211 calls this function when a TIM bit must be set or cleared
|
||||
* for a given AID. Must be atomic.
|
||||
* @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit
|
||||
* must be set or cleared for a given AID. Must be atomic.
|
||||
*
|
||||
* @set_key: See the section "Hardware crypto acceleration"
|
||||
* This callback can sleep, and is only called between add_interface
|
||||
|
@ -27,6 +27,7 @@ enum qdisc_state_t
|
||||
{
|
||||
__QDISC_STATE_RUNNING,
|
||||
__QDISC_STATE_SCHED,
|
||||
__QDISC_STATE_DEACTIVATED,
|
||||
};
|
||||
|
||||
struct qdisc_size_table {
|
||||
@ -60,7 +61,6 @@ struct Qdisc
|
||||
struct gnet_stats_basic bstats;
|
||||
struct gnet_stats_queue qstats;
|
||||
struct gnet_stats_rate_est rate_est;
|
||||
struct rcu_head q_rcu;
|
||||
int (*reshape_fail)(struct sk_buff *skb,
|
||||
struct Qdisc *q);
|
||||
|
||||
|
@ -456,7 +456,7 @@ static void __exit bt_exit(void)
|
||||
subsys_initcall(bt_init);
|
||||
module_exit(bt_exit);
|
||||
|
||||
MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
|
||||
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
||||
MODULE_DESCRIPTION("Bluetooth Core ver " VERSION);
|
||||
MODULE_VERSION(VERSION);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -736,7 +736,7 @@ MODULE_PARM_DESC(compress_src, "Compress sources headers");
|
||||
module_param(compress_dst, bool, 0644);
|
||||
MODULE_PARM_DESC(compress_dst, "Compress destination headers");
|
||||
|
||||
MODULE_AUTHOR("David Libault <david.libault@inventel.fr>, Maxim Krasnyansky <maxk@qualcomm.com>");
|
||||
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
||||
MODULE_DESCRIPTION("Bluetooth BNEP ver " VERSION);
|
||||
MODULE_VERSION(VERSION);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -3,8 +3,6 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
||||
@ -12,10 +10,164 @@
|
||||
#undef BT_DBG
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
struct class *bt_class = NULL;
|
||||
EXPORT_SYMBOL_GPL(bt_class);
|
||||
|
||||
static struct workqueue_struct *btaddconn;
|
||||
static struct workqueue_struct *btdelconn;
|
||||
|
||||
static inline char *typetostr(int type)
|
||||
static inline char *link_typetostr(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case ACL_LINK:
|
||||
return "ACL";
|
||||
case SCO_LINK:
|
||||
return "SCO";
|
||||
case ESCO_LINK:
|
||||
return "eSCO";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t show_link_type(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct hci_conn *conn = dev_get_drvdata(dev);
|
||||
return sprintf(buf, "%s\n", link_typetostr(conn->type));
|
||||
}
|
||||
|
||||
static ssize_t show_link_address(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct hci_conn *conn = dev_get_drvdata(dev);
|
||||
bdaddr_t bdaddr;
|
||||
baswap(&bdaddr, &conn->dst);
|
||||
return sprintf(buf, "%s\n", batostr(&bdaddr));
|
||||
}
|
||||
|
||||
static ssize_t show_link_features(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct hci_conn *conn = dev_get_drvdata(dev);
|
||||
|
||||
return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
|
||||
conn->features[0], conn->features[1],
|
||||
conn->features[2], conn->features[3],
|
||||
conn->features[4], conn->features[5],
|
||||
conn->features[6], conn->features[7]);
|
||||
}
|
||||
|
||||
#define LINK_ATTR(_name,_mode,_show,_store) \
|
||||
struct device_attribute link_attr_##_name = __ATTR(_name,_mode,_show,_store)
|
||||
|
||||
static LINK_ATTR(type, S_IRUGO, show_link_type, NULL);
|
||||
static LINK_ATTR(address, S_IRUGO, show_link_address, NULL);
|
||||
static LINK_ATTR(features, S_IRUGO, show_link_features, NULL);
|
||||
|
||||
static struct attribute *bt_link_attrs[] = {
|
||||
&link_attr_type.attr,
|
||||
&link_attr_address.attr,
|
||||
&link_attr_features.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group bt_link_group = {
|
||||
.attrs = bt_link_attrs,
|
||||
};
|
||||
|
||||
static struct attribute_group *bt_link_groups[] = {
|
||||
&bt_link_group,
|
||||
NULL
|
||||
};
|
||||
|
||||
static void bt_link_release(struct device *dev)
|
||||
{
|
||||
void *data = dev_get_drvdata(dev);
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
static struct device_type bt_link = {
|
||||
.name = "link",
|
||||
.groups = bt_link_groups,
|
||||
.release = bt_link_release,
|
||||
};
|
||||
|
||||
static void add_conn(struct work_struct *work)
|
||||
{
|
||||
struct hci_conn *conn = container_of(work, struct hci_conn, work);
|
||||
|
||||
flush_workqueue(btdelconn);
|
||||
|
||||
if (device_add(&conn->dev) < 0) {
|
||||
BT_ERR("Failed to register connection device");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void hci_conn_add_sysfs(struct hci_conn *conn)
|
||||
{
|
||||
struct hci_dev *hdev = conn->hdev;
|
||||
|
||||
BT_DBG("conn %p", conn);
|
||||
|
||||
conn->dev.type = &bt_link;
|
||||
conn->dev.class = bt_class;
|
||||
conn->dev.parent = &hdev->dev;
|
||||
|
||||
snprintf(conn->dev.bus_id, BUS_ID_SIZE, "%s:%d",
|
||||
hdev->name, conn->handle);
|
||||
|
||||
dev_set_drvdata(&conn->dev, conn);
|
||||
|
||||
device_initialize(&conn->dev);
|
||||
|
||||
INIT_WORK(&conn->work, add_conn);
|
||||
|
||||
queue_work(btaddconn, &conn->work);
|
||||
}
|
||||
|
||||
/*
|
||||
* The rfcomm tty device will possibly retain even when conn
|
||||
* is down, and sysfs doesn't support move zombie device,
|
||||
* so we should move the device before conn device is destroyed.
|
||||
*/
|
||||
static int __match_tty(struct device *dev, void *data)
|
||||
{
|
||||
return !strncmp(dev->bus_id, "rfcomm", 6);
|
||||
}
|
||||
|
||||
static void del_conn(struct work_struct *work)
|
||||
{
|
||||
struct hci_conn *conn = container_of(work, struct hci_conn, work);
|
||||
struct hci_dev *hdev = conn->hdev;
|
||||
|
||||
while (1) {
|
||||
struct device *dev;
|
||||
|
||||
dev = device_find_child(&conn->dev, NULL, __match_tty);
|
||||
if (!dev)
|
||||
break;
|
||||
device_move(dev, NULL);
|
||||
put_device(dev);
|
||||
}
|
||||
|
||||
device_del(&conn->dev);
|
||||
put_device(&conn->dev);
|
||||
hci_dev_put(hdev);
|
||||
}
|
||||
|
||||
void hci_conn_del_sysfs(struct hci_conn *conn)
|
||||
{
|
||||
BT_DBG("conn %p", conn);
|
||||
|
||||
if (!device_is_registered(&conn->dev))
|
||||
return;
|
||||
|
||||
INIT_WORK(&conn->work, del_conn);
|
||||
|
||||
queue_work(btdelconn, &conn->work);
|
||||
}
|
||||
|
||||
static inline char *host_typetostr(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case HCI_VIRTUAL:
|
||||
@ -40,7 +192,7 @@ static inline char *typetostr(int type)
|
||||
static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct hci_dev *hdev = dev_get_drvdata(dev);
|
||||
return sprintf(buf, "%s\n", typetostr(hdev->type));
|
||||
return sprintf(buf, "%s\n", host_typetostr(hdev->type));
|
||||
}
|
||||
|
||||
static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
@ -221,183 +373,62 @@ static DEVICE_ATTR(sniff_max_interval, S_IRUGO | S_IWUSR,
|
||||
static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR,
|
||||
show_sniff_min_interval, store_sniff_min_interval);
|
||||
|
||||
static struct device_attribute *bt_attrs[] = {
|
||||
&dev_attr_type,
|
||||
&dev_attr_name,
|
||||
&dev_attr_class,
|
||||
&dev_attr_address,
|
||||
&dev_attr_features,
|
||||
&dev_attr_manufacturer,
|
||||
&dev_attr_hci_version,
|
||||
&dev_attr_hci_revision,
|
||||
&dev_attr_inquiry_cache,
|
||||
&dev_attr_idle_timeout,
|
||||
&dev_attr_sniff_max_interval,
|
||||
&dev_attr_sniff_min_interval,
|
||||
static struct attribute *bt_host_attrs[] = {
|
||||
&dev_attr_type.attr,
|
||||
&dev_attr_name.attr,
|
||||
&dev_attr_class.attr,
|
||||
&dev_attr_address.attr,
|
||||
&dev_attr_features.attr,
|
||||
&dev_attr_manufacturer.attr,
|
||||
&dev_attr_hci_version.attr,
|
||||
&dev_attr_hci_revision.attr,
|
||||
&dev_attr_inquiry_cache.attr,
|
||||
&dev_attr_idle_timeout.attr,
|
||||
&dev_attr_sniff_max_interval.attr,
|
||||
&dev_attr_sniff_min_interval.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static ssize_t show_conn_type(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct hci_conn *conn = dev_get_drvdata(dev);
|
||||
return sprintf(buf, "%s\n", conn->type == ACL_LINK ? "ACL" : "SCO");
|
||||
}
|
||||
static struct attribute_group bt_host_group = {
|
||||
.attrs = bt_host_attrs,
|
||||
};
|
||||
|
||||
static ssize_t show_conn_address(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct hci_conn *conn = dev_get_drvdata(dev);
|
||||
bdaddr_t bdaddr;
|
||||
baswap(&bdaddr, &conn->dst);
|
||||
return sprintf(buf, "%s\n", batostr(&bdaddr));
|
||||
}
|
||||
|
||||
static ssize_t show_conn_features(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct hci_conn *conn = dev_get_drvdata(dev);
|
||||
|
||||
return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
|
||||
conn->features[0], conn->features[1],
|
||||
conn->features[2], conn->features[3],
|
||||
conn->features[4], conn->features[5],
|
||||
conn->features[6], conn->features[7]);
|
||||
}
|
||||
|
||||
#define CONN_ATTR(_name,_mode,_show,_store) \
|
||||
struct device_attribute conn_attr_##_name = __ATTR(_name,_mode,_show,_store)
|
||||
|
||||
static CONN_ATTR(type, S_IRUGO, show_conn_type, NULL);
|
||||
static CONN_ATTR(address, S_IRUGO, show_conn_address, NULL);
|
||||
static CONN_ATTR(features, S_IRUGO, show_conn_features, NULL);
|
||||
|
||||
static struct device_attribute *conn_attrs[] = {
|
||||
&conn_attr_type,
|
||||
&conn_attr_address,
|
||||
&conn_attr_features,
|
||||
static struct attribute_group *bt_host_groups[] = {
|
||||
&bt_host_group,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct class *bt_class = NULL;
|
||||
EXPORT_SYMBOL_GPL(bt_class);
|
||||
|
||||
static struct bus_type bt_bus = {
|
||||
.name = "bluetooth",
|
||||
};
|
||||
|
||||
static struct platform_device *bt_platform;
|
||||
|
||||
static void bt_release(struct device *dev)
|
||||
static void bt_host_release(struct device *dev)
|
||||
{
|
||||
void *data = dev_get_drvdata(dev);
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
static void add_conn(struct work_struct *work)
|
||||
{
|
||||
struct hci_conn *conn = container_of(work, struct hci_conn, work);
|
||||
int i;
|
||||
|
||||
flush_workqueue(btdelconn);
|
||||
|
||||
if (device_add(&conn->dev) < 0) {
|
||||
BT_ERR("Failed to register connection device");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; conn_attrs[i]; i++)
|
||||
if (device_create_file(&conn->dev, conn_attrs[i]) < 0)
|
||||
BT_ERR("Failed to create connection attribute");
|
||||
}
|
||||
|
||||
void hci_conn_add_sysfs(struct hci_conn *conn)
|
||||
{
|
||||
struct hci_dev *hdev = conn->hdev;
|
||||
|
||||
BT_DBG("conn %p", conn);
|
||||
|
||||
conn->dev.bus = &bt_bus;
|
||||
conn->dev.parent = &hdev->dev;
|
||||
|
||||
conn->dev.release = bt_release;
|
||||
|
||||
snprintf(conn->dev.bus_id, BUS_ID_SIZE, "%s:%d",
|
||||
hdev->name, conn->handle);
|
||||
|
||||
dev_set_drvdata(&conn->dev, conn);
|
||||
|
||||
device_initialize(&conn->dev);
|
||||
|
||||
INIT_WORK(&conn->work, add_conn);
|
||||
|
||||
queue_work(btaddconn, &conn->work);
|
||||
}
|
||||
|
||||
/*
|
||||
* The rfcomm tty device will possibly retain even when conn
|
||||
* is down, and sysfs doesn't support move zombie device,
|
||||
* so we should move the device before conn device is destroyed.
|
||||
*/
|
||||
static int __match_tty(struct device *dev, void *data)
|
||||
{
|
||||
return !strncmp(dev->bus_id, "rfcomm", 6);
|
||||
}
|
||||
|
||||
static void del_conn(struct work_struct *work)
|
||||
{
|
||||
struct hci_conn *conn = container_of(work, struct hci_conn, work);
|
||||
struct hci_dev *hdev = conn->hdev;
|
||||
|
||||
while (1) {
|
||||
struct device *dev;
|
||||
|
||||
dev = device_find_child(&conn->dev, NULL, __match_tty);
|
||||
if (!dev)
|
||||
break;
|
||||
device_move(dev, NULL);
|
||||
put_device(dev);
|
||||
}
|
||||
|
||||
device_del(&conn->dev);
|
||||
put_device(&conn->dev);
|
||||
hci_dev_put(hdev);
|
||||
}
|
||||
|
||||
void hci_conn_del_sysfs(struct hci_conn *conn)
|
||||
{
|
||||
BT_DBG("conn %p", conn);
|
||||
|
||||
if (!device_is_registered(&conn->dev))
|
||||
return;
|
||||
|
||||
INIT_WORK(&conn->work, del_conn);
|
||||
|
||||
queue_work(btdelconn, &conn->work);
|
||||
}
|
||||
static struct device_type bt_host = {
|
||||
.name = "host",
|
||||
.groups = bt_host_groups,
|
||||
.release = bt_host_release,
|
||||
};
|
||||
|
||||
int hci_register_sysfs(struct hci_dev *hdev)
|
||||
{
|
||||
struct device *dev = &hdev->dev;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
|
||||
|
||||
dev->bus = &bt_bus;
|
||||
dev->type = &bt_host;
|
||||
dev->class = bt_class;
|
||||
dev->parent = hdev->parent;
|
||||
|
||||
strlcpy(dev->bus_id, hdev->name, BUS_ID_SIZE);
|
||||
|
||||
dev->release = bt_release;
|
||||
|
||||
dev_set_drvdata(dev, hdev);
|
||||
|
||||
err = device_register(dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
for (i = 0; bt_attrs[i]; i++)
|
||||
if (device_create_file(dev, bt_attrs[i]) < 0)
|
||||
BT_ERR("Failed to create device attribute");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -410,59 +441,30 @@ void hci_unregister_sysfs(struct hci_dev *hdev)
|
||||
|
||||
int __init bt_sysfs_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
btaddconn = create_singlethread_workqueue("btaddconn");
|
||||
if (!btaddconn) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (!btaddconn)
|
||||
return -ENOMEM;
|
||||
|
||||
btdelconn = create_singlethread_workqueue("btdelconn");
|
||||
if (!btdelconn) {
|
||||
err = -ENOMEM;
|
||||
goto out_del;
|
||||
destroy_workqueue(btaddconn);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
bt_platform = platform_device_register_simple("bluetooth", -1, NULL, 0);
|
||||
if (IS_ERR(bt_platform)) {
|
||||
err = PTR_ERR(bt_platform);
|
||||
goto out_platform;
|
||||
}
|
||||
|
||||
err = bus_register(&bt_bus);
|
||||
if (err < 0)
|
||||
goto out_bus;
|
||||
|
||||
bt_class = class_create(THIS_MODULE, "bluetooth");
|
||||
if (IS_ERR(bt_class)) {
|
||||
err = PTR_ERR(bt_class);
|
||||
goto out_class;
|
||||
destroy_workqueue(btdelconn);
|
||||
destroy_workqueue(btaddconn);
|
||||
return PTR_ERR(bt_class);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_class:
|
||||
bus_unregister(&bt_bus);
|
||||
out_bus:
|
||||
platform_device_unregister(bt_platform);
|
||||
out_platform:
|
||||
destroy_workqueue(btdelconn);
|
||||
out_del:
|
||||
destroy_workqueue(btaddconn);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
void bt_sysfs_cleanup(void)
|
||||
{
|
||||
destroy_workqueue(btaddconn);
|
||||
|
||||
destroy_workqueue(btdelconn);
|
||||
|
||||
class_destroy(bt_class);
|
||||
|
||||
bus_unregister(&bt_bus);
|
||||
|
||||
platform_device_unregister(bt_platform);
|
||||
}
|
||||
|
@ -2516,7 +2516,7 @@ EXPORT_SYMBOL(l2cap_load);
|
||||
module_init(l2cap_init);
|
||||
module_exit(l2cap_exit);
|
||||
|
||||
MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
|
||||
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
||||
MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION);
|
||||
MODULE_VERSION(VERSION);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -2115,7 +2115,7 @@ MODULE_PARM_DESC(channel_mtu, "Default MTU for the RFCOMM channel");
|
||||
module_param(l2cap_mtu, uint, 0644);
|
||||
MODULE_PARM_DESC(l2cap_mtu, "Default MTU for the L2CAP connection");
|
||||
|
||||
MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
|
||||
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
||||
MODULE_DESCRIPTION("Bluetooth RFCOMM ver " VERSION);
|
||||
MODULE_VERSION(VERSION);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -1002,7 +1002,7 @@ module_exit(sco_exit);
|
||||
module_param(disable_esco, bool, 0644);
|
||||
MODULE_PARM_DESC(disable_esco, "Disable eSCO connection creation");
|
||||
|
||||
MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
|
||||
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
||||
MODULE_DESCRIPTION("Bluetooth SCO ver " VERSION);
|
||||
MODULE_VERSION(VERSION);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -148,11 +148,16 @@ static int br_set_tx_csum(struct net_device *dev, u32 data)
|
||||
}
|
||||
|
||||
static struct ethtool_ops br_ethtool_ops = {
|
||||
.get_drvinfo = br_getinfo,
|
||||
.get_link = ethtool_op_get_link,
|
||||
.set_sg = br_set_sg,
|
||||
.set_tx_csum = br_set_tx_csum,
|
||||
.set_tso = br_set_tso,
|
||||
.get_drvinfo = br_getinfo,
|
||||
.get_link = ethtool_op_get_link,
|
||||
.get_tx_csum = ethtool_op_get_tx_csum,
|
||||
.set_tx_csum = br_set_tx_csum,
|
||||
.get_sg = ethtool_op_get_sg,
|
||||
.set_sg = br_set_sg,
|
||||
.get_tso = ethtool_op_get_tso,
|
||||
.set_tso = br_set_tso,
|
||||
.get_ufo = ethtool_op_get_ufo,
|
||||
.get_flags = ethtool_op_get_flags,
|
||||
};
|
||||
|
||||
void br_dev_setup(struct net_device *dev)
|
||||
|
@ -339,6 +339,93 @@ fault:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* skb_copy_datagram_from_iovec - Copy a datagram from an iovec.
|
||||
* @skb: buffer to copy
|
||||
* @offset: offset in the buffer to start copying to
|
||||
* @from: io vector to copy to
|
||||
* @len: amount of data to copy to buffer from iovec
|
||||
*
|
||||
* Returns 0 or -EFAULT.
|
||||
* Note: the iovec is modified during the copy.
|
||||
*/
|
||||
int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset,
|
||||
struct iovec *from, int len)
|
||||
{
|
||||
int start = skb_headlen(skb);
|
||||
int i, copy = start - offset;
|
||||
|
||||
/* Copy header. */
|
||||
if (copy > 0) {
|
||||
if (copy > len)
|
||||
copy = len;
|
||||
if (memcpy_fromiovec(skb->data + offset, from, copy))
|
||||
goto fault;
|
||||
if ((len -= copy) == 0)
|
||||
return 0;
|
||||
offset += copy;
|
||||
}
|
||||
|
||||
/* Copy paged appendix. Hmm... why does this look so complicated? */
|
||||
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
|
||||
int end;
|
||||
|
||||
WARN_ON(start > offset + len);
|
||||
|
||||
end = start + skb_shinfo(skb)->frags[i].size;
|
||||
if ((copy = end - offset) > 0) {
|
||||
int err;
|
||||
u8 *vaddr;
|
||||
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
|
||||
struct page *page = frag->page;
|
||||
|
||||
if (copy > len)
|
||||
copy = len;
|
||||
vaddr = kmap(page);
|
||||
err = memcpy_fromiovec(vaddr + frag->page_offset +
|
||||
offset - start, from, copy);
|
||||
kunmap(page);
|
||||
if (err)
|
||||
goto fault;
|
||||
|
||||
if (!(len -= copy))
|
||||
return 0;
|
||||
offset += copy;
|
||||
}
|
||||
start = end;
|
||||
}
|
||||
|
||||
if (skb_shinfo(skb)->frag_list) {
|
||||
struct sk_buff *list = skb_shinfo(skb)->frag_list;
|
||||
|
||||
for (; list; list = list->next) {
|
||||
int end;
|
||||
|
||||
WARN_ON(start > offset + len);
|
||||
|
||||
end = start + list->len;
|
||||
if ((copy = end - offset) > 0) {
|
||||
if (copy > len)
|
||||
copy = len;
|
||||
if (skb_copy_datagram_from_iovec(list,
|
||||
offset - start,
|
||||
from, copy))
|
||||
goto fault;
|
||||
if ((len -= copy) == 0)
|
||||
return 0;
|
||||
offset += copy;
|
||||
}
|
||||
start = end;
|
||||
}
|
||||
}
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
fault:
|
||||
return -EFAULT;
|
||||
}
|
||||
EXPORT_SYMBOL(skb_copy_datagram_from_iovec);
|
||||
|
||||
static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
|
||||
u8 __user *to, int len,
|
||||
__wsum *csump)
|
||||
|
@ -1339,19 +1339,23 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
|
||||
}
|
||||
|
||||
|
||||
static inline void __netif_reschedule(struct Qdisc *q)
|
||||
{
|
||||
struct softnet_data *sd;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
sd = &__get_cpu_var(softnet_data);
|
||||
q->next_sched = sd->output_queue;
|
||||
sd->output_queue = q;
|
||||
raise_softirq_irqoff(NET_TX_SOFTIRQ);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
void __netif_schedule(struct Qdisc *q)
|
||||
{
|
||||
if (!test_and_set_bit(__QDISC_STATE_SCHED, &q->state)) {
|
||||
struct softnet_data *sd;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
sd = &__get_cpu_var(softnet_data);
|
||||
q->next_sched = sd->output_queue;
|
||||
sd->output_queue = q;
|
||||
raise_softirq_irqoff(NET_TX_SOFTIRQ);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
if (!test_and_set_bit(__QDISC_STATE_SCHED, &q->state))
|
||||
__netif_reschedule(q);
|
||||
}
|
||||
EXPORT_SYMBOL(__netif_schedule);
|
||||
|
||||
@ -1800,9 +1804,13 @@ gso:
|
||||
|
||||
spin_lock(root_lock);
|
||||
|
||||
rc = qdisc_enqueue_root(skb, q);
|
||||
qdisc_run(q);
|
||||
|
||||
if (unlikely(test_bit(__QDISC_STATE_DEACTIVATED, &q->state))) {
|
||||
kfree_skb(skb);
|
||||
rc = NET_XMIT_DROP;
|
||||
} else {
|
||||
rc = qdisc_enqueue_root(skb, q);
|
||||
qdisc_run(q);
|
||||
}
|
||||
spin_unlock(root_lock);
|
||||
|
||||
goto out;
|
||||
@ -1974,15 +1982,17 @@ static void net_tx_action(struct softirq_action *h)
|
||||
|
||||
head = head->next_sched;
|
||||
|
||||
smp_mb__before_clear_bit();
|
||||
clear_bit(__QDISC_STATE_SCHED, &q->state);
|
||||
|
||||
root_lock = qdisc_lock(q);
|
||||
if (spin_trylock(root_lock)) {
|
||||
smp_mb__before_clear_bit();
|
||||
clear_bit(__QDISC_STATE_SCHED,
|
||||
&q->state);
|
||||
qdisc_run(q);
|
||||
spin_unlock(root_lock);
|
||||
} else {
|
||||
__netif_schedule(q);
|
||||
if (!test_bit(__QDISC_STATE_DEACTIVATED,
|
||||
&q->state))
|
||||
__netif_reschedule(q);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2084,7 +2094,8 @@ static int ing_filter(struct sk_buff *skb)
|
||||
q = rxq->qdisc;
|
||||
if (q != &noop_qdisc) {
|
||||
spin_lock(qdisc_lock(q));
|
||||
result = qdisc_enqueue_root(skb, q);
|
||||
if (likely(!test_bit(__QDISC_STATE_DEACTIVATED, &q->state)))
|
||||
result = qdisc_enqueue_root(skb, q);
|
||||
spin_unlock(qdisc_lock(q));
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ struct gen_estimator_head
|
||||
|
||||
static struct gen_estimator_head elist[EST_MAX_INTERVAL+1];
|
||||
|
||||
/* Protects against NULL dereference and RCU write-side */
|
||||
/* Protects against NULL dereference */
|
||||
static DEFINE_RWLOCK(est_lock);
|
||||
|
||||
static void est_timer(unsigned long arg)
|
||||
@ -185,7 +185,6 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,
|
||||
est->last_packets = bstats->packets;
|
||||
est->avpps = rate_est->pps<<10;
|
||||
|
||||
write_lock_bh(&est_lock);
|
||||
if (!elist[idx].timer.function) {
|
||||
INIT_LIST_HEAD(&elist[idx].list);
|
||||
setup_timer(&elist[idx].timer, est_timer, idx);
|
||||
@ -195,7 +194,6 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,
|
||||
mod_timer(&elist[idx].timer, jiffies + ((HZ/4) << idx));
|
||||
|
||||
list_add_rcu(&est->list, &elist[idx].list);
|
||||
write_unlock_bh(&est_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -214,6 +212,7 @@ static void __gen_kill_estimator(struct rcu_head *head)
|
||||
* Removes the rate estimator specified by &bstats and &rate_est
|
||||
* and deletes the timer.
|
||||
*
|
||||
* NOTE: Called under rtnl_mutex
|
||||
*/
|
||||
void gen_kill_estimator(struct gnet_stats_basic *bstats,
|
||||
struct gnet_stats_rate_est *rate_est)
|
||||
@ -227,17 +226,17 @@ void gen_kill_estimator(struct gnet_stats_basic *bstats,
|
||||
if (!elist[idx].timer.function)
|
||||
continue;
|
||||
|
||||
write_lock_bh(&est_lock);
|
||||
list_for_each_entry_safe(e, n, &elist[idx].list, list) {
|
||||
if (e->rate_est != rate_est || e->bstats != bstats)
|
||||
continue;
|
||||
|
||||
write_lock_bh(&est_lock);
|
||||
e->bstats = NULL;
|
||||
write_unlock_bh(&est_lock);
|
||||
|
||||
list_del_rcu(&e->list);
|
||||
call_rcu(&e->e_rcu, __gen_kill_estimator);
|
||||
}
|
||||
write_unlock_bh(&est_lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2256,14 +2256,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features)
|
||||
segs = nskb;
|
||||
tail = nskb;
|
||||
|
||||
nskb->dev = skb->dev;
|
||||
skb_copy_queue_mapping(nskb, skb);
|
||||
nskb->priority = skb->priority;
|
||||
nskb->protocol = skb->protocol;
|
||||
nskb->vlan_tci = skb->vlan_tci;
|
||||
nskb->dst = dst_clone(skb->dst);
|
||||
memcpy(nskb->cb, skb->cb, sizeof(skb->cb));
|
||||
nskb->pkt_type = skb->pkt_type;
|
||||
__copy_skb_header(nskb, skb);
|
||||
nskb->mac_len = skb->mac_len;
|
||||
|
||||
skb_reserve(nskb, headroom);
|
||||
@ -2274,6 +2267,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features)
|
||||
skb_copy_from_linear_data(skb, skb_put(nskb, doffset),
|
||||
doffset);
|
||||
if (!sg) {
|
||||
nskb->ip_summed = CHECKSUM_NONE;
|
||||
nskb->csum = skb_copy_and_csum_bits(skb, offset,
|
||||
skb_put(nskb, len),
|
||||
len, 0);
|
||||
@ -2283,8 +2277,6 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features)
|
||||
frag = skb_shinfo(nskb)->frags;
|
||||
k = 0;
|
||||
|
||||
nskb->ip_summed = CHECKSUM_PARTIAL;
|
||||
nskb->csum = skb->csum;
|
||||
skb_copy_from_linear_data_offset(skb, offset,
|
||||
skb_put(nskb, hsize), hsize);
|
||||
|
||||
|
@ -411,12 +411,6 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
long tstamp = dccp_timestamp();
|
||||
|
||||
/* Stop the REQUEST timer */
|
||||
inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS);
|
||||
WARN_ON(sk->sk_send_head == NULL);
|
||||
__kfree_skb(sk->sk_send_head);
|
||||
sk->sk_send_head = NULL;
|
||||
|
||||
if (!between48(DCCP_SKB_CB(skb)->dccpd_ack_seq,
|
||||
dp->dccps_awl, dp->dccps_awh)) {
|
||||
dccp_pr_debug("invalid ackno: S.AWL=%llu, "
|
||||
@ -441,6 +435,12 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
|
||||
DCCP_ACKVEC_STATE_RECEIVED))
|
||||
goto out_invalid_packet; /* FIXME: change error code */
|
||||
|
||||
/* Stop the REQUEST timer */
|
||||
inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS);
|
||||
WARN_ON(sk->sk_send_head == NULL);
|
||||
kfree_skb(sk->sk_send_head);
|
||||
sk->sk_send_head = NULL;
|
||||
|
||||
dp->dccps_isr = DCCP_SKB_CB(skb)->dccpd_seq;
|
||||
dccp_update_gsr(sk, dp->dccps_isr);
|
||||
/*
|
||||
|
@ -70,7 +70,7 @@ addrtype_mt_v1(const struct sk_buff *skb, const struct net_device *in,
|
||||
(info->flags & IPT_ADDRTYPE_INVERT_SOURCE);
|
||||
if (ret && info->dest)
|
||||
ret &= match_type(dev, iph->daddr, info->dest) ^
|
||||
(info->flags & IPT_ADDRTYPE_INVERT_DEST);
|
||||
!!(info->flags & IPT_ADDRTYPE_INVERT_DEST);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -73,9 +73,13 @@ bool nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
|
||||
range_size = ntohs(range->max.all) - min + 1;
|
||||
}
|
||||
|
||||
off = *rover;
|
||||
if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
|
||||
off = net_random();
|
||||
off = secure_ipv4_port_ephemeral(tuple->src.u3.ip, tuple->dst.u3.ip,
|
||||
maniptype == IP_NAT_MANIP_SRC
|
||||
? tuple->dst.u.all
|
||||
: tuple->src.u.all);
|
||||
else
|
||||
off = *rover;
|
||||
|
||||
for (i = 0; i < range_size; i++, off++) {
|
||||
*portptr = htons(min + off % range_size);
|
||||
|
@ -2914,6 +2914,68 @@ static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rt_secret_reschedule(int old)
|
||||
{
|
||||
struct net *net;
|
||||
int new = ip_rt_secret_interval;
|
||||
int diff = new - old;
|
||||
|
||||
if (!diff)
|
||||
return;
|
||||
|
||||
rtnl_lock();
|
||||
for_each_net(net) {
|
||||
int deleted = del_timer_sync(&net->ipv4.rt_secret_timer);
|
||||
|
||||
if (!new)
|
||||
continue;
|
||||
|
||||
if (deleted) {
|
||||
long time = net->ipv4.rt_secret_timer.expires - jiffies;
|
||||
|
||||
if (time <= 0 || (time += diff) <= 0)
|
||||
time = 0;
|
||||
|
||||
net->ipv4.rt_secret_timer.expires = time;
|
||||
} else
|
||||
net->ipv4.rt_secret_timer.expires = new;
|
||||
|
||||
net->ipv4.rt_secret_timer.expires += jiffies;
|
||||
add_timer(&net->ipv4.rt_secret_timer);
|
||||
}
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
static int ipv4_sysctl_rt_secret_interval(ctl_table *ctl, int write,
|
||||
struct file *filp,
|
||||
void __user *buffer, size_t *lenp,
|
||||
loff_t *ppos)
|
||||
{
|
||||
int old = ip_rt_secret_interval;
|
||||
int ret = proc_dointvec_jiffies(ctl, write, filp, buffer, lenp, ppos);
|
||||
|
||||
rt_secret_reschedule(old);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ipv4_sysctl_rt_secret_interval_strategy(ctl_table *table,
|
||||
int __user *name,
|
||||
int nlen,
|
||||
void __user *oldval,
|
||||
size_t __user *oldlenp,
|
||||
void __user *newval,
|
||||
size_t newlen)
|
||||
{
|
||||
int old = ip_rt_secret_interval;
|
||||
int ret = sysctl_jiffies(table, name, nlen, oldval, oldlenp, newval,
|
||||
newlen);
|
||||
|
||||
rt_secret_reschedule(old);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ctl_table ipv4_route_table[] = {
|
||||
{
|
||||
.ctl_name = NET_IPV4_ROUTE_GC_THRESH,
|
||||
@ -3048,8 +3110,8 @@ static ctl_table ipv4_route_table[] = {
|
||||
.data = &ip_rt_secret_interval,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_jiffies,
|
||||
.strategy = &sysctl_jiffies,
|
||||
.proc_handler = &ipv4_sysctl_rt_secret_interval,
|
||||
.strategy = &ipv4_sysctl_rt_secret_interval_strategy,
|
||||
},
|
||||
{ .ctl_name = 0 }
|
||||
};
|
||||
@ -3126,10 +3188,12 @@ static __net_init int rt_secret_timer_init(struct net *net)
|
||||
net->ipv4.rt_secret_timer.data = (unsigned long)net;
|
||||
init_timer_deferrable(&net->ipv4.rt_secret_timer);
|
||||
|
||||
net->ipv4.rt_secret_timer.expires =
|
||||
jiffies + net_random() % ip_rt_secret_interval +
|
||||
ip_rt_secret_interval;
|
||||
add_timer(&net->ipv4.rt_secret_timer);
|
||||
if (ip_rt_secret_interval) {
|
||||
net->ipv4.rt_secret_timer.expires =
|
||||
jiffies + net_random() % ip_rt_secret_interval +
|
||||
ip_rt_secret_interval;
|
||||
add_timer(&net->ipv4.rt_secret_timer);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1106,13 +1106,12 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ipv6_dev_get_saddr(struct net_device *dst_dev,
|
||||
int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev,
|
||||
const struct in6_addr *daddr, unsigned int prefs,
|
||||
struct in6_addr *saddr)
|
||||
{
|
||||
struct ipv6_saddr_score scores[2],
|
||||
*score = &scores[0], *hiscore = &scores[1];
|
||||
struct net *net = dev_net(dst_dev);
|
||||
struct ipv6_saddr_dst dst;
|
||||
struct net_device *dev;
|
||||
int dst_type;
|
||||
|
@ -93,7 +93,8 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
|
||||
if (flags & RT6_LOOKUP_F_SRCPREF_COA)
|
||||
srcprefs |= IPV6_PREFER_SRC_COA;
|
||||
|
||||
if (ipv6_dev_get_saddr(ip6_dst_idev(&rt->u.dst)->dev,
|
||||
if (ipv6_dev_get_saddr(net,
|
||||
ip6_dst_idev(&rt->u.dst)->dev,
|
||||
&flp->fl6_dst, srcprefs,
|
||||
&saddr))
|
||||
goto again;
|
||||
|
@ -378,6 +378,7 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
|
||||
arg.skb = skb;
|
||||
arg.cb = cb;
|
||||
arg.net = net;
|
||||
w->args = &arg;
|
||||
|
||||
for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) {
|
||||
|
@ -934,7 +934,7 @@ static int ip6_dst_lookup_tail(struct sock *sk,
|
||||
goto out_err_release;
|
||||
|
||||
if (ipv6_addr_any(&fl->fl6_src)) {
|
||||
err = ipv6_dev_get_saddr(ip6_dst_idev(*dst)->dev,
|
||||
err = ipv6_dev_get_saddr(net, ip6_dst_idev(*dst)->dev,
|
||||
&fl->fl6_dst,
|
||||
sk ? inet6_sk(sk)->srcprefs : 0,
|
||||
&fl->fl6_src);
|
||||
|
@ -911,7 +911,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
|
||||
} else {
|
||||
if (np->rxopt.bits.rxinfo) {
|
||||
struct in6_pktinfo src_info;
|
||||
src_info.ipi6_ifindex = np->mcast_oif;
|
||||
src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif : sk->sk_bound_dev_if;
|
||||
ipv6_addr_copy(&src_info.ipi6_addr, &np->daddr);
|
||||
put_cmsg(&msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), &src_info);
|
||||
}
|
||||
@ -921,7 +921,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
|
||||
}
|
||||
if (np->rxopt.bits.rxoinfo) {
|
||||
struct in6_pktinfo src_info;
|
||||
src_info.ipi6_ifindex = np->mcast_oif;
|
||||
src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif : sk->sk_bound_dev_if;
|
||||
ipv6_addr_copy(&src_info.ipi6_addr, &np->daddr);
|
||||
put_cmsg(&msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user