diff options
335 files changed, 7035 insertions, 2926 deletions
diff --git a/drivers/bcma/driver_chipcommon_sflash.c b/drivers/bcma/driver_chipcommon_sflash.c index 4d07cce9c5d9..7e11ef4cb7db 100644 --- a/drivers/bcma/driver_chipcommon_sflash.c +++ b/drivers/bcma/driver_chipcommon_sflash.c | |||
| @@ -38,7 +38,7 @@ static const struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { | |||
| 38 | { "M25P32", 0x15, 0x10000, 64, }, | 38 | { "M25P32", 0x15, 0x10000, 64, }, |
| 39 | { "M25P64", 0x16, 0x10000, 128, }, | 39 | { "M25P64", 0x16, 0x10000, 128, }, |
| 40 | { "M25FL128", 0x17, 0x10000, 256, }, | 40 | { "M25FL128", 0x17, 0x10000, 256, }, |
| 41 | { 0 }, | 41 | { NULL }, |
| 42 | }; | 42 | }; |
| 43 | 43 | ||
| 44 | static const struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { | 44 | static const struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { |
| @@ -56,7 +56,7 @@ static const struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { | |||
| 56 | { "SST25VF016", 0x41, 0x1000, 512, }, | 56 | { "SST25VF016", 0x41, 0x1000, 512, }, |
| 57 | { "SST25VF032", 0x4a, 0x1000, 1024, }, | 57 | { "SST25VF032", 0x4a, 0x1000, 1024, }, |
| 58 | { "SST25VF064", 0x4b, 0x1000, 2048, }, | 58 | { "SST25VF064", 0x4b, 0x1000, 2048, }, |
| 59 | { 0 }, | 59 | { NULL }, |
| 60 | }; | 60 | }; |
| 61 | 61 | ||
| 62 | static const struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { | 62 | static const struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { |
| @@ -67,7 +67,7 @@ static const struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { | |||
| 67 | { "AT45DB161", 0x2c, 512, 4096, }, | 67 | { "AT45DB161", 0x2c, 512, 4096, }, |
| 68 | { "AT45DB321", 0x34, 512, 8192, }, | 68 | { "AT45DB321", 0x34, 512, 8192, }, |
| 69 | { "AT45DB642", 0x3c, 1024, 8192, }, | 69 | { "AT45DB642", 0x3c, 1024, 8192, }, |
| 70 | { 0 }, | 70 | { NULL }, |
| 71 | }; | 71 | }; |
| 72 | 72 | ||
| 73 | static void bcma_sflash_cmd(struct bcma_drv_cc *cc, u32 opcode) | 73 | static void bcma_sflash_cmd(struct bcma_drv_cc *cc, u32 opcode) |
diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c index b61440aaee65..83f6437dd91d 100644 --- a/drivers/bluetooth/btsdio.c +++ b/drivers/bluetooth/btsdio.c | |||
| @@ -73,6 +73,7 @@ struct btsdio_data { | |||
| 73 | #define REG_CL_INTRD 0x13 /* Interrupt Clear */ | 73 | #define REG_CL_INTRD 0x13 /* Interrupt Clear */ |
| 74 | #define REG_EN_INTRD 0x14 /* Interrupt Enable */ | 74 | #define REG_EN_INTRD 0x14 /* Interrupt Enable */ |
| 75 | #define REG_MD_STAT 0x20 /* Bluetooth Mode Status */ | 75 | #define REG_MD_STAT 0x20 /* Bluetooth Mode Status */ |
| 76 | #define REG_MD_SET 0x20 /* Bluetooth Mode Set */ | ||
| 76 | 77 | ||
| 77 | static int btsdio_tx_packet(struct btsdio_data *data, struct sk_buff *skb) | 78 | static int btsdio_tx_packet(struct btsdio_data *data, struct sk_buff *skb) |
| 78 | { | 79 | { |
| @@ -212,7 +213,7 @@ static int btsdio_open(struct hci_dev *hdev) | |||
| 212 | } | 213 | } |
| 213 | 214 | ||
| 214 | if (data->func->class == SDIO_CLASS_BT_B) | 215 | if (data->func->class == SDIO_CLASS_BT_B) |
| 215 | sdio_writeb(data->func, 0x00, REG_MD_STAT, NULL); | 216 | sdio_writeb(data->func, 0x00, REG_MD_SET, NULL); |
| 216 | 217 | ||
| 217 | sdio_writeb(data->func, 0x01, REG_EN_INTRD, NULL); | 218 | sdio_writeb(data->func, 0x01, REG_EN_INTRD, NULL); |
| 218 | 219 | ||
| @@ -333,6 +334,9 @@ static int btsdio_probe(struct sdio_func *func, | |||
| 333 | hdev->flush = btsdio_flush; | 334 | hdev->flush = btsdio_flush; |
| 334 | hdev->send = btsdio_send_frame; | 335 | hdev->send = btsdio_send_frame; |
| 335 | 336 | ||
| 337 | if (func->vendor == 0x0104 && func->device == 0x00c5) | ||
| 338 | set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); | ||
| 339 | |||
| 336 | err = hci_register_dev(hdev); | 340 | err = hci_register_dev(hdev); |
| 337 | if (err < 0) { | 341 | if (err < 0) { |
| 338 | hci_free_dev(hdev); | 342 | hci_free_dev(hdev); |
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 9f7e539de510..baeaaed299e4 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
| @@ -965,6 +965,45 @@ static int btusb_setup_bcm92035(struct hci_dev *hdev) | |||
| 965 | return 0; | 965 | return 0; |
| 966 | } | 966 | } |
| 967 | 967 | ||
| 968 | static int btusb_setup_csr(struct hci_dev *hdev) | ||
| 969 | { | ||
| 970 | struct hci_rp_read_local_version *rp; | ||
| 971 | struct sk_buff *skb; | ||
| 972 | int ret; | ||
| 973 | |||
| 974 | BT_DBG("%s", hdev->name); | ||
| 975 | |||
| 976 | skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, | ||
| 977 | HCI_INIT_TIMEOUT); | ||
| 978 | if (IS_ERR(skb)) { | ||
| 979 | BT_ERR("Reading local version failed (%ld)", -PTR_ERR(skb)); | ||
| 980 | return -PTR_ERR(skb); | ||
| 981 | } | ||
| 982 | |||
| 983 | rp = (struct hci_rp_read_local_version *) skb->data; | ||
| 984 | |||
| 985 | if (!rp->status) { | ||
| 986 | if (le16_to_cpu(rp->manufacturer) != 10) { | ||
| 987 | /* Clear the reset quirk since this is not an actual | ||
| 988 | * early Bluetooth 1.1 device from CSR. | ||
| 989 | */ | ||
| 990 | clear_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); | ||
| 991 | |||
| 992 | /* These fake CSR controllers have all a broken | ||
| 993 | * stored link key handling and so just disable it. | ||
| 994 | */ | ||
| 995 | set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, | ||
| 996 | &hdev->quirks); | ||
| 997 | } | ||
| 998 | } | ||
| 999 | |||
| 1000 | ret = -bt_to_errno(rp->status); | ||
| 1001 | |||
| 1002 | kfree_skb(skb); | ||
| 1003 | |||
| 1004 | return ret; | ||
| 1005 | } | ||
| 1006 | |||
| 968 | struct intel_version { | 1007 | struct intel_version { |
| 969 | u8 status; | 1008 | u8 status; |
| 970 | u8 hw_platform; | 1009 | u8 hw_platform; |
| @@ -1465,10 +1504,15 @@ static int btusb_probe(struct usb_interface *intf, | |||
| 1465 | 1504 | ||
| 1466 | if (id->driver_info & BTUSB_CSR) { | 1505 | if (id->driver_info & BTUSB_CSR) { |
| 1467 | struct usb_device *udev = data->udev; | 1506 | struct usb_device *udev = data->udev; |
| 1507 | u16 bcdDevice = le16_to_cpu(udev->descriptor.bcdDevice); | ||
| 1468 | 1508 | ||
| 1469 | /* Old firmware would otherwise execute USB reset */ | 1509 | /* Old firmware would otherwise execute USB reset */ |
| 1470 | if (le16_to_cpu(udev->descriptor.bcdDevice) < 0x117) | 1510 | if (bcdDevice < 0x117) |
| 1471 | set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); | 1511 | set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); |
| 1512 | |||
| 1513 | /* Fake CSR devices with broken commands */ | ||
| 1514 | if (bcdDevice <= 0x100) | ||
| 1515 | hdev->setup = btusb_setup_csr; | ||
| 1472 | } | 1516 | } |
| 1473 | 1517 | ||
| 1474 | if (id->driver_info & BTUSB_SNIFFER) { | 1518 | if (id->driver_info & BTUSB_SNIFFER) { |
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index 7b167385a1c4..1ef6990a5c7e 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c | |||
| @@ -141,22 +141,28 @@ static int vhci_create_device(struct vhci_data *data, __u8 dev_type) | |||
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | static inline ssize_t vhci_get_user(struct vhci_data *data, | 143 | static inline ssize_t vhci_get_user(struct vhci_data *data, |
| 144 | const char __user *buf, size_t count) | 144 | const struct iovec *iov, |
| 145 | unsigned long count) | ||
| 145 | { | 146 | { |
| 147 | size_t len = iov_length(iov, count); | ||
| 146 | struct sk_buff *skb; | 148 | struct sk_buff *skb; |
| 147 | __u8 pkt_type, dev_type; | 149 | __u8 pkt_type, dev_type; |
| 150 | unsigned long i; | ||
| 148 | int ret; | 151 | int ret; |
| 149 | 152 | ||
| 150 | if (count < 2 || count > HCI_MAX_FRAME_SIZE) | 153 | if (len < 2 || len > HCI_MAX_FRAME_SIZE) |
| 151 | return -EINVAL; | 154 | return -EINVAL; |
| 152 | 155 | ||
| 153 | skb = bt_skb_alloc(count, GFP_KERNEL); | 156 | skb = bt_skb_alloc(len, GFP_KERNEL); |
| 154 | if (!skb) | 157 | if (!skb) |
| 155 | return -ENOMEM; | 158 | return -ENOMEM; |
| 156 | 159 | ||
| 157 | if (copy_from_user(skb_put(skb, count), buf, count)) { | 160 | for (i = 0; i < count; i++) { |
| 158 | kfree_skb(skb); | 161 | if (copy_from_user(skb_put(skb, iov[i].iov_len), |
| 159 | return -EFAULT; | 162 | iov[i].iov_base, iov[i].iov_len)) { |
| 163 | kfree_skb(skb); | ||
| 164 | return -EFAULT; | ||
| 165 | } | ||
| 160 | } | 166 | } |
| 161 | 167 | ||
| 162 | pkt_type = *((__u8 *) skb->data); | 168 | pkt_type = *((__u8 *) skb->data); |
| @@ -205,7 +211,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data, | |||
| 205 | return -EINVAL; | 211 | return -EINVAL; |
| 206 | } | 212 | } |
| 207 | 213 | ||
| 208 | return (ret < 0) ? ret : count; | 214 | return (ret < 0) ? ret : len; |
| 209 | } | 215 | } |
| 210 | 216 | ||
| 211 | static inline ssize_t vhci_put_user(struct vhci_data *data, | 217 | static inline ssize_t vhci_put_user(struct vhci_data *data, |
| @@ -272,12 +278,13 @@ static ssize_t vhci_read(struct file *file, | |||
| 272 | return ret; | 278 | return ret; |
| 273 | } | 279 | } |
| 274 | 280 | ||
| 275 | static ssize_t vhci_write(struct file *file, | 281 | static ssize_t vhci_write(struct kiocb *iocb, const struct iovec *iov, |
| 276 | const char __user *buf, size_t count, loff_t *pos) | 282 | unsigned long count, loff_t pos) |
| 277 | { | 283 | { |
| 284 | struct file *file = iocb->ki_filp; | ||
| 278 | struct vhci_data *data = file->private_data; | 285 | struct vhci_data *data = file->private_data; |
| 279 | 286 | ||
| 280 | return vhci_get_user(data, buf, count); | 287 | return vhci_get_user(data, iov, count); |
| 281 | } | 288 | } |
| 282 | 289 | ||
| 283 | static unsigned int vhci_poll(struct file *file, poll_table *wait) | 290 | static unsigned int vhci_poll(struct file *file, poll_table *wait) |
| @@ -342,7 +349,7 @@ static int vhci_release(struct inode *inode, struct file *file) | |||
| 342 | static const struct file_operations vhci_fops = { | 349 | static const struct file_operations vhci_fops = { |
| 343 | .owner = THIS_MODULE, | 350 | .owner = THIS_MODULE, |
| 344 | .read = vhci_read, | 351 | .read = vhci_read, |
| 345 | .write = vhci_write, | 352 | .aio_write = vhci_write, |
| 346 | .poll = vhci_poll, | 353 | .poll = vhci_poll, |
| 347 | .open = vhci_open, | 354 | .open = vhci_open, |
| 348 | .release = vhci_release, | 355 | .release = vhci_release, |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index b97e35c33d17..16782b2cff49 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | |||
| @@ -50,13 +50,13 @@ | |||
| 50 | #include "cxgb4_uld.h" | 50 | #include "cxgb4_uld.h" |
| 51 | 51 | ||
| 52 | #define T4FW_VERSION_MAJOR 0x01 | 52 | #define T4FW_VERSION_MAJOR 0x01 |
| 53 | #define T4FW_VERSION_MINOR 0x06 | 53 | #define T4FW_VERSION_MINOR 0x09 |
| 54 | #define T4FW_VERSION_MICRO 0x18 | 54 | #define T4FW_VERSION_MICRO 0x17 |
| 55 | #define T4FW_VERSION_BUILD 0x00 | 55 | #define T4FW_VERSION_BUILD 0x00 |
| 56 | 56 | ||
| 57 | #define T5FW_VERSION_MAJOR 0x01 | 57 | #define T5FW_VERSION_MAJOR 0x01 |
| 58 | #define T5FW_VERSION_MINOR 0x08 | 58 | #define T5FW_VERSION_MINOR 0x09 |
| 59 | #define T5FW_VERSION_MICRO 0x1C | 59 | #define T5FW_VERSION_MICRO 0x17 |
| 60 | #define T5FW_VERSION_BUILD 0x00 | 60 | #define T5FW_VERSION_BUILD 0x00 |
| 61 | 61 | ||
| 62 | #define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__) | 62 | #define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__) |
diff --git a/drivers/net/ethernet/intel/i40e/Makefile b/drivers/net/ethernet/intel/i40e/Makefile index 479b2c4e552d..6ec1a795f184 100644 --- a/drivers/net/ethernet/intel/i40e/Makefile +++ b/drivers/net/ethernet/intel/i40e/Makefile | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | ################################################################################ | 1 | ################################################################################ |
| 2 | # | 2 | # |
| 3 | # Intel Ethernet Controller XL710 Family Linux Driver | 3 | # Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | # Copyright(c) 2013 Intel Corporation. | 4 | # Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | # | 5 | # |
| 6 | # This program is free software; you can redistribute it and/or modify it | 6 | # This program is free software; you can redistribute it and/or modify it |
| 7 | # under the terms and conditions of the GNU General Public License, | 7 | # under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | # more details. | 13 | # more details. |
| 14 | # | 14 | # |
| 15 | # You should have received a copy of the GNU General Public License along with | 15 | # You should have received a copy of the GNU General Public License along |
| 16 | # this program; if not, write to the Free Software Foundation, Inc., | 16 | # with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | # 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | # | 17 | # |
| 19 | # The full GNU General Public License is included in this distribution in | 18 | # The full GNU General Public License is included in this distribution in |
| 20 | # the file called "COPYING". | 19 | # the file called "COPYING". |
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 09d92d00cb13..4d4cdbf6fad7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index 2b320841a108..c75aa2d07491 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
| @@ -584,6 +583,9 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw) | |||
| 584 | goto init_adminq_free_arq; | 583 | goto init_adminq_free_arq; |
| 585 | } | 584 | } |
| 586 | 585 | ||
| 586 | /* pre-emptive resource lock release */ | ||
| 587 | i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL); | ||
| 588 | |||
| 587 | ret_code = i40e_aq_set_hmc_resource_profile(hw, | 589 | ret_code = i40e_aq_set_hmc_resource_profile(hw, |
| 588 | I40E_HMC_PROFILE_DEFAULT, | 590 | I40E_HMC_PROFILE_DEFAULT, |
| 589 | 0, | 591 | 0, |
| @@ -862,7 +864,7 @@ void i40e_fill_default_direct_cmd_desc(struct i40e_aq_desc *desc, | |||
| 862 | /* zero out the desc */ | 864 | /* zero out the desc */ |
| 863 | memset((void *)desc, 0, sizeof(struct i40e_aq_desc)); | 865 | memset((void *)desc, 0, sizeof(struct i40e_aq_desc)); |
| 864 | desc->opcode = cpu_to_le16(opcode); | 866 | desc->opcode = cpu_to_le16(opcode); |
| 865 | desc->flags = cpu_to_le16(I40E_AQ_FLAG_EI | I40E_AQ_FLAG_SI); | 867 | desc->flags = cpu_to_le16(I40E_AQ_FLAG_SI); |
| 866 | } | 868 | } |
| 867 | 869 | ||
| 868 | /** | 870 | /** |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.h b/drivers/net/ethernet/intel/i40e/i40e_adminq.h index 21801c3d65dd..993f7685a911 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index 007508772cf0..c009eb47058a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_alloc.h b/drivers/net/ethernet/intel/i40e/i40e_alloc.h index 3b1cc214f9dc..926811ad44ac 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_alloc.h +++ b/drivers/net/ethernet/intel/i40e/i40e_alloc.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index d564910b4f58..807312bb62a2 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
| @@ -255,8 +254,11 @@ i40e_status i40e_aq_mac_address_write(struct i40e_hw *hw, | |||
| 255 | i40e_fill_default_direct_cmd_desc(&desc, | 254 | i40e_fill_default_direct_cmd_desc(&desc, |
| 256 | i40e_aqc_opc_mac_address_write); | 255 | i40e_aqc_opc_mac_address_write); |
| 257 | cmd_data->command_flags = cpu_to_le16(flags); | 256 | cmd_data->command_flags = cpu_to_le16(flags); |
| 258 | memcpy(&cmd_data->mac_sal, &mac_addr[0], 4); | 257 | cmd_data->mac_sah = cpu_to_le16((u16)mac_addr[0] << 8 | mac_addr[1]); |
| 259 | memcpy(&cmd_data->mac_sah, &mac_addr[4], 2); | 258 | cmd_data->mac_sal = cpu_to_le32(((u32)mac_addr[2] << 24) | |
| 259 | ((u32)mac_addr[3] << 16) | | ||
| 260 | ((u32)mac_addr[4] << 8) | | ||
| 261 | mac_addr[5]); | ||
| 260 | 262 | ||
| 261 | status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); | 263 | status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); |
| 262 | 264 | ||
diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index 125f758a03ac..0220b18b2b18 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
| @@ -516,10 +515,10 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid) | |||
| 516 | rx_ring->stats.bytes, | 515 | rx_ring->stats.bytes, |
| 517 | rx_ring->rx_stats.non_eop_descs); | 516 | rx_ring->rx_stats.non_eop_descs); |
| 518 | dev_info(&pf->pdev->dev, | 517 | dev_info(&pf->pdev->dev, |
| 519 | " rx_rings[%i]: rx_stats: alloc_rx_page_failed = %lld, alloc_rx_buff_failed = %lld\n", | 518 | " rx_rings[%i]: rx_stats: alloc_page_failed = %lld, alloc_buff_failed = %lld\n", |
| 520 | i, | 519 | i, |
| 521 | rx_ring->rx_stats.alloc_rx_page_failed, | 520 | rx_ring->rx_stats.alloc_page_failed, |
| 522 | rx_ring->rx_stats.alloc_rx_buff_failed); | 521 | rx_ring->rx_stats.alloc_buff_failed); |
| 523 | dev_info(&pf->pdev->dev, | 522 | dev_info(&pf->pdev->dev, |
| 524 | " rx_rings[%i]: size = %i, dma = 0x%08lx\n", | 523 | " rx_rings[%i]: size = %i, dma = 0x%08lx\n", |
| 525 | i, rx_ring->size, | 524 | i, rx_ring->size, |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_diag.c b/drivers/net/ethernet/intel/i40e/i40e_diag.c index 6a1657e62418..b2380daef8c1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_diag.c +++ b/drivers/net/ethernet/intel/i40e/i40e_diag.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_diag.h b/drivers/net/ethernet/intel/i40e/i40e_diag.h index d1fc68cd6c94..0b5911652084 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_diag.h +++ b/drivers/net/ethernet/intel/i40e/i40e_diag.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 42c36d18e8c6..b886ee5bd99d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
| @@ -1244,6 +1243,7 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) | |||
| 1244 | } | 1243 | } |
| 1245 | 1244 | ||
| 1246 | #define IP_HEADER_OFFSET 14 | 1245 | #define IP_HEADER_OFFSET 14 |
| 1246 | #define I40E_UDPIP_DUMMY_PACKET_LEN 42 | ||
| 1247 | /** | 1247 | /** |
| 1248 | * i40e_add_del_fdir_udpv4 - Add/Remove UDPv4 Flow Director filters for | 1248 | * i40e_add_del_fdir_udpv4 - Add/Remove UDPv4 Flow Director filters for |
| 1249 | * a specific flow spec | 1249 | * a specific flow spec |
| @@ -1264,6 +1264,12 @@ static int i40e_add_del_fdir_udpv4(struct i40e_vsi *vsi, | |||
| 1264 | bool err = false; | 1264 | bool err = false; |
| 1265 | int ret; | 1265 | int ret; |
| 1266 | int i; | 1266 | int i; |
| 1267 | char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0, | ||
| 1268 | 0x45, 0, 0, 0x1c, 0, 0, 0x40, 0, 0x40, 0x11, | ||
| 1269 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 1270 | 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 1271 | |||
| 1272 | memcpy(fd_data->raw_packet, packet, I40E_UDPIP_DUMMY_PACKET_LEN); | ||
| 1267 | 1273 | ||
| 1268 | ip = (struct iphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET); | 1274 | ip = (struct iphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET); |
| 1269 | udp = (struct udphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET | 1275 | udp = (struct udphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET |
| @@ -1294,6 +1300,7 @@ static int i40e_add_del_fdir_udpv4(struct i40e_vsi *vsi, | |||
| 1294 | return err ? -EOPNOTSUPP : 0; | 1300 | return err ? -EOPNOTSUPP : 0; |
| 1295 | } | 1301 | } |
| 1296 | 1302 | ||
| 1303 | #define I40E_TCPIP_DUMMY_PACKET_LEN 54 | ||
| 1297 | /** | 1304 | /** |
| 1298 | * i40e_add_del_fdir_tcpv4 - Add/Remove TCPv4 Flow Director filters for | 1305 | * i40e_add_del_fdir_tcpv4 - Add/Remove TCPv4 Flow Director filters for |
| 1299 | * a specific flow spec | 1306 | * a specific flow spec |
| @@ -1313,6 +1320,14 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi, | |||
| 1313 | struct iphdr *ip; | 1320 | struct iphdr *ip; |
| 1314 | bool err = false; | 1321 | bool err = false; |
| 1315 | int ret; | 1322 | int ret; |
| 1323 | /* Dummy packet */ | ||
| 1324 | char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0, | ||
| 1325 | 0x45, 0, 0, 0x28, 0, 0, 0x40, 0, 0x40, 0x6, | ||
| 1326 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 1327 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 1328 | 0x80, 0x11, 0x0, 0x72, 0, 0, 0, 0}; | ||
| 1329 | |||
| 1330 | memcpy(fd_data->raw_packet, packet, I40E_TCPIP_DUMMY_PACKET_LEN); | ||
| 1316 | 1331 | ||
| 1317 | ip = (struct iphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET); | 1332 | ip = (struct iphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET); |
| 1318 | tcp = (struct tcphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET | 1333 | tcp = (struct tcphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET |
| @@ -1320,6 +1335,8 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi, | |||
| 1320 | 1335 | ||
| 1321 | ip->daddr = fsp->h_u.tcp_ip4_spec.ip4dst; | 1336 | ip->daddr = fsp->h_u.tcp_ip4_spec.ip4dst; |
| 1322 | tcp->dest = fsp->h_u.tcp_ip4_spec.pdst; | 1337 | tcp->dest = fsp->h_u.tcp_ip4_spec.pdst; |
| 1338 | ip->saddr = fsp->h_u.tcp_ip4_spec.ip4src; | ||
| 1339 | tcp->source = fsp->h_u.tcp_ip4_spec.psrc; | ||
| 1323 | 1340 | ||
| 1324 | fd_data->pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN; | 1341 | fd_data->pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN; |
| 1325 | ret = i40e_program_fdir_filter(fd_data, pf, add); | 1342 | ret = i40e_program_fdir_filter(fd_data, pf, add); |
| @@ -1334,9 +1351,6 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi, | |||
| 1334 | fd_data->pctype, ret); | 1351 | fd_data->pctype, ret); |
| 1335 | } | 1352 | } |
| 1336 | 1353 | ||
| 1337 | ip->saddr = fsp->h_u.tcp_ip4_spec.ip4src; | ||
| 1338 | tcp->source = fsp->h_u.tcp_ip4_spec.psrc; | ||
| 1339 | |||
| 1340 | fd_data->pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP; | 1354 | fd_data->pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP; |
| 1341 | 1355 | ||
| 1342 | ret = i40e_program_fdir_filter(fd_data, pf, add); | 1356 | ret = i40e_program_fdir_filter(fd_data, pf, add); |
| @@ -1370,6 +1384,7 @@ static int i40e_add_del_fdir_sctpv4(struct i40e_vsi *vsi, | |||
| 1370 | return -EOPNOTSUPP; | 1384 | return -EOPNOTSUPP; |
| 1371 | } | 1385 | } |
| 1372 | 1386 | ||
| 1387 | #define I40E_IP_DUMMY_PACKET_LEN 34 | ||
| 1373 | /** | 1388 | /** |
| 1374 | * i40e_add_del_fdir_ipv4 - Add/Remove IPv4 Flow Director filters for | 1389 | * i40e_add_del_fdir_ipv4 - Add/Remove IPv4 Flow Director filters for |
| 1375 | * a specific flow spec | 1390 | * a specific flow spec |
| @@ -1389,7 +1404,11 @@ static int i40e_add_del_fdir_ipv4(struct i40e_vsi *vsi, | |||
| 1389 | bool err = false; | 1404 | bool err = false; |
| 1390 | int ret; | 1405 | int ret; |
| 1391 | int i; | 1406 | int i; |
| 1407 | char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0, | ||
| 1408 | 0x45, 0, 0, 0x14, 0, 0, 0x40, 0, 0x40, 0x10, | ||
| 1409 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 1392 | 1410 | ||
| 1411 | memcpy(fd_data->raw_packet, packet, I40E_IP_DUMMY_PACKET_LEN); | ||
| 1393 | ip = (struct iphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET); | 1412 | ip = (struct iphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET); |
| 1394 | 1413 | ||
| 1395 | ip->saddr = fsp->h_u.usr_ip4_spec.ip4src; | 1414 | ip->saddr = fsp->h_u.usr_ip4_spec.ip4src; |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_hmc.c b/drivers/net/ethernet/intel/i40e/i40e_hmc.c index bcedf3fb1143..76dfef3e0104 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_hmc.c +++ b/drivers/net/ethernet/intel/i40e/i40e_hmc.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_hmc.h b/drivers/net/ethernet/intel/i40e/i40e_hmc.h index aacd42a261e9..72bf30aba150 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_hmc.h +++ b/drivers/net/ethernet/intel/i40e/i40e_hmc.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c b/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c index a695b91c9c79..101ed4107312 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c +++ b/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h b/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h index f8afbcb053c5..341de925a298 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h +++ b/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index f736c4470412..1b792ee592d0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
| @@ -423,7 +422,7 @@ void i40e_vsi_reset_stats(struct i40e_vsi *vsi) | |||
| 423 | memset(&vsi->net_stats_offsets, 0, sizeof(vsi->net_stats_offsets)); | 422 | memset(&vsi->net_stats_offsets, 0, sizeof(vsi->net_stats_offsets)); |
| 424 | memset(&vsi->eth_stats, 0, sizeof(vsi->eth_stats)); | 423 | memset(&vsi->eth_stats, 0, sizeof(vsi->eth_stats)); |
| 425 | memset(&vsi->eth_stats_offsets, 0, sizeof(vsi->eth_stats_offsets)); | 424 | memset(&vsi->eth_stats_offsets, 0, sizeof(vsi->eth_stats_offsets)); |
| 426 | if (vsi->rx_rings) | 425 | if (vsi->rx_rings && vsi->rx_rings[0]) { |
| 427 | for (i = 0; i < vsi->num_queue_pairs; i++) { | 426 | for (i = 0; i < vsi->num_queue_pairs; i++) { |
| 428 | memset(&vsi->rx_rings[i]->stats, 0 , | 427 | memset(&vsi->rx_rings[i]->stats, 0 , |
| 429 | sizeof(vsi->rx_rings[i]->stats)); | 428 | sizeof(vsi->rx_rings[i]->stats)); |
| @@ -434,6 +433,7 @@ void i40e_vsi_reset_stats(struct i40e_vsi *vsi) | |||
| 434 | memset(&vsi->tx_rings[i]->tx_stats, 0, | 433 | memset(&vsi->tx_rings[i]->tx_stats, 0, |
| 435 | sizeof(vsi->tx_rings[i]->tx_stats)); | 434 | sizeof(vsi->tx_rings[i]->tx_stats)); |
| 436 | } | 435 | } |
| 436 | } | ||
| 437 | vsi->stat_offsets_loaded = false; | 437 | vsi->stat_offsets_loaded = false; |
| 438 | } | 438 | } |
| 439 | 439 | ||
| @@ -786,8 +786,8 @@ void i40e_update_stats(struct i40e_vsi *vsi) | |||
| 786 | } while (u64_stats_fetch_retry_bh(&p->syncp, start)); | 786 | } while (u64_stats_fetch_retry_bh(&p->syncp, start)); |
| 787 | rx_b += bytes; | 787 | rx_b += bytes; |
| 788 | rx_p += packets; | 788 | rx_p += packets; |
| 789 | rx_buf += p->rx_stats.alloc_rx_buff_failed; | 789 | rx_buf += p->rx_stats.alloc_buff_failed; |
| 790 | rx_page += p->rx_stats.alloc_rx_page_failed; | 790 | rx_page += p->rx_stats.alloc_page_failed; |
| 791 | } | 791 | } |
| 792 | rcu_read_unlock(); | 792 | rcu_read_unlock(); |
| 793 | vsi->tx_restart = tx_restart; | 793 | vsi->tx_restart = tx_restart; |
| @@ -2068,8 +2068,11 @@ static void i40e_vsi_free_tx_resources(struct i40e_vsi *vsi) | |||
| 2068 | { | 2068 | { |
| 2069 | int i; | 2069 | int i; |
| 2070 | 2070 | ||
| 2071 | if (!vsi->tx_rings) | ||
| 2072 | return; | ||
| 2073 | |||
| 2071 | for (i = 0; i < vsi->num_queue_pairs; i++) | 2074 | for (i = 0; i < vsi->num_queue_pairs; i++) |
| 2072 | if (vsi->tx_rings[i]->desc) | 2075 | if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc) |
| 2073 | i40e_free_tx_resources(vsi->tx_rings[i]); | 2076 | i40e_free_tx_resources(vsi->tx_rings[i]); |
| 2074 | } | 2077 | } |
| 2075 | 2078 | ||
| @@ -2102,8 +2105,11 @@ static void i40e_vsi_free_rx_resources(struct i40e_vsi *vsi) | |||
| 2102 | { | 2105 | { |
| 2103 | int i; | 2106 | int i; |
| 2104 | 2107 | ||
| 2108 | if (!vsi->rx_rings) | ||
| 2109 | return; | ||
| 2110 | |||
| 2105 | for (i = 0; i < vsi->num_queue_pairs; i++) | 2111 | for (i = 0; i < vsi->num_queue_pairs; i++) |
| 2106 | if (vsi->rx_rings[i]->desc) | 2112 | if (vsi->rx_rings[i] && vsi->rx_rings[i]->desc) |
| 2107 | i40e_free_rx_resources(vsi->rx_rings[i]); | 2113 | i40e_free_rx_resources(vsi->rx_rings[i]); |
| 2108 | } | 2114 | } |
| 2109 | 2115 | ||
| @@ -2758,16 +2764,16 @@ static irqreturn_t i40e_intr(int irq, void *data) | |||
| 2758 | { | 2764 | { |
| 2759 | struct i40e_pf *pf = (struct i40e_pf *)data; | 2765 | struct i40e_pf *pf = (struct i40e_pf *)data; |
| 2760 | struct i40e_hw *hw = &pf->hw; | 2766 | struct i40e_hw *hw = &pf->hw; |
| 2767 | irqreturn_t ret = IRQ_NONE; | ||
| 2761 | u32 icr0, icr0_remaining; | 2768 | u32 icr0, icr0_remaining; |
| 2762 | u32 val, ena_mask; | 2769 | u32 val, ena_mask; |
| 2763 | 2770 | ||
| 2764 | icr0 = rd32(hw, I40E_PFINT_ICR0); | 2771 | icr0 = rd32(hw, I40E_PFINT_ICR0); |
| 2772 | ena_mask = rd32(hw, I40E_PFINT_ICR0_ENA); | ||
| 2765 | 2773 | ||
| 2766 | /* if sharing a legacy IRQ, we might get called w/o an intr pending */ | 2774 | /* if sharing a legacy IRQ, we might get called w/o an intr pending */ |
| 2767 | if ((icr0 & I40E_PFINT_ICR0_INTEVENT_MASK) == 0) | 2775 | if ((icr0 & I40E_PFINT_ICR0_INTEVENT_MASK) == 0) |
| 2768 | return IRQ_NONE; | 2776 | goto enable_intr; |
| 2769 | |||
| 2770 | ena_mask = rd32(hw, I40E_PFINT_ICR0_ENA); | ||
| 2771 | 2777 | ||
| 2772 | /* if interrupt but no bits showing, must be SWINT */ | 2778 | /* if interrupt but no bits showing, must be SWINT */ |
| 2773 | if (((icr0 & ~I40E_PFINT_ICR0_INTEVENT_MASK) == 0) || | 2779 | if (((icr0 & ~I40E_PFINT_ICR0_INTEVENT_MASK) == 0) || |
| @@ -2843,7 +2849,9 @@ static irqreturn_t i40e_intr(int irq, void *data) | |||
| 2843 | } | 2849 | } |
| 2844 | ena_mask &= ~icr0_remaining; | 2850 | ena_mask &= ~icr0_remaining; |
| 2845 | } | 2851 | } |
| 2852 | ret = IRQ_HANDLED; | ||
| 2846 | 2853 | ||
| 2854 | enable_intr: | ||
| 2847 | /* re-enable interrupt causes */ | 2855 | /* re-enable interrupt causes */ |
| 2848 | wr32(hw, I40E_PFINT_ICR0_ENA, ena_mask); | 2856 | wr32(hw, I40E_PFINT_ICR0_ENA, ena_mask); |
| 2849 | if (!test_bit(__I40E_DOWN, &pf->state)) { | 2857 | if (!test_bit(__I40E_DOWN, &pf->state)) { |
| @@ -2851,7 +2859,7 @@ static irqreturn_t i40e_intr(int irq, void *data) | |||
| 2851 | i40e_irq_dynamic_enable_icr0(pf); | 2859 | i40e_irq_dynamic_enable_icr0(pf); |
| 2852 | } | 2860 | } |
| 2853 | 2861 | ||
| 2854 | return IRQ_HANDLED; | 2862 | return ret; |
| 2855 | } | 2863 | } |
| 2856 | 2864 | ||
| 2857 | /** | 2865 | /** |
| @@ -4514,10 +4522,13 @@ static void i40e_clean_adminq_subtask(struct i40e_pf *pf) | |||
| 4514 | dev_info(&pf->pdev->dev, "ARQ LAN queue overflow event received\n"); | 4522 | dev_info(&pf->pdev->dev, "ARQ LAN queue overflow event received\n"); |
| 4515 | i40e_handle_lan_overflow_event(pf, &event); | 4523 | i40e_handle_lan_overflow_event(pf, &event); |
| 4516 | break; | 4524 | break; |
| 4525 | case i40e_aqc_opc_send_msg_to_peer: | ||
| 4526 | dev_info(&pf->pdev->dev, "ARQ: Msg from other pf\n"); | ||
| 4527 | break; | ||
| 4517 | default: | 4528 | default: |
| 4518 | dev_info(&pf->pdev->dev, | 4529 | dev_info(&pf->pdev->dev, |
| 4519 | "ARQ Error: Unknown event %d received\n", | 4530 | "ARQ Error: Unknown event 0x%04x received\n", |
| 4520 | event.desc.opcode); | 4531 | opcode); |
| 4521 | break; | 4532 | break; |
| 4522 | } | 4533 | } |
| 4523 | } while (pending && (i++ < pf->adminq_work_limit)); | 4534 | } while (pending && (i++ < pf->adminq_work_limit)); |
| @@ -4647,7 +4658,7 @@ static int i40e_get_capabilities(struct i40e_pf *pf) | |||
| 4647 | } | 4658 | } |
| 4648 | } while (err); | 4659 | } while (err); |
| 4649 | 4660 | ||
| 4650 | if (pf->hw.revision_id == 0 && pf->hw.func_caps.npar_enable) { | 4661 | if (pf->hw.revision_id == 0 && (pf->flags & I40E_FLAG_MFP_ENABLED)) { |
| 4651 | pf->hw.func_caps.num_msix_vectors += 1; | 4662 | pf->hw.func_caps.num_msix_vectors += 1; |
| 4652 | pf->hw.func_caps.num_tx_qp = | 4663 | pf->hw.func_caps.num_tx_qp = |
| 4653 | min_t(int, pf->hw.func_caps.num_tx_qp, | 4664 | min_t(int, pf->hw.func_caps.num_tx_qp, |
| @@ -4784,7 +4795,7 @@ static int i40e_prep_for_reset(struct i40e_pf *pf) | |||
| 4784 | } | 4795 | } |
| 4785 | 4796 | ||
| 4786 | /** | 4797 | /** |
| 4787 | * i40e_reset_and_rebuild - reset and rebuid using a saved config | 4798 | * i40e_reset_and_rebuild - reset and rebuild using a saved config |
| 4788 | * @pf: board private structure | 4799 | * @pf: board private structure |
| 4789 | * @reinit: if the Main VSI needs to re-initialized. | 4800 | * @reinit: if the Main VSI needs to re-initialized. |
| 4790 | **/ | 4801 | **/ |
| @@ -5348,7 +5359,7 @@ static void i40e_vsi_clear_rings(struct i40e_vsi *vsi) | |||
| 5348 | { | 5359 | { |
| 5349 | int i; | 5360 | int i; |
| 5350 | 5361 | ||
| 5351 | if (vsi->tx_rings[0]) { | 5362 | if (vsi->tx_rings && vsi->tx_rings[0]) { |
| 5352 | for (i = 0; i < vsi->alloc_queue_pairs; i++) { | 5363 | for (i = 0; i < vsi->alloc_queue_pairs; i++) { |
| 5353 | kfree_rcu(vsi->tx_rings[i], rcu); | 5364 | kfree_rcu(vsi->tx_rings[i], rcu); |
| 5354 | vsi->tx_rings[i] = NULL; | 5365 | vsi->tx_rings[i] = NULL; |
| @@ -5763,16 +5774,8 @@ int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count) | |||
| 5763 | queue_count = rounddown_pow_of_two(queue_count); | 5774 | queue_count = rounddown_pow_of_two(queue_count); |
| 5764 | 5775 | ||
| 5765 | if (queue_count != pf->rss_size) { | 5776 | if (queue_count != pf->rss_size) { |
| 5766 | if (pf->queues_left < (queue_count - pf->rss_size)) { | ||
| 5767 | dev_info(&pf->pdev->dev, | ||
| 5768 | "Not enough queues to do RSS on %d queues: remaining queues %d\n", | ||
| 5769 | queue_count, pf->queues_left); | ||
| 5770 | return pf->rss_size; | ||
| 5771 | } | ||
| 5772 | i40e_prep_for_reset(pf); | 5777 | i40e_prep_for_reset(pf); |
| 5773 | 5778 | ||
| 5774 | pf->num_lan_qps += (queue_count - pf->rss_size); | ||
| 5775 | pf->queues_left -= (queue_count - pf->rss_size); | ||
| 5776 | pf->rss_size = queue_count; | 5779 | pf->rss_size = queue_count; |
| 5777 | 5780 | ||
| 5778 | i40e_reset_and_rebuild(pf, true); | 5781 | i40e_reset_and_rebuild(pf, true); |
| @@ -5809,7 +5812,6 @@ static int i40e_sw_init(struct i40e_pf *pf) | |||
| 5809 | pf->flags = I40E_FLAG_RX_CSUM_ENABLED | | 5812 | pf->flags = I40E_FLAG_RX_CSUM_ENABLED | |
| 5810 | I40E_FLAG_MSI_ENABLED | | 5813 | I40E_FLAG_MSI_ENABLED | |
| 5811 | I40E_FLAG_MSIX_ENABLED | | 5814 | I40E_FLAG_MSIX_ENABLED | |
| 5812 | I40E_FLAG_RX_PS_ENABLED | | ||
| 5813 | I40E_FLAG_RX_1BUF_ENABLED; | 5815 | I40E_FLAG_RX_1BUF_ENABLED; |
| 5814 | 5816 | ||
| 5815 | /* Depending on PF configurations, it is possible that the RSS | 5817 | /* Depending on PF configurations, it is possible that the RSS |
| @@ -5825,6 +5827,12 @@ static int i40e_sw_init(struct i40e_pf *pf) | |||
| 5825 | pf->rss_size = 1; | 5827 | pf->rss_size = 1; |
| 5826 | } | 5828 | } |
| 5827 | 5829 | ||
| 5830 | /* MFP mode enabled */ | ||
| 5831 | if (pf->hw.func_caps.npar_enable || pf->hw.func_caps.mfp_mode_1) { | ||
| 5832 | pf->flags |= I40E_FLAG_MFP_ENABLED; | ||
| 5833 | dev_info(&pf->pdev->dev, "MFP mode Enabled\n"); | ||
| 5834 | } | ||
| 5835 | |||
| 5828 | if (pf->hw.func_caps.dcb) | 5836 | if (pf->hw.func_caps.dcb) |
| 5829 | pf->num_tc_qps = I40E_DEFAULT_QUEUES_PER_TC; | 5837 | pf->num_tc_qps = I40E_DEFAULT_QUEUES_PER_TC; |
| 5830 | else | 5838 | else |
| @@ -5853,12 +5861,6 @@ static int i40e_sw_init(struct i40e_pf *pf) | |||
| 5853 | pf->num_vmdq_qps = I40E_DEFAULT_QUEUES_PER_VMDQ; | 5861 | pf->num_vmdq_qps = I40E_DEFAULT_QUEUES_PER_VMDQ; |
| 5854 | } | 5862 | } |
| 5855 | 5863 | ||
| 5856 | /* MFP mode enabled */ | ||
| 5857 | if (pf->hw.func_caps.npar_enable || pf->hw.func_caps.mfp_mode_1) { | ||
| 5858 | pf->flags |= I40E_FLAG_MFP_ENABLED; | ||
| 5859 | dev_info(&pf->pdev->dev, "MFP mode Enabled\n"); | ||
| 5860 | } | ||
| 5861 | |||
| 5862 | #ifdef CONFIG_PCI_IOV | 5864 | #ifdef CONFIG_PCI_IOV |
| 5863 | if (pf->hw.func_caps.num_vfs) { | 5865 | if (pf->hw.func_caps.num_vfs) { |
| 5864 | pf->num_vf_qps = I40E_DEFAULT_QUEUES_PER_VF; | 5866 | pf->num_vf_qps = I40E_DEFAULT_QUEUES_PER_VF; |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index e2da0a2784dd..37d66c87abc9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_osdep.h b/drivers/net/ethernet/intel/i40e/i40e_osdep.h index 702c81ba86e3..ecd0f0b663c9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_osdep.h +++ b/drivers/net/ethernet/intel/i40e/i40e_osdep.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h index e05d303105a7..c7c3d8231b36 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_register.h b/drivers/net/ethernet/intel/i40e/i40e_register.h index d188ec03aff2..1d40f425acf1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_register.h +++ b/drivers/net/ethernet/intel/i40e/i40e_register.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_status.h b/drivers/net/ethernet/intel/i40e/i40e_status.h index 5e5bcddac573..5f9cac55aa55 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_status.h +++ b/drivers/net/ethernet/intel/i40e/i40e_status.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index fac4fb37f87b..43d88dd66ed4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
| @@ -775,7 +774,7 @@ void i40e_alloc_rx_buffers(struct i40e_ring *rx_ring, u16 cleaned_count) | |||
| 775 | skb = netdev_alloc_skb_ip_align(rx_ring->netdev, | 774 | skb = netdev_alloc_skb_ip_align(rx_ring->netdev, |
| 776 | rx_ring->rx_buf_len); | 775 | rx_ring->rx_buf_len); |
| 777 | if (!skb) { | 776 | if (!skb) { |
| 778 | rx_ring->rx_stats.alloc_rx_buff_failed++; | 777 | rx_ring->rx_stats.alloc_buff_failed++; |
| 779 | goto no_buffers; | 778 | goto no_buffers; |
| 780 | } | 779 | } |
| 781 | /* initialize queue mapping */ | 780 | /* initialize queue mapping */ |
| @@ -789,7 +788,7 @@ void i40e_alloc_rx_buffers(struct i40e_ring *rx_ring, u16 cleaned_count) | |||
| 789 | rx_ring->rx_buf_len, | 788 | rx_ring->rx_buf_len, |
| 790 | DMA_FROM_DEVICE); | 789 | DMA_FROM_DEVICE); |
| 791 | if (dma_mapping_error(rx_ring->dev, bi->dma)) { | 790 | if (dma_mapping_error(rx_ring->dev, bi->dma)) { |
| 792 | rx_ring->rx_stats.alloc_rx_buff_failed++; | 791 | rx_ring->rx_stats.alloc_buff_failed++; |
| 793 | bi->dma = 0; | 792 | bi->dma = 0; |
| 794 | goto no_buffers; | 793 | goto no_buffers; |
| 795 | } | 794 | } |
| @@ -799,7 +798,7 @@ void i40e_alloc_rx_buffers(struct i40e_ring *rx_ring, u16 cleaned_count) | |||
| 799 | if (!bi->page) { | 798 | if (!bi->page) { |
| 800 | bi->page = alloc_page(GFP_ATOMIC); | 799 | bi->page = alloc_page(GFP_ATOMIC); |
| 801 | if (!bi->page) { | 800 | if (!bi->page) { |
| 802 | rx_ring->rx_stats.alloc_rx_page_failed++; | 801 | rx_ring->rx_stats.alloc_page_failed++; |
| 803 | goto no_buffers; | 802 | goto no_buffers; |
| 804 | } | 803 | } |
| 805 | } | 804 | } |
| @@ -814,7 +813,7 @@ void i40e_alloc_rx_buffers(struct i40e_ring *rx_ring, u16 cleaned_count) | |||
| 814 | DMA_FROM_DEVICE); | 813 | DMA_FROM_DEVICE); |
| 815 | if (dma_mapping_error(rx_ring->dev, | 814 | if (dma_mapping_error(rx_ring->dev, |
| 816 | bi->page_dma)) { | 815 | bi->page_dma)) { |
| 817 | rx_ring->rx_stats.alloc_rx_page_failed++; | 816 | rx_ring->rx_stats.alloc_page_failed++; |
| 818 | bi->page_dma = 0; | 817 | bi->page_dma = 0; |
| 819 | goto no_buffers; | 818 | goto no_buffers; |
| 820 | } | 819 | } |
| @@ -991,15 +990,15 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget) | |||
| 991 | skb = rx_bi->skb; | 990 | skb = rx_bi->skb; |
| 992 | prefetch(skb->data); | 991 | prefetch(skb->data); |
| 993 | 992 | ||
| 994 | rx_packet_len = (qword & I40E_RXD_QW1_LENGTH_PBUF_MASK) | 993 | rx_packet_len = (qword & I40E_RXD_QW1_LENGTH_PBUF_MASK) >> |
| 995 | >> I40E_RXD_QW1_LENGTH_PBUF_SHIFT; | 994 | I40E_RXD_QW1_LENGTH_PBUF_SHIFT; |
| 996 | rx_header_len = (qword & I40E_RXD_QW1_LENGTH_HBUF_MASK) | 995 | rx_header_len = (qword & I40E_RXD_QW1_LENGTH_HBUF_MASK) >> |
| 997 | >> I40E_RXD_QW1_LENGTH_HBUF_SHIFT; | 996 | I40E_RXD_QW1_LENGTH_HBUF_SHIFT; |
| 998 | rx_sph = (qword & I40E_RXD_QW1_LENGTH_SPH_MASK) | 997 | rx_sph = (qword & I40E_RXD_QW1_LENGTH_SPH_MASK) >> |
| 999 | >> I40E_RXD_QW1_LENGTH_SPH_SHIFT; | 998 | I40E_RXD_QW1_LENGTH_SPH_SHIFT; |
| 1000 | 999 | ||
| 1001 | rx_error = (qword & I40E_RXD_QW1_ERROR_MASK) | 1000 | rx_error = (qword & I40E_RXD_QW1_ERROR_MASK) >> |
| 1002 | >> I40E_RXD_QW1_ERROR_SHIFT; | 1001 | I40E_RXD_QW1_ERROR_SHIFT; |
| 1003 | rx_hbo = rx_error & (1 << I40E_RX_DESC_ERROR_HBO_SHIFT); | 1002 | rx_hbo = rx_error & (1 << I40E_RX_DESC_ERROR_HBO_SHIFT); |
| 1004 | rx_error &= ~(1 << I40E_RX_DESC_ERROR_HBO_SHIFT); | 1003 | rx_error &= ~(1 << I40E_RX_DESC_ERROR_HBO_SHIFT); |
| 1005 | 1004 | ||
| @@ -1115,8 +1114,8 @@ next_desc: | |||
| 1115 | /* use prefetched values */ | 1114 | /* use prefetched values */ |
| 1116 | rx_desc = next_rxd; | 1115 | rx_desc = next_rxd; |
| 1117 | qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len); | 1116 | qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len); |
| 1118 | rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) | 1117 | rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >> |
| 1119 | >> I40E_RXD_QW1_STATUS_SHIFT; | 1118 | I40E_RXD_QW1_STATUS_SHIFT; |
| 1120 | } | 1119 | } |
| 1121 | 1120 | ||
| 1122 | rx_ring->next_to_clean = i; | 1121 | rx_ring->next_to_clean = i; |
| @@ -1415,10 +1414,10 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb, | |||
| 1415 | cd_cmd = I40E_TX_CTX_DESC_TSO; | 1414 | cd_cmd = I40E_TX_CTX_DESC_TSO; |
| 1416 | cd_tso_len = skb->len - *hdr_len; | 1415 | cd_tso_len = skb->len - *hdr_len; |
| 1417 | cd_mss = skb_shinfo(skb)->gso_size; | 1416 | cd_mss = skb_shinfo(skb)->gso_size; |
| 1418 | *cd_type_cmd_tso_mss |= ((u64)cd_cmd << I40E_TXD_CTX_QW1_CMD_SHIFT) | 1417 | *cd_type_cmd_tso_mss |= ((u64)cd_cmd << I40E_TXD_CTX_QW1_CMD_SHIFT) | |
| 1419 | | ((u64)cd_tso_len | 1418 | ((u64)cd_tso_len << |
| 1420 | << I40E_TXD_CTX_QW1_TSO_LEN_SHIFT) | 1419 | I40E_TXD_CTX_QW1_TSO_LEN_SHIFT) | |
| 1421 | | ((u64)cd_mss << I40E_TXD_CTX_QW1_MSS_SHIFT); | 1420 | ((u64)cd_mss << I40E_TXD_CTX_QW1_MSS_SHIFT); |
| 1422 | return 1; | 1421 | return 1; |
| 1423 | } | 1422 | } |
| 1424 | 1423 | ||
| @@ -1716,6 +1715,7 @@ dma_error: | |||
| 1716 | static inline int __i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size) | 1715 | static inline int __i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size) |
| 1717 | { | 1716 | { |
| 1718 | netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index); | 1717 | netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index); |
| 1718 | /* Memory barrier before checking head and tail */ | ||
| 1719 | smp_mb(); | 1719 | smp_mb(); |
| 1720 | 1720 | ||
| 1721 | /* Check again in a case another CPU has just made room available. */ | 1721 | /* Check again in a case another CPU has just made room available. */ |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index 92f5cf5079e1..6f8506c181d9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
| @@ -175,8 +174,8 @@ struct i40e_tx_queue_stats { | |||
| 175 | 174 | ||
| 176 | struct i40e_rx_queue_stats { | 175 | struct i40e_rx_queue_stats { |
| 177 | u64 non_eop_descs; | 176 | u64 non_eop_descs; |
| 178 | u64 alloc_rx_page_failed; | 177 | u64 alloc_page_failed; |
| 179 | u64 alloc_rx_buff_failed; | 178 | u64 alloc_buff_failed; |
| 180 | }; | 179 | }; |
| 181 | 180 | ||
| 182 | enum i40e_ring_state_t { | 181 | enum i40e_ring_state_t { |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index bcf031773568..12473ad5c8e6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
| @@ -77,8 +76,6 @@ | |||
| 77 | struct i40e_hw; | 76 | struct i40e_hw; |
| 78 | typedef void (*I40E_ADMINQ_CALLBACK)(struct i40e_hw *, struct i40e_aq_desc *); | 77 | typedef void (*I40E_ADMINQ_CALLBACK)(struct i40e_hw *, struct i40e_aq_desc *); |
| 79 | 78 | ||
| 80 | #define I40E_ETH_LENGTH_OF_ADDRESS 6 | ||
| 81 | |||
| 82 | /* Data type manipulation macros. */ | 79 | /* Data type manipulation macros. */ |
| 83 | 80 | ||
| 84 | #define I40E_DESC_UNUSED(R) \ | 81 | #define I40E_DESC_UNUSED(R) \ |
| @@ -240,9 +237,9 @@ struct i40e_hw_capabilities { | |||
| 240 | 237 | ||
| 241 | struct i40e_mac_info { | 238 | struct i40e_mac_info { |
| 242 | enum i40e_mac_type type; | 239 | enum i40e_mac_type type; |
| 243 | u8 addr[I40E_ETH_LENGTH_OF_ADDRESS]; | 240 | u8 addr[ETH_ALEN]; |
| 244 | u8 perm_addr[I40E_ETH_LENGTH_OF_ADDRESS]; | 241 | u8 perm_addr[ETH_ALEN]; |
| 245 | u8 san_addr[I40E_ETH_LENGTH_OF_ADDRESS]; | 242 | u8 san_addr[ETH_ALEN]; |
| 246 | u16 max_fcoeq; | 243 | u16 max_fcoeq; |
| 247 | }; | 244 | }; |
| 248 | 245 | ||
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h index cc6654f1dac7..22a1b69cd646 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
| @@ -142,7 +141,7 @@ struct i40e_virtchnl_vsi_resource { | |||
| 142 | u16 num_queue_pairs; | 141 | u16 num_queue_pairs; |
| 143 | enum i40e_vsi_type vsi_type; | 142 | enum i40e_vsi_type vsi_type; |
| 144 | u16 qset_handle; | 143 | u16 qset_handle; |
| 145 | u8 default_mac_addr[I40E_ETH_LENGTH_OF_ADDRESS]; | 144 | u8 default_mac_addr[ETH_ALEN]; |
| 146 | }; | 145 | }; |
| 147 | /* VF offload flags */ | 146 | /* VF offload flags */ |
| 148 | #define I40E_VIRTCHNL_VF_OFFLOAD_L2 0x00000001 | 147 | #define I40E_VIRTCHNL_VF_OFFLOAD_L2 0x00000001 |
| @@ -265,7 +264,7 @@ struct i40e_virtchnl_queue_select { | |||
| 265 | */ | 264 | */ |
| 266 | 265 | ||
| 267 | struct i40e_virtchnl_ether_addr { | 266 | struct i40e_virtchnl_ether_addr { |
| 268 | u8 addr[I40E_ETH_LENGTH_OF_ADDRESS]; | 267 | u8 addr[ETH_ALEN]; |
| 269 | u8 pad[2]; | 268 | u8 pad[2]; |
| 270 | }; | 269 | }; |
| 271 | 270 | ||
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index efb9a242d275..51a4f6125437 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
| @@ -177,7 +176,8 @@ static void i40e_config_irq_link_list(struct i40e_vf *vf, u16 vsi_idx, | |||
| 177 | (I40E_MAX_VSI_QP * | 176 | (I40E_MAX_VSI_QP * |
| 178 | I40E_VIRTCHNL_SUPPORTED_QTYPES), | 177 | I40E_VIRTCHNL_SUPPORTED_QTYPES), |
| 179 | next_q + 1); | 178 | next_q + 1); |
| 180 | if (next_q < (I40E_MAX_VSI_QP * I40E_VIRTCHNL_SUPPORTED_QTYPES)) { | 179 | if (next_q < |
| 180 | (I40E_MAX_VSI_QP * I40E_VIRTCHNL_SUPPORTED_QTYPES)) { | ||
| 181 | vsi_queue_id = next_q / I40E_VIRTCHNL_SUPPORTED_QTYPES; | 181 | vsi_queue_id = next_q / I40E_VIRTCHNL_SUPPORTED_QTYPES; |
| 182 | qtype = next_q % I40E_VIRTCHNL_SUPPORTED_QTYPES; | 182 | qtype = next_q % I40E_VIRTCHNL_SUPPORTED_QTYPES; |
| 183 | pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_idx, | 183 | pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_idx, |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h index 8d0f4dd2a252..cc1feee36e12 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /******************************************************************************* | 1 | /******************************************************************************* |
| 2 | * | 2 | * |
| 3 | * Intel Ethernet Controller XL710 Family Linux Driver | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | * Copyright(c) 2013 Intel Corporation. | 4 | * Copyright(c) 2013 - 2014 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -12,9 +12,8 @@ | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. | 13 | * more details. |
| 14 | * | 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with | 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | * | 17 | * |
| 19 | * The full GNU General Public License is included in this distribution in | 18 | * The full GNU General Public License is included in this distribution in |
| 20 | * the file called "COPYING". | 19 | * the file called "COPYING". |
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig index 2a30193d0d50..2dc82f1d2e70 100644 --- a/drivers/net/irda/Kconfig +++ b/drivers/net/irda/Kconfig | |||
| @@ -62,8 +62,6 @@ config SIR_BFIN_PIO | |||
| 62 | bool "PIO mode" | 62 | bool "PIO mode" |
| 63 | endchoice | 63 | endchoice |
| 64 | 64 | ||
| 65 | comment "Dongle support" | ||
| 66 | |||
| 67 | config SH_SIR | 65 | config SH_SIR |
| 68 | tristate "SuperH SIR on UART" | 66 | tristate "SuperH SIR on UART" |
| 69 | depends on IRDA && SUPERH && \ | 67 | depends on IRDA && SUPERH && \ |
| @@ -74,6 +72,8 @@ config SH_SIR | |||
| 74 | Say Y here if your want to enable SIR function on SuperH UART | 72 | Say Y here if your want to enable SIR function on SuperH UART |
| 75 | devices. | 73 | devices. |
| 76 | 74 | ||
| 75 | comment "Dongle support" | ||
| 76 | |||
| 77 | config DONGLE | 77 | config DONGLE |
| 78 | bool "Serial dongle support" | 78 | bool "Serial dongle support" |
| 79 | depends on IRTTY_SIR | 79 | depends on IRTTY_SIR |
diff --git a/drivers/net/irda/sh_irda.c b/drivers/net/irda/sh_irda.c index ff45cd0d60e8..c96b46b2c3a8 100644 --- a/drivers/net/irda/sh_irda.c +++ b/drivers/net/irda/sh_irda.c | |||
| @@ -804,7 +804,7 @@ static int sh_irda_probe(struct platform_device *pdev) | |||
| 804 | goto err_mem_4; | 804 | goto err_mem_4; |
| 805 | 805 | ||
| 806 | platform_set_drvdata(pdev, ndev); | 806 | platform_set_drvdata(pdev, ndev); |
| 807 | err = request_irq(irq, sh_irda_irq, 0, "sh_irda", self); | 807 | err = devm_request_irq(&pdev->dev, irq, sh_irda_irq, 0, "sh_irda", self); |
| 808 | if (err) { | 808 | if (err) { |
| 809 | dev_warn(&pdev->dev, "Unable to attach sh_irda interrupt\n"); | 809 | dev_warn(&pdev->dev, "Unable to attach sh_irda interrupt\n"); |
| 810 | goto err_mem_4; | 810 | goto err_mem_4; |
diff --git a/drivers/net/irda/sh_sir.c b/drivers/net/irda/sh_sir.c index 8d9ae5a086d5..cadf52e22464 100644 --- a/drivers/net/irda/sh_sir.c +++ b/drivers/net/irda/sh_sir.c | |||
| @@ -761,7 +761,7 @@ static int sh_sir_probe(struct platform_device *pdev) | |||
| 761 | goto err_mem_4; | 761 | goto err_mem_4; |
| 762 | 762 | ||
| 763 | platform_set_drvdata(pdev, ndev); | 763 | platform_set_drvdata(pdev, ndev); |
| 764 | err = request_irq(irq, sh_sir_irq, 0, "sh_sir", self); | 764 | err = devm_request_irq(&pdev->dev, irq, sh_sir_irq, 0, "sh_sir", self); |
| 765 | if (err) { | 765 | if (err) { |
| 766 | dev_warn(&pdev->dev, "Unable to attach sh_sir interrupt\n"); | 766 | dev_warn(&pdev->dev, "Unable to attach sh_sir interrupt\n"); |
| 767 | goto err_mem_4; | 767 | goto err_mem_4; |
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 1d40c69cc4a9..55eda7afc041 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | * more details. | 15 | * more details. |
| 16 | */ | 16 | */ |
| 17 | 17 | ||
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
| 20 | #include <linux/if.h> | 19 | #include <linux/if.h> |
| 21 | #include <linux/skbuff.h> | 20 | #include <linux/skbuff.h> |
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index 14128fd265ac..7e9ede6c5798 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c | |||
| @@ -23,7 +23,6 @@ | |||
| 23 | #ifdef __IN_PCMCIA_PACKAGE__ | 23 | #ifdef __IN_PCMCIA_PACKAGE__ |
| 24 | #include <pcmcia/k_compat.h> | 24 | #include <pcmcia/k_compat.h> |
| 25 | #endif | 25 | #endif |
| 26 | #include <linux/init.h> | ||
| 27 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
| 28 | #include <linux/module.h> | 27 | #include <linux/module.h> |
| 29 | #include <linux/ptrace.h> | 28 | #include <linux/ptrace.h> |
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 34c8a33cac06..031d4ec64779 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c | |||
| @@ -1721,7 +1721,7 @@ static void at76_mac80211_tx(struct ieee80211_hw *hw, | |||
| 1721 | * following workaround is necessary. If the TX frame is an | 1721 | * following workaround is necessary. If the TX frame is an |
| 1722 | * authentication frame extract the bssid and send the CMD_JOIN. */ | 1722 | * authentication frame extract the bssid and send the CMD_JOIN. */ |
| 1723 | if (mgmt->frame_control & cpu_to_le16(IEEE80211_STYPE_AUTH)) { | 1723 | if (mgmt->frame_control & cpu_to_le16(IEEE80211_STYPE_AUTH)) { |
| 1724 | if (!ether_addr_equal(priv->bssid, mgmt->bssid)) { | 1724 | if (!ether_addr_equal_64bits(priv->bssid, mgmt->bssid)) { |
| 1725 | memcpy(priv->bssid, mgmt->bssid, ETH_ALEN); | 1725 | memcpy(priv->bssid, mgmt->bssid, ETH_ALEN); |
| 1726 | ieee80211_queue_work(hw, &priv->work_join_bssid); | 1726 | ieee80211_queue_work(hw, &priv->work_join_bssid); |
| 1727 | dev_kfree_skb_any(skb); | 1727 | dev_kfree_skb_any(skb); |
diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c index 280fc3d53a36..8aa20df55e50 100644 --- a/drivers/net/wireless/ath/ar5523/ar5523.c +++ b/drivers/net/wireless/ath/ar5523/ar5523.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | * that and only has minimal functionality. | 25 | * that and only has minimal functionality. |
| 26 | */ | 26 | */ |
| 27 | #include <linux/compiler.h> | 27 | #include <linux/compiler.h> |
| 28 | #include <linux/init.h> | ||
| 29 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
| 30 | #include <linux/module.h> | 29 | #include <linux/module.h> |
| 31 | #include <linux/list.h> | 30 | #include <linux/list.h> |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 69f58b073e85..6396ad4bce67 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
| @@ -1245,7 +1245,7 @@ ath5k_check_ibss_tsf(struct ath5k_hw *ah, struct sk_buff *skb, | |||
| 1245 | 1245 | ||
| 1246 | if (ieee80211_is_beacon(mgmt->frame_control) && | 1246 | if (ieee80211_is_beacon(mgmt->frame_control) && |
| 1247 | le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && | 1247 | le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && |
| 1248 | ether_addr_equal(mgmt->bssid, common->curbssid)) { | 1248 | ether_addr_equal_64bits(mgmt->bssid, common->curbssid)) { |
| 1249 | /* | 1249 | /* |
| 1250 | * Received an IBSS beacon with the same BSSID. Hardware *must* | 1250 | * Received an IBSS beacon with the same BSSID. Hardware *must* |
| 1251 | * have updated the local TSF. We have to work around various | 1251 | * have updated the local TSF. We have to work around various |
| @@ -1309,7 +1309,7 @@ ath5k_update_beacon_rssi(struct ath5k_hw *ah, struct sk_buff *skb, int rssi) | |||
| 1309 | 1309 | ||
| 1310 | /* only beacons from our BSSID */ | 1310 | /* only beacons from our BSSID */ |
| 1311 | if (!ieee80211_is_beacon(mgmt->frame_control) || | 1311 | if (!ieee80211_is_beacon(mgmt->frame_control) || |
| 1312 | !ether_addr_equal(mgmt->bssid, common->curbssid)) | 1312 | !ether_addr_equal_64bits(mgmt->bssid, common->curbssid)) |
| 1313 | return; | 1313 | return; |
| 1314 | 1314 | ||
| 1315 | ewma_add(&ah->ah_beacon_rssi_avg, rssi); | 1315 | ewma_add(&ah->ah_beacon_rssi_avg, rssi); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index 149aba3c7298..d480d2f3e185 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c | |||
| @@ -383,6 +383,20 @@ void ar9002_hw_enable_async_fifo(struct ath_hw *ah) | |||
| 383 | } | 383 | } |
| 384 | } | 384 | } |
| 385 | 385 | ||
| 386 | static void ar9002_hw_init_hang_checks(struct ath_hw *ah) | ||
| 387 | { | ||
| 388 | if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) { | ||
| 389 | ah->config.hw_hang_checks |= HW_BB_RIFS_HANG; | ||
| 390 | ah->config.hw_hang_checks |= HW_BB_DFS_HANG; | ||
| 391 | } | ||
| 392 | |||
| 393 | if (AR_SREV_9280(ah)) | ||
| 394 | ah->config.hw_hang_checks |= HW_BB_RX_CLEAR_STUCK_HANG; | ||
| 395 | |||
| 396 | if (AR_SREV_5416(ah) || AR_SREV_9100(ah) || AR_SREV_9160(ah)) | ||
| 397 | ah->config.hw_hang_checks |= HW_MAC_HANG; | ||
| 398 | } | ||
| 399 | |||
| 386 | /* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */ | 400 | /* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */ |
| 387 | int ar9002_hw_attach_ops(struct ath_hw *ah) | 401 | int ar9002_hw_attach_ops(struct ath_hw *ah) |
| 388 | { | 402 | { |
| @@ -395,6 +409,7 @@ int ar9002_hw_attach_ops(struct ath_hw *ah) | |||
| 395 | return ret; | 409 | return ret; |
| 396 | 410 | ||
| 397 | priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs; | 411 | priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs; |
| 412 | priv_ops->init_hang_checks = ar9002_hw_init_hang_checks; | ||
| 398 | 413 | ||
| 399 | ops->config_pci_powersave = ar9002_hw_configpcipowersave; | 414 | ops->config_pci_powersave = ar9002_hw_configpcipowersave; |
| 400 | 415 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 97e09d5f3a42..8c145cd98c1c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
| @@ -326,6 +326,224 @@ static void ar9003_hw_init_cal_settings(struct ath_hw *ah) | |||
| 326 | ah->supp_cals = IQ_MISMATCH_CAL; | 326 | ah->supp_cals = IQ_MISMATCH_CAL; |
| 327 | } | 327 | } |
| 328 | 328 | ||
| 329 | #define OFF_UPPER_LT 24 | ||
| 330 | #define OFF_LOWER_LT 7 | ||
| 331 | |||
| 332 | static bool ar9003_hw_dynamic_osdac_selection(struct ath_hw *ah, | ||
| 333 | bool txiqcal_done) | ||
| 334 | { | ||
| 335 | struct ath_common *common = ath9k_hw_common(ah); | ||
| 336 | int ch0_done, osdac_ch0, dc_off_ch0_i1, dc_off_ch0_q1, dc_off_ch0_i2, | ||
| 337 | dc_off_ch0_q2, dc_off_ch0_i3, dc_off_ch0_q3; | ||
| 338 | int ch1_done, osdac_ch1, dc_off_ch1_i1, dc_off_ch1_q1, dc_off_ch1_i2, | ||
| 339 | dc_off_ch1_q2, dc_off_ch1_i3, dc_off_ch1_q3; | ||
| 340 | int ch2_done, osdac_ch2, dc_off_ch2_i1, dc_off_ch2_q1, dc_off_ch2_i2, | ||
| 341 | dc_off_ch2_q2, dc_off_ch2_i3, dc_off_ch2_q3; | ||
| 342 | bool status; | ||
| 343 | u32 temp, val; | ||
| 344 | |||
| 345 | /* | ||
| 346 | * Clear offset and IQ calibration, run AGC cal. | ||
| 347 | */ | ||
| 348 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | ||
| 349 | AR_PHY_AGC_CONTROL_OFFSET_CAL); | ||
| 350 | REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0, | ||
| 351 | AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL); | ||
| 352 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, | ||
| 353 | REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL); | ||
| 354 | |||
| 355 | status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, | ||
| 356 | AR_PHY_AGC_CONTROL_CAL, | ||
| 357 | 0, AH_WAIT_TIMEOUT); | ||
| 358 | if (!status) { | ||
| 359 | ath_dbg(common, CALIBRATE, | ||
| 360 | "AGC cal without offset cal failed to complete in 1ms"); | ||
| 361 | return false; | ||
| 362 | } | ||
| 363 | |||
| 364 | /* | ||
| 365 | * Allow only offset calibration and disable the others | ||
| 366 | * (Carrier Leak calibration, TX Filter calibration and | ||
| 367 | * Peak Detector offset calibration). | ||
| 368 | */ | ||
| 369 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, | ||
| 370 | AR_PHY_AGC_CONTROL_OFFSET_CAL); | ||
| 371 | REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, | ||
| 372 | AR_PHY_CL_CAL_ENABLE); | ||
| 373 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | ||
| 374 | AR_PHY_AGC_CONTROL_FLTR_CAL); | ||
| 375 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | ||
| 376 | AR_PHY_AGC_CONTROL_PKDET_CAL); | ||
| 377 | |||
| 378 | ch0_done = 0; | ||
| 379 | ch1_done = 0; | ||
| 380 | ch2_done = 0; | ||
| 381 | |||
| 382 | while ((ch0_done == 0) || (ch1_done == 0) || (ch2_done == 0)) { | ||
| 383 | osdac_ch0 = (REG_READ(ah, AR_PHY_65NM_CH0_BB1) >> 30) & 0x3; | ||
| 384 | osdac_ch1 = (REG_READ(ah, AR_PHY_65NM_CH1_BB1) >> 30) & 0x3; | ||
| 385 | osdac_ch2 = (REG_READ(ah, AR_PHY_65NM_CH2_BB1) >> 30) & 0x3; | ||
| 386 | |||
| 387 | REG_SET_BIT(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); | ||
| 388 | |||
| 389 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, | ||
| 390 | REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL); | ||
| 391 | |||
| 392 | status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, | ||
| 393 | AR_PHY_AGC_CONTROL_CAL, | ||
| 394 | 0, AH_WAIT_TIMEOUT); | ||
| 395 | if (!status) { | ||
| 396 | ath_dbg(common, CALIBRATE, | ||
| 397 | "DC offset cal failed to complete in 1ms"); | ||
| 398 | return false; | ||
| 399 | } | ||
| 400 | |||
| 401 | REG_CLR_BIT(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); | ||
| 402 | |||
| 403 | /* | ||
| 404 | * High gain. | ||
| 405 | */ | ||
| 406 | REG_WRITE(ah, AR_PHY_65NM_CH0_BB3, | ||
| 407 | ((REG_READ(ah, AR_PHY_65NM_CH0_BB3) & 0xfffffcff) | (1 << 8))); | ||
| 408 | REG_WRITE(ah, AR_PHY_65NM_CH1_BB3, | ||
| 409 | ((REG_READ(ah, AR_PHY_65NM_CH1_BB3) & 0xfffffcff) | (1 << 8))); | ||
| 410 | REG_WRITE(ah, AR_PHY_65NM_CH2_BB3, | ||
| 411 | ((REG_READ(ah, AR_PHY_65NM_CH2_BB3) & 0xfffffcff) | (1 << 8))); | ||
| 412 | |||
| 413 | temp = REG_READ(ah, AR_PHY_65NM_CH0_BB3); | ||
| 414 | dc_off_ch0_i1 = (temp >> 26) & 0x1f; | ||
| 415 | dc_off_ch0_q1 = (temp >> 21) & 0x1f; | ||
| 416 | |||
| 417 | temp = REG_READ(ah, AR_PHY_65NM_CH1_BB3); | ||
| 418 | dc_off_ch1_i1 = (temp >> 26) & 0x1f; | ||
| 419 | dc_off_ch1_q1 = (temp >> 21) & 0x1f; | ||
| 420 | |||
| 421 | temp = REG_READ(ah, AR_PHY_65NM_CH2_BB3); | ||
| 422 | dc_off_ch2_i1 = (temp >> 26) & 0x1f; | ||
| 423 | dc_off_ch2_q1 = (temp >> 21) & 0x1f; | ||
| 424 | |||
| 425 | /* | ||
| 426 | * Low gain. | ||
| 427 | */ | ||
| 428 | REG_WRITE(ah, AR_PHY_65NM_CH0_BB3, | ||
| 429 | ((REG_READ(ah, AR_PHY_65NM_CH0_BB3) & 0xfffffcff) | (2 << 8))); | ||
| 430 | REG_WRITE(ah, AR_PHY_65NM_CH1_BB3, | ||
| 431 | ((REG_READ(ah, AR_PHY_65NM_CH1_BB3) & 0xfffffcff) | (2 << 8))); | ||
| 432 | REG_WRITE(ah, AR_PHY_65NM_CH2_BB3, | ||
| 433 | ((REG_READ(ah, AR_PHY_65NM_CH2_BB3) & 0xfffffcff) | (2 << 8))); | ||
| 434 | |||
| 435 | temp = REG_READ(ah, AR_PHY_65NM_CH0_BB3); | ||
| 436 | dc_off_ch0_i2 = (temp >> 26) & 0x1f; | ||
| 437 | dc_off_ch0_q2 = (temp >> 21) & 0x1f; | ||
| 438 | |||
| 439 | temp = REG_READ(ah, AR_PHY_65NM_CH1_BB3); | ||
| 440 | dc_off_ch1_i2 = (temp >> 26) & 0x1f; | ||
| 441 | dc_off_ch1_q2 = (temp >> 21) & 0x1f; | ||
| 442 | |||
| 443 | temp = REG_READ(ah, AR_PHY_65NM_CH2_BB3); | ||
| 444 | dc_off_ch2_i2 = (temp >> 26) & 0x1f; | ||
| 445 | dc_off_ch2_q2 = (temp >> 21) & 0x1f; | ||
| 446 | |||
| 447 | /* | ||
| 448 | * Loopback. | ||
| 449 | */ | ||
| 450 | REG_WRITE(ah, AR_PHY_65NM_CH0_BB3, | ||
| 451 | ((REG_READ(ah, AR_PHY_65NM_CH0_BB3) & 0xfffffcff) | (3 << 8))); | ||
| 452 | REG_WRITE(ah, AR_PHY_65NM_CH1_BB3, | ||
| 453 | ((REG_READ(ah, AR_PHY_65NM_CH1_BB3) & 0xfffffcff) | (3 << 8))); | ||
| 454 | REG_WRITE(ah, AR_PHY_65NM_CH2_BB3, | ||
| 455 | ((REG_READ(ah, AR_PHY_65NM_CH2_BB3) & 0xfffffcff) | (3 << 8))); | ||
| 456 | |||
| 457 | temp = REG_READ(ah, AR_PHY_65NM_CH0_BB3); | ||
| 458 | dc_off_ch0_i3 = (temp >> 26) & 0x1f; | ||
| 459 | dc_off_ch0_q3 = (temp >> 21) & 0x1f; | ||
| 460 | |||
| 461 | temp = REG_READ(ah, AR_PHY_65NM_CH1_BB3); | ||
| 462 | dc_off_ch1_i3 = (temp >> 26) & 0x1f; | ||
| 463 | dc_off_ch1_q3 = (temp >> 21) & 0x1f; | ||
| 464 | |||
| 465 | temp = REG_READ(ah, AR_PHY_65NM_CH2_BB3); | ||
| 466 | dc_off_ch2_i3 = (temp >> 26) & 0x1f; | ||
| 467 | dc_off_ch2_q3 = (temp >> 21) & 0x1f; | ||
| 468 | |||
| 469 | if ((dc_off_ch0_i1 > OFF_UPPER_LT) || (dc_off_ch0_i1 < OFF_LOWER_LT) || | ||
| 470 | (dc_off_ch0_i2 > OFF_UPPER_LT) || (dc_off_ch0_i2 < OFF_LOWER_LT) || | ||
| 471 | (dc_off_ch0_i3 > OFF_UPPER_LT) || (dc_off_ch0_i3 < OFF_LOWER_LT) || | ||
| 472 | (dc_off_ch0_q1 > OFF_UPPER_LT) || (dc_off_ch0_q1 < OFF_LOWER_LT) || | ||
| 473 | (dc_off_ch0_q2 > OFF_UPPER_LT) || (dc_off_ch0_q2 < OFF_LOWER_LT) || | ||
| 474 | (dc_off_ch0_q3 > OFF_UPPER_LT) || (dc_off_ch0_q3 < OFF_LOWER_LT)) { | ||
| 475 | if (osdac_ch0 == 3) { | ||
| 476 | ch0_done = 1; | ||
| 477 | } else { | ||
| 478 | osdac_ch0++; | ||
| 479 | |||
| 480 | val = REG_READ(ah, AR_PHY_65NM_CH0_BB1) & 0x3fffffff; | ||
| 481 | val |= (osdac_ch0 << 30); | ||
| 482 | REG_WRITE(ah, AR_PHY_65NM_CH0_BB1, val); | ||
| 483 | |||
| 484 | ch0_done = 0; | ||
| 485 | } | ||
| 486 | } else { | ||
| 487 | ch0_done = 1; | ||
| 488 | } | ||
| 489 | |||
| 490 | if ((dc_off_ch1_i1 > OFF_UPPER_LT) || (dc_off_ch1_i1 < OFF_LOWER_LT) || | ||
| 491 | (dc_off_ch1_i2 > OFF_UPPER_LT) || (dc_off_ch1_i2 < OFF_LOWER_LT) || | ||
| 492 | (dc_off_ch1_i3 > OFF_UPPER_LT) || (dc_off_ch1_i3 < OFF_LOWER_LT) || | ||
| 493 | (dc_off_ch1_q1 > OFF_UPPER_LT) || (dc_off_ch1_q1 < OFF_LOWER_LT) || | ||
| 494 | (dc_off_ch1_q2 > OFF_UPPER_LT) || (dc_off_ch1_q2 < OFF_LOWER_LT) || | ||
| 495 | (dc_off_ch1_q3 > OFF_UPPER_LT) || (dc_off_ch1_q3 < OFF_LOWER_LT)) { | ||
| 496 | if (osdac_ch1 == 3) { | ||
| 497 | ch1_done = 1; | ||
| 498 | } else { | ||
| 499 | osdac_ch1++; | ||
| 500 | |||
| 501 | val = REG_READ(ah, AR_PHY_65NM_CH1_BB1) & 0x3fffffff; | ||
| 502 | val |= (osdac_ch1 << 30); | ||
| 503 | REG_WRITE(ah, AR_PHY_65NM_CH1_BB1, val); | ||
| 504 | |||
| 505 | ch1_done = 0; | ||
| 506 | } | ||
| 507 | } else { | ||
| 508 | ch1_done = 1; | ||
| 509 | } | ||
| 510 | |||
| 511 | if ((dc_off_ch2_i1 > OFF_UPPER_LT) || (dc_off_ch2_i1 < OFF_LOWER_LT) || | ||
| 512 | (dc_off_ch2_i2 > OFF_UPPER_LT) || (dc_off_ch2_i2 < OFF_LOWER_LT) || | ||
| 513 | (dc_off_ch2_i3 > OFF_UPPER_LT) || (dc_off_ch2_i3 < OFF_LOWER_LT) || | ||
| 514 | (dc_off_ch2_q1 > OFF_UPPER_LT) || (dc_off_ch2_q1 < OFF_LOWER_LT) || | ||
| 515 | (dc_off_ch2_q2 > OFF_UPPER_LT) || (dc_off_ch2_q2 < OFF_LOWER_LT) || | ||
| 516 | (dc_off_ch2_q3 > OFF_UPPER_LT) || (dc_off_ch2_q3 < OFF_LOWER_LT)) { | ||
| 517 | if (osdac_ch2 == 3) { | ||
| 518 | ch2_done = 1; | ||
| 519 | } else { | ||
| 520 | osdac_ch2++; | ||
| 521 | |||
| 522 | val = REG_READ(ah, AR_PHY_65NM_CH2_BB1) & 0x3fffffff; | ||
| 523 | val |= (osdac_ch2 << 30); | ||
| 524 | REG_WRITE(ah, AR_PHY_65NM_CH2_BB1, val); | ||
| 525 | |||
| 526 | ch2_done = 0; | ||
| 527 | } | ||
| 528 | } else { | ||
| 529 | ch2_done = 1; | ||
| 530 | } | ||
| 531 | } | ||
| 532 | |||
| 533 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | ||
| 534 | AR_PHY_AGC_CONTROL_OFFSET_CAL); | ||
| 535 | REG_SET_BIT(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); | ||
| 536 | |||
| 537 | /* | ||
| 538 | * We don't need to check txiqcal_done here since it is always | ||
| 539 | * set for AR9550. | ||
| 540 | */ | ||
| 541 | REG_SET_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0, | ||
| 542 | AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL); | ||
| 543 | |||
| 544 | return true; | ||
| 545 | } | ||
| 546 | |||
| 329 | /* | 547 | /* |
| 330 | * solve 4x4 linear equation used in loopback iq cal. | 548 | * solve 4x4 linear equation used in loopback iq cal. |
| 331 | */ | 549 | */ |
| @@ -1271,6 +1489,11 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, | |||
| 1271 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); | 1489 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); |
| 1272 | } | 1490 | } |
| 1273 | 1491 | ||
| 1492 | if (AR_SREV_9550(ah) && IS_CHAN_2GHZ(chan)) { | ||
| 1493 | if (!ar9003_hw_dynamic_osdac_selection(ah, txiqcal_done)) | ||
| 1494 | return false; | ||
| 1495 | } | ||
| 1496 | |||
| 1274 | skip_tx_iqcal: | 1497 | skip_tx_iqcal: |
| 1275 | if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { | 1498 | if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { |
| 1276 | if (AR_SREV_9330_11(ah)) | 1499 | if (AR_SREV_9330_11(ah)) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index c8d22eccfef8..25243cbc07f0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
| @@ -3598,7 +3598,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) | |||
| 3598 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { | 3598 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { |
| 3599 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, | 3599 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, |
| 3600 | AR_SWITCH_TABLE_COM_AR9462_ALL, value); | 3600 | AR_SWITCH_TABLE_COM_AR9462_ALL, value); |
| 3601 | } else if (AR_SREV_9550(ah)) { | 3601 | } else if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) { |
| 3602 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, | 3602 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, |
| 3603 | AR_SWITCH_TABLE_COM_AR9550_ALL, value); | 3603 | AR_SWITCH_TABLE_COM_AR9550_ALL, value); |
| 3604 | } else | 3604 | } else |
| @@ -3975,7 +3975,7 @@ static void ar9003_hw_apply_tuning_caps(struct ath_hw *ah) | |||
| 3975 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; | 3975 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; |
| 3976 | u8 tuning_caps_param = eep->baseEepHeader.params_for_tuning_caps[0]; | 3976 | u8 tuning_caps_param = eep->baseEepHeader.params_for_tuning_caps[0]; |
| 3977 | 3977 | ||
| 3978 | if (AR_SREV_9340(ah)) | 3978 | if (AR_SREV_9340(ah) || AR_SREV_9531(ah)) |
| 3979 | return; | 3979 | return; |
| 3980 | 3980 | ||
| 3981 | if (eep->baseEepHeader.featureEnable & 0x40) { | 3981 | if (eep->baseEepHeader.featureEnable & 0x40) { |
| @@ -4030,7 +4030,10 @@ static void ar9003_hw_xpa_timing_control_apply(struct ath_hw *ah, bool is2ghz) | |||
| 4030 | if (!(eep->baseEepHeader.featureEnable & 0x80)) | 4030 | if (!(eep->baseEepHeader.featureEnable & 0x80)) |
| 4031 | return; | 4031 | return; |
| 4032 | 4032 | ||
| 4033 | if (!AR_SREV_9300(ah) && !AR_SREV_9340(ah) && !AR_SREV_9580(ah)) | 4033 | if (!AR_SREV_9300(ah) && |
| 4034 | !AR_SREV_9340(ah) && | ||
| 4035 | !AR_SREV_9580(ah) && | ||
| 4036 | !AR_SREV_9531(ah)) | ||
| 4034 | return; | 4037 | return; |
| 4035 | 4038 | ||
| 4036 | xpa_ctl = ar9003_modal_header(ah, is2ghz)->txFrameToXpaOn; | 4039 | xpa_ctl = ar9003_modal_header(ah, is2ghz)->txFrameToXpaOn; |
| @@ -4163,7 +4166,7 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah, | |||
| 4163 | ar9003_hw_xlna_bias_strength_apply(ah, is2ghz); | 4166 | ar9003_hw_xlna_bias_strength_apply(ah, is2ghz); |
| 4164 | ar9003_hw_atten_apply(ah, chan); | 4167 | ar9003_hw_atten_apply(ah, chan); |
| 4165 | ar9003_hw_quick_drop_apply(ah, chan->channel); | 4168 | ar9003_hw_quick_drop_apply(ah, chan->channel); |
| 4166 | if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah)) | 4169 | if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah) && !AR_SREV_9531(ah)) |
| 4167 | ar9003_hw_internal_regulator_apply(ah); | 4170 | ar9003_hw_internal_regulator_apply(ah); |
| 4168 | ar9003_hw_apply_tuning_caps(ah); | 4171 | ar9003_hw_apply_tuning_caps(ah); |
| 4169 | ar9003_hw_apply_minccapwr_thresh(ah, chan); | 4172 | ar9003_hw_apply_minccapwr_thresh(ah, chan); |
| @@ -4788,7 +4791,7 @@ static void ar9003_hw_power_control_override(struct ath_hw *ah, | |||
| 4788 | } | 4791 | } |
| 4789 | 4792 | ||
| 4790 | tempslope: | 4793 | tempslope: |
| 4791 | if (AR_SREV_9550(ah)) { | 4794 | if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) { |
| 4792 | /* | 4795 | /* |
| 4793 | * AR955x has tempSlope register for each chain. | 4796 | * AR955x has tempSlope register for each chain. |
| 4794 | * Check whether temp_compensation feature is enabled or not. | 4797 | * Check whether temp_compensation feature is enabled or not. |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 29613ebbc5d7..ec1da0cc25f5 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include "ar9462_2p1_initvals.h" | 28 | #include "ar9462_2p1_initvals.h" |
| 29 | #include "ar9565_1p0_initvals.h" | 29 | #include "ar9565_1p0_initvals.h" |
| 30 | #include "ar9565_1p1_initvals.h" | 30 | #include "ar9565_1p1_initvals.h" |
| 31 | #include "ar953x_initvals.h" | ||
| 31 | 32 | ||
| 32 | /* General hardware code for the AR9003 hadware family */ | 33 | /* General hardware code for the AR9003 hadware family */ |
| 33 | 34 | ||
| @@ -308,6 +309,31 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | |||
| 308 | /* Fast clock modal settings */ | 309 | /* Fast clock modal settings */ |
| 309 | INIT_INI_ARRAY(&ah->iniModesFastClock, | 310 | INIT_INI_ARRAY(&ah->iniModesFastClock, |
| 310 | ar955x_1p0_modes_fast_clock); | 311 | ar955x_1p0_modes_fast_clock); |
| 312 | } else if (AR_SREV_9531(ah)) { | ||
| 313 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], | ||
| 314 | qca953x_1p0_mac_core); | ||
| 315 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], | ||
| 316 | qca953x_1p0_mac_postamble); | ||
| 317 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], | ||
| 318 | qca953x_1p0_baseband_core); | ||
| 319 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], | ||
| 320 | qca953x_1p0_baseband_postamble); | ||
| 321 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], | ||
| 322 | qca953x_1p0_radio_core); | ||
| 323 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], | ||
| 324 | qca953x_1p0_radio_postamble); | ||
| 325 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], | ||
| 326 | qca953x_1p0_soc_preamble); | ||
| 327 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], | ||
| 328 | qca953x_1p0_soc_postamble); | ||
| 329 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
| 330 | qca953x_1p0_common_wo_xlna_rx_gain_table); | ||
| 331 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, | ||
| 332 | qca953x_1p0_common_wo_xlna_rx_gain_bounds); | ||
| 333 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
| 334 | qca953x_1p0_modes_no_xpa_tx_gain_table); | ||
| 335 | INIT_INI_ARRAY(&ah->iniModesFastClock, | ||
| 336 | qca953x_1p0_modes_fast_clock); | ||
| 311 | } else if (AR_SREV_9580(ah)) { | 337 | } else if (AR_SREV_9580(ah)) { |
| 312 | /* mac */ | 338 | /* mac */ |
| 313 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], | 339 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], |
| @@ -485,6 +511,9 @@ static void ar9003_tx_gain_table_mode0(struct ath_hw *ah) | |||
| 485 | else if (AR_SREV_9550(ah)) | 511 | else if (AR_SREV_9550(ah)) |
| 486 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 512 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
| 487 | ar955x_1p0_modes_xpa_tx_gain_table); | 513 | ar955x_1p0_modes_xpa_tx_gain_table); |
| 514 | else if (AR_SREV_9531(ah)) | ||
| 515 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
| 516 | qca953x_1p0_modes_xpa_tx_gain_table); | ||
| 488 | else if (AR_SREV_9580(ah)) | 517 | else if (AR_SREV_9580(ah)) |
| 489 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 518 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
| 490 | ar9580_1p0_lowest_ob_db_tx_gain_table); | 519 | ar9580_1p0_lowest_ob_db_tx_gain_table); |
| @@ -525,7 +554,14 @@ static void ar9003_tx_gain_table_mode1(struct ath_hw *ah) | |||
| 525 | else if (AR_SREV_9550(ah)) | 554 | else if (AR_SREV_9550(ah)) |
| 526 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 555 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
| 527 | ar955x_1p0_modes_no_xpa_tx_gain_table); | 556 | ar955x_1p0_modes_no_xpa_tx_gain_table); |
| 528 | else if (AR_SREV_9462_21(ah)) | 557 | else if (AR_SREV_9531(ah)) { |
| 558 | if (AR_SREV_9531_11(ah)) | ||
| 559 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
| 560 | qca953x_1p1_modes_no_xpa_tx_gain_table); | ||
| 561 | else | ||
| 562 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
| 563 | qca953x_1p0_modes_no_xpa_tx_gain_table); | ||
| 564 | } else if (AR_SREV_9462_21(ah)) | ||
| 529 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 565 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
| 530 | ar9462_2p1_modes_high_ob_db_tx_gain); | 566 | ar9462_2p1_modes_high_ob_db_tx_gain); |
| 531 | else if (AR_SREV_9462_20(ah)) | 567 | else if (AR_SREV_9462_20(ah)) |
| @@ -699,6 +735,11 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah) | |||
| 699 | ar955x_1p0_common_rx_gain_table); | 735 | ar955x_1p0_common_rx_gain_table); |
| 700 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, | 736 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, |
| 701 | ar955x_1p0_common_rx_gain_bounds); | 737 | ar955x_1p0_common_rx_gain_bounds); |
| 738 | } else if (AR_SREV_9531(ah)) { | ||
| 739 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
| 740 | qca953x_1p0_common_rx_gain_table); | ||
| 741 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, | ||
| 742 | qca953x_1p0_common_rx_gain_bounds); | ||
| 702 | } else if (AR_SREV_9580(ah)) | 743 | } else if (AR_SREV_9580(ah)) |
| 703 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 744 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
| 704 | ar9580_1p0_rx_gain_table); | 745 | ar9580_1p0_rx_gain_table); |
| @@ -744,6 +785,11 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah) | |||
| 744 | ar955x_1p0_common_wo_xlna_rx_gain_table); | 785 | ar955x_1p0_common_wo_xlna_rx_gain_table); |
| 745 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, | 786 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, |
| 746 | ar955x_1p0_common_wo_xlna_rx_gain_bounds); | 787 | ar955x_1p0_common_wo_xlna_rx_gain_bounds); |
| 788 | } else if (AR_SREV_9531(ah)) { | ||
| 789 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
| 790 | qca953x_1p0_common_wo_xlna_rx_gain_table); | ||
| 791 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, | ||
| 792 | qca953x_1p0_common_wo_xlna_rx_gain_bounds); | ||
| 747 | } else if (AR_SREV_9580(ah)) | 793 | } else if (AR_SREV_9580(ah)) |
| 748 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 794 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
| 749 | ar9580_1p0_wo_xlna_rx_gain_table); | 795 | ar9580_1p0_wo_xlna_rx_gain_table); |
| @@ -872,6 +918,117 @@ static void ar9003_hw_configpcipowersave(struct ath_hw *ah, | |||
| 872 | } | 918 | } |
| 873 | } | 919 | } |
| 874 | 920 | ||
| 921 | static void ar9003_hw_init_hang_checks(struct ath_hw *ah) | ||
| 922 | { | ||
| 923 | /* | ||
| 924 | * All chips support detection of BB/MAC hangs. | ||
| 925 | */ | ||
| 926 | ah->config.hw_hang_checks |= HW_BB_WATCHDOG; | ||
| 927 | ah->config.hw_hang_checks |= HW_MAC_HANG; | ||
| 928 | |||
| 929 | /* | ||
| 930 | * This is not required for AR9580 1.0 | ||
| 931 | */ | ||
| 932 | if (AR_SREV_9300_22(ah)) | ||
| 933 | ah->config.hw_hang_checks |= HW_PHYRESTART_CLC_WAR; | ||
| 934 | |||
| 935 | if (AR_SREV_9330(ah)) | ||
| 936 | ah->bb_watchdog_timeout_ms = 85; | ||
| 937 | else | ||
| 938 | ah->bb_watchdog_timeout_ms = 25; | ||
| 939 | } | ||
| 940 | |||
| 941 | /* | ||
| 942 | * MAC HW hang check | ||
| 943 | * ================= | ||
| 944 | * | ||
| 945 | * Signature: dcu_chain_state is 0x6 and dcu_complete_state is 0x1. | ||
| 946 | * | ||
| 947 | * The state of each DCU chain (mapped to TX queues) is available from these | ||
| 948 | * DMA debug registers: | ||
| 949 | * | ||
| 950 | * Chain 0 state : Bits 4:0 of AR_DMADBG_4 | ||
| 951 | * Chain 1 state : Bits 9:5 of AR_DMADBG_4 | ||
| 952 | * Chain 2 state : Bits 14:10 of AR_DMADBG_4 | ||
| 953 | * Chain 3 state : Bits 19:15 of AR_DMADBG_4 | ||
| 954 | * Chain 4 state : Bits 24:20 of AR_DMADBG_4 | ||
| 955 | * Chain 5 state : Bits 29:25 of AR_DMADBG_4 | ||
| 956 | * Chain 6 state : Bits 4:0 of AR_DMADBG_5 | ||
| 957 | * Chain 7 state : Bits 9:5 of AR_DMADBG_5 | ||
| 958 | * Chain 8 state : Bits 14:10 of AR_DMADBG_5 | ||
| 959 | * Chain 9 state : Bits 19:15 of AR_DMADBG_5 | ||
| 960 | * | ||
| 961 | * The DCU chain state "0x6" means "WAIT_FRDONE" - wait for TX frame to be done. | ||
| 962 | */ | ||
| 963 | |||
| 964 | #define NUM_STATUS_READS 50 | ||
| 965 | |||
| 966 | static bool ath9k_hw_verify_hang(struct ath_hw *ah, unsigned int queue) | ||
| 967 | { | ||
| 968 | u32 dma_dbg_chain, dma_dbg_complete; | ||
| 969 | u8 dcu_chain_state, dcu_complete_state; | ||
| 970 | int i; | ||
| 971 | |||
| 972 | for (i = 0; i < NUM_STATUS_READS; i++) { | ||
| 973 | if (queue < 6) | ||
| 974 | dma_dbg_chain = REG_READ(ah, AR_DMADBG_4); | ||
| 975 | else | ||
| 976 | dma_dbg_chain = REG_READ(ah, AR_DMADBG_5); | ||
| 977 | |||
| 978 | dma_dbg_complete = REG_READ(ah, AR_DMADBG_6); | ||
| 979 | |||
| 980 | dcu_chain_state = (dma_dbg_chain >> (5 * queue)) & 0x1f; | ||
| 981 | dcu_complete_state = dma_dbg_complete & 0x3; | ||
| 982 | |||
| 983 | if ((dcu_chain_state != 0x6) || (dcu_complete_state != 0x1)) | ||
| 984 | return false; | ||
| 985 | } | ||
| 986 | |||
| 987 | ath_dbg(ath9k_hw_common(ah), RESET, | ||
| 988 | "MAC Hang signature found for queue: %d\n", queue); | ||
| 989 | |||
| 990 | return true; | ||
| 991 | } | ||
| 992 | |||
| 993 | static bool ar9003_hw_detect_mac_hang(struct ath_hw *ah) | ||
| 994 | { | ||
| 995 | u32 dma_dbg_4, dma_dbg_5, dma_dbg_6, chk_dbg; | ||
| 996 | u8 dcu_chain_state, dcu_complete_state; | ||
| 997 | bool dcu_wait_frdone = false; | ||
| 998 | unsigned long chk_dcu = 0; | ||
| 999 | unsigned int i = 0; | ||
| 1000 | |||
| 1001 | dma_dbg_4 = REG_READ(ah, AR_DMADBG_4); | ||
| 1002 | dma_dbg_5 = REG_READ(ah, AR_DMADBG_5); | ||
| 1003 | dma_dbg_6 = REG_READ(ah, AR_DMADBG_6); | ||
| 1004 | |||
| 1005 | dcu_complete_state = dma_dbg_6 & 0x3; | ||
| 1006 | if (dcu_complete_state != 0x1) | ||
| 1007 | goto exit; | ||
| 1008 | |||
| 1009 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | ||
| 1010 | if (i < 6) | ||
| 1011 | chk_dbg = dma_dbg_4; | ||
| 1012 | else | ||
| 1013 | chk_dbg = dma_dbg_5; | ||
| 1014 | |||
| 1015 | dcu_chain_state = (chk_dbg >> (5 * i)) & 0x1f; | ||
| 1016 | if (dcu_chain_state == 0x6) { | ||
| 1017 | dcu_wait_frdone = true; | ||
| 1018 | chk_dcu |= BIT(i); | ||
| 1019 | } | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | if ((dcu_complete_state == 0x1) && dcu_wait_frdone) { | ||
| 1023 | for_each_set_bit(i, &chk_dcu, ATH9K_NUM_TX_QUEUES) { | ||
| 1024 | if (ath9k_hw_verify_hang(ah, i)) | ||
| 1025 | return true; | ||
| 1026 | } | ||
| 1027 | } | ||
| 1028 | exit: | ||
| 1029 | return false; | ||
| 1030 | } | ||
| 1031 | |||
| 875 | /* Sets up the AR9003 hardware familiy callbacks */ | 1032 | /* Sets up the AR9003 hardware familiy callbacks */ |
| 876 | void ar9003_hw_attach_ops(struct ath_hw *ah) | 1033 | void ar9003_hw_attach_ops(struct ath_hw *ah) |
| 877 | { | 1034 | { |
| @@ -880,6 +1037,8 @@ void ar9003_hw_attach_ops(struct ath_hw *ah) | |||
| 880 | 1037 | ||
| 881 | ar9003_hw_init_mode_regs(ah); | 1038 | ar9003_hw_init_mode_regs(ah); |
| 882 | priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs; | 1039 | priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs; |
| 1040 | priv_ops->init_hang_checks = ar9003_hw_init_hang_checks; | ||
| 1041 | priv_ops->detect_mac_hang = ar9003_hw_detect_mac_hang; | ||
| 883 | 1042 | ||
| 884 | ops->config_pci_powersave = ar9003_hw_configpcipowersave; | 1043 | ops->config_pci_powersave = ar9003_hw_configpcipowersave; |
| 885 | 1044 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 9f051a08e143..09facba1dc6d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
| @@ -103,7 +103,7 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |||
| 103 | } else { | 103 | } else { |
| 104 | channelSel = CHANSEL_2G(freq) >> 1; | 104 | channelSel = CHANSEL_2G(freq) >> 1; |
| 105 | } | 105 | } |
| 106 | } else if (AR_SREV_9550(ah)) { | 106 | } else if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) { |
| 107 | if (ah->is_clk_25mhz) | 107 | if (ah->is_clk_25mhz) |
| 108 | div = 75; | 108 | div = 75; |
| 109 | else | 109 | else |
| @@ -118,7 +118,7 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |||
| 118 | /* Set to 2G mode */ | 118 | /* Set to 2G mode */ |
| 119 | bMode = 1; | 119 | bMode = 1; |
| 120 | } else { | 120 | } else { |
| 121 | if ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) && | 121 | if ((AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) && |
| 122 | ah->is_clk_25mhz) { | 122 | ah->is_clk_25mhz) { |
| 123 | channelSel = freq / 75; | 123 | channelSel = freq / 75; |
| 124 | chan_frac = ((freq % 75) * 0x20000) / 75; | 124 | chan_frac = ((freq % 75) * 0x20000) / 75; |
| @@ -810,10 +810,12 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, | |||
| 810 | /* | 810 | /* |
| 811 | * TXGAIN initvals. | 811 | * TXGAIN initvals. |
| 812 | */ | 812 | */ |
| 813 | if (AR_SREV_9550(ah)) { | 813 | if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) { |
| 814 | int modes_txgain_index; | 814 | int modes_txgain_index = 1; |
| 815 | |||
| 816 | if (AR_SREV_9550(ah)) | ||
| 817 | modes_txgain_index = ar9550_hw_get_modes_txgain_index(ah, chan); | ||
| 815 | 818 | ||
| 816 | modes_txgain_index = ar9550_hw_get_modes_txgain_index(ah, chan); | ||
| 817 | if (modes_txgain_index < 0) | 819 | if (modes_txgain_index < 0) |
| 818 | return -EINVAL; | 820 | return -EINVAL; |
| 819 | 821 | ||
| @@ -1814,6 +1816,68 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | |||
| 1814 | memcpy(ah->nf_regs, ar9300_cca_regs, sizeof(ah->nf_regs)); | 1816 | memcpy(ah->nf_regs, ar9300_cca_regs, sizeof(ah->nf_regs)); |
| 1815 | } | 1817 | } |
| 1816 | 1818 | ||
| 1819 | /* | ||
| 1820 | * Baseband Watchdog signatures: | ||
| 1821 | * | ||
| 1822 | * 0x04000539: BB hang when operating in HT40 DFS Channel. | ||
| 1823 | * Full chip reset is not required, but a recovery | ||
| 1824 | * mechanism is needed. | ||
| 1825 | * | ||
| 1826 | * 0x1300000a: Related to CAC deafness. | ||
| 1827 | * Chip reset is not required. | ||
| 1828 | * | ||
| 1829 | * 0x0400000a: Related to CAC deafness. | ||
| 1830 | * Full chip reset is required. | ||
| 1831 | * | ||
| 1832 | * 0x04000b09: RX state machine gets into an illegal state | ||
| 1833 | * when a packet with unsupported rate is received. | ||
| 1834 | * Full chip reset is required and PHY_RESTART has | ||
| 1835 | * to be disabled. | ||
| 1836 | * | ||
| 1837 | * 0x04000409: Packet stuck on receive. | ||
| 1838 | * Full chip reset is required for all chips except AR9340. | ||
| 1839 | */ | ||
| 1840 | |||
| 1841 | /* | ||
| 1842 | * ar9003_hw_bb_watchdog_check(): Returns true if a chip reset is required. | ||
| 1843 | */ | ||
| 1844 | bool ar9003_hw_bb_watchdog_check(struct ath_hw *ah) | ||
| 1845 | { | ||
| 1846 | u32 val; | ||
| 1847 | |||
| 1848 | switch(ah->bb_watchdog_last_status) { | ||
| 1849 | case 0x04000539: | ||
| 1850 | val = REG_READ(ah, AR_PHY_RADAR_0); | ||
| 1851 | val &= (~AR_PHY_RADAR_0_FIRPWR); | ||
| 1852 | val |= SM(0x7f, AR_PHY_RADAR_0_FIRPWR); | ||
| 1853 | REG_WRITE(ah, AR_PHY_RADAR_0, val); | ||
| 1854 | udelay(1); | ||
| 1855 | val = REG_READ(ah, AR_PHY_RADAR_0); | ||
| 1856 | val &= ~AR_PHY_RADAR_0_FIRPWR; | ||
| 1857 | val |= SM(AR9300_DFS_FIRPWR, AR_PHY_RADAR_0_FIRPWR); | ||
| 1858 | REG_WRITE(ah, AR_PHY_RADAR_0, val); | ||
| 1859 | |||
| 1860 | return false; | ||
| 1861 | case 0x1300000a: | ||
| 1862 | return false; | ||
| 1863 | case 0x0400000a: | ||
| 1864 | case 0x04000b09: | ||
| 1865 | return true; | ||
| 1866 | case 0x04000409: | ||
| 1867 | if (AR_SREV_9340(ah) || AR_SREV_9531(ah)) | ||
| 1868 | return false; | ||
| 1869 | else | ||
| 1870 | return true; | ||
| 1871 | default: | ||
| 1872 | /* | ||
| 1873 | * For any other unknown signatures, do a | ||
| 1874 | * full chip reset. | ||
| 1875 | */ | ||
| 1876 | return true; | ||
| 1877 | } | ||
| 1878 | } | ||
| 1879 | EXPORT_SYMBOL(ar9003_hw_bb_watchdog_check); | ||
| 1880 | |||
| 1817 | void ar9003_hw_bb_watchdog_config(struct ath_hw *ah) | 1881 | void ar9003_hw_bb_watchdog_config(struct ath_hw *ah) |
| 1818 | { | 1882 | { |
| 1819 | struct ath_common *common = ath9k_hw_common(ah); | 1883 | struct ath_common *common = ath9k_hw_common(ah); |
| @@ -1930,6 +1994,7 @@ EXPORT_SYMBOL(ar9003_hw_bb_watchdog_dbg_info); | |||
| 1930 | 1994 | ||
| 1931 | void ar9003_hw_disable_phy_restart(struct ath_hw *ah) | 1995 | void ar9003_hw_disable_phy_restart(struct ath_hw *ah) |
| 1932 | { | 1996 | { |
| 1997 | u8 result; | ||
| 1933 | u32 val; | 1998 | u32 val; |
| 1934 | 1999 | ||
| 1935 | /* While receiving unsupported rate frame rx state machine | 2000 | /* While receiving unsupported rate frame rx state machine |
| @@ -1937,15 +2002,13 @@ void ar9003_hw_disable_phy_restart(struct ath_hw *ah) | |||
| 1937 | * state, BB would go hang. If RXSM is in 0xb state after | 2002 | * state, BB would go hang. If RXSM is in 0xb state after |
| 1938 | * first bb panic, ensure to disable the phy_restart. | 2003 | * first bb panic, ensure to disable the phy_restart. |
| 1939 | */ | 2004 | */ |
| 1940 | if (!((MS(ah->bb_watchdog_last_status, | 2005 | result = MS(ah->bb_watchdog_last_status, AR_PHY_WATCHDOG_RX_OFDM_SM); |
| 1941 | AR_PHY_WATCHDOG_RX_OFDM_SM) == 0xb) || | ||
| 1942 | ah->bb_hang_rx_ofdm)) | ||
| 1943 | return; | ||
| 1944 | |||
| 1945 | ah->bb_hang_rx_ofdm = true; | ||
| 1946 | val = REG_READ(ah, AR_PHY_RESTART); | ||
| 1947 | val &= ~AR_PHY_RESTART_ENA; | ||
| 1948 | 2006 | ||
| 1949 | REG_WRITE(ah, AR_PHY_RESTART, val); | 2007 | if ((result == 0xb) || ah->bb_hang_rx_ofdm) { |
| 2008 | ah->bb_hang_rx_ofdm = true; | ||
| 2009 | val = REG_READ(ah, AR_PHY_RESTART); | ||
| 2010 | val &= ~AR_PHY_RESTART_ENA; | ||
| 2011 | REG_WRITE(ah, AR_PHY_RESTART, val); | ||
| 2012 | } | ||
| 1950 | } | 2013 | } |
| 1951 | EXPORT_SYMBOL(ar9003_hw_disable_phy_restart); | 2014 | EXPORT_SYMBOL(ar9003_hw_disable_phy_restart); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 1b441715ba39..fd090b1f2d0f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h | |||
| @@ -338,9 +338,8 @@ | |||
| 338 | #define AR_PHY_CCA_NOM_VAL_9300_5GHZ -115 | 338 | #define AR_PHY_CCA_NOM_VAL_9300_5GHZ -115 |
| 339 | #define AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ -125 | 339 | #define AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ -125 |
| 340 | #define AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ -125 | 340 | #define AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ -125 |
| 341 | #define AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ -95 | 341 | #define AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ -60 |
| 342 | #define AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ -100 | 342 | #define AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ -60 |
| 343 | |||
| 344 | #define AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_2GHZ -95 | 343 | #define AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_2GHZ -95 |
| 345 | #define AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_5GHZ -100 | 344 | #define AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_5GHZ -100 |
| 346 | 345 | ||
| @@ -670,6 +669,16 @@ | |||
| 670 | #define AR_PHY_65NM_CH1_RXTX4 0x1650c | 669 | #define AR_PHY_65NM_CH1_RXTX4 0x1650c |
| 671 | #define AR_PHY_65NM_CH2_RXTX4 0x1690c | 670 | #define AR_PHY_65NM_CH2_RXTX4 0x1690c |
| 672 | 671 | ||
| 672 | #define AR_PHY_65NM_CH0_BB1 0x16140 | ||
| 673 | #define AR_PHY_65NM_CH0_BB2 0x16144 | ||
| 674 | #define AR_PHY_65NM_CH0_BB3 0x16148 | ||
| 675 | #define AR_PHY_65NM_CH1_BB1 0x16540 | ||
| 676 | #define AR_PHY_65NM_CH1_BB2 0x16544 | ||
| 677 | #define AR_PHY_65NM_CH1_BB3 0x16548 | ||
| 678 | #define AR_PHY_65NM_CH2_BB1 0x16940 | ||
| 679 | #define AR_PHY_65NM_CH2_BB2 0x16944 | ||
| 680 | #define AR_PHY_65NM_CH2_BB3 0x16948 | ||
| 681 | |||
| 673 | #define AR_PHY_65NM_CH0_SYNTH12_VREFMUL3 0x00780000 | 682 | #define AR_PHY_65NM_CH0_SYNTH12_VREFMUL3 0x00780000 |
| 674 | #define AR_PHY_65NM_CH0_SYNTH12_VREFMUL3_S 19 | 683 | #define AR_PHY_65NM_CH0_SYNTH12_VREFMUL3_S 19 |
| 675 | #define AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK 0x00000004 | 684 | #define AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK 0x00000004 |
| @@ -1334,4 +1343,6 @@ | |||
| 1334 | #define AR_PHY_65NM_RXRF_AGC_AGC_OUT 0x00000004 | 1343 | #define AR_PHY_65NM_RXRF_AGC_AGC_OUT 0x00000004 |
| 1335 | #define AR_PHY_65NM_RXRF_AGC_AGC_OUT_S 2 | 1344 | #define AR_PHY_65NM_RXRF_AGC_AGC_OUT_S 2 |
| 1336 | 1345 | ||
| 1346 | #define AR9300_DFS_FIRPWR -28 | ||
| 1347 | |||
| 1337 | #endif /* AR9003_PHY_H */ | 1348 | #endif /* AR9003_PHY_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h new file mode 100644 index 000000000000..3c9113d9b1bc --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h | |||
| @@ -0,0 +1,718 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. | ||
| 3 | * Copyright (c) 2011-2012 Qualcomm Atheros Inc. | ||
| 4 | * | ||
| 5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 6 | * purpose with or without fee is hereby granted, provided that the above | ||
| 7 | * copyright notice and this permission notice appear in all copies. | ||
| 8 | * | ||
| 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef INITVALS_953X_H | ||
| 19 | #define INITVALS_953X_H | ||
| 20 | |||
| 21 | #define qca953x_1p0_mac_postamble ar9300_2p2_mac_postamble | ||
| 22 | |||
| 23 | #define qca953x_1p0_soc_postamble ar9300_2p2_soc_postamble | ||
| 24 | |||
| 25 | #define qca953x_1p0_common_rx_gain_table ar9300Common_rx_gain_table_2p2 | ||
| 26 | |||
| 27 | #define qca953x_1p0_common_wo_xlna_rx_gain_table ar9300Common_wo_xlna_rx_gain_table_2p2 | ||
| 28 | |||
| 29 | #define qca953x_1p0_modes_fast_clock ar9300Modes_fast_clock_2p2 | ||
| 30 | |||
| 31 | static const u32 qca953x_1p0_mac_core[][2] = { | ||
| 32 | /* Addr allmodes */ | ||
| 33 | {0x00000008, 0x00000000}, | ||
| 34 | {0x00000030, 0x00020085}, | ||
| 35 | {0x00000034, 0x00000005}, | ||
| 36 | {0x00000040, 0x00000000}, | ||
| 37 | {0x00000044, 0x00000000}, | ||
| 38 | {0x00000048, 0x00000008}, | ||
| 39 | {0x0000004c, 0x00000010}, | ||
| 40 | {0x00000050, 0x00000000}, | ||
| 41 | {0x00001040, 0x002ffc0f}, | ||
| 42 | {0x00001044, 0x002ffc0f}, | ||
| 43 | {0x00001048, 0x002ffc0f}, | ||
| 44 | {0x0000104c, 0x002ffc0f}, | ||
| 45 | {0x00001050, 0x002ffc0f}, | ||
| 46 | {0x00001054, 0x002ffc0f}, | ||
| 47 | {0x00001058, 0x002ffc0f}, | ||
| 48 | {0x0000105c, 0x002ffc0f}, | ||
| 49 | {0x00001060, 0x002ffc0f}, | ||
| 50 | {0x00001064, 0x002ffc0f}, | ||
| 51 | {0x000010f0, 0x00000100}, | ||
| 52 | {0x00001270, 0x00000000}, | ||
| 53 | {0x000012b0, 0x00000000}, | ||
| 54 | {0x000012f0, 0x00000000}, | ||
| 55 | {0x0000143c, 0x00000000}, | ||
| 56 | {0x0000147c, 0x00000000}, | ||
| 57 | {0x00008000, 0x00000000}, | ||
| 58 | {0x00008004, 0x00000000}, | ||
| 59 | {0x00008008, 0x00000000}, | ||
| 60 | {0x0000800c, 0x00000000}, | ||
| 61 | {0x00008018, 0x00000000}, | ||
| 62 | {0x00008020, 0x00000000}, | ||
| 63 | {0x00008038, 0x00000000}, | ||
| 64 | {0x0000803c, 0x00000000}, | ||
| 65 | {0x00008040, 0x00000000}, | ||
| 66 | {0x00008044, 0x00000000}, | ||
| 67 | {0x00008048, 0x00000000}, | ||
| 68 | {0x0000804c, 0xffffffff}, | ||
| 69 | {0x00008054, 0x00000000}, | ||
| 70 | {0x00008058, 0x00000000}, | ||
| 71 | {0x0000805c, 0x000fc78f}, | ||
| 72 | {0x00008060, 0x0000000f}, | ||
| 73 | {0x00008064, 0x00000000}, | ||
| 74 | {0x00008070, 0x00000310}, | ||
| 75 | {0x00008074, 0x00000020}, | ||
| 76 | {0x00008078, 0x00000000}, | ||
| 77 | {0x0000809c, 0x0000000f}, | ||
| 78 | {0x000080a0, 0x00000000}, | ||
| 79 | {0x000080a4, 0x02ff0000}, | ||
| 80 | {0x000080a8, 0x0e070605}, | ||
| 81 | {0x000080ac, 0x0000000d}, | ||
| 82 | {0x000080b0, 0x00000000}, | ||
| 83 | {0x000080b4, 0x00000000}, | ||
| 84 | {0x000080b8, 0x00000000}, | ||
| 85 | {0x000080bc, 0x00000000}, | ||
| 86 | {0x000080c0, 0x2a800000}, | ||
| 87 | {0x000080c4, 0x06900168}, | ||
| 88 | {0x000080c8, 0x13881c22}, | ||
| 89 | {0x000080cc, 0x01f40000}, | ||
| 90 | {0x000080d0, 0x00252500}, | ||
| 91 | {0x000080d4, 0x00a00000}, | ||
| 92 | {0x000080d8, 0x00400000}, | ||
| 93 | {0x000080dc, 0x00000000}, | ||
| 94 | {0x000080e0, 0xffffffff}, | ||
| 95 | {0x000080e4, 0x0000ffff}, | ||
| 96 | {0x000080e8, 0x3f3f3f3f}, | ||
| 97 | {0x000080ec, 0x00000000}, | ||
| 98 | {0x000080f0, 0x00000000}, | ||
| 99 | {0x000080f4, 0x00000000}, | ||
| 100 | {0x000080fc, 0x00020000}, | ||
| 101 | {0x00008100, 0x00000000}, | ||
| 102 | {0x00008108, 0x00000052}, | ||
| 103 | {0x0000810c, 0x00000000}, | ||
| 104 | {0x00008110, 0x00000000}, | ||
| 105 | {0x00008114, 0x000007ff}, | ||
| 106 | {0x00008118, 0x000000aa}, | ||
| 107 | {0x0000811c, 0x00003210}, | ||
| 108 | {0x00008124, 0x00000000}, | ||
| 109 | {0x00008128, 0x00000000}, | ||
| 110 | {0x0000812c, 0x00000000}, | ||
| 111 | {0x00008130, 0x00000000}, | ||
| 112 | {0x00008134, 0x00000000}, | ||
| 113 | {0x00008138, 0x00000000}, | ||
| 114 | {0x0000813c, 0x0000ffff}, | ||
| 115 | {0x00008140, 0x000000fe}, | ||
| 116 | {0x00008144, 0xffffffff}, | ||
| 117 | {0x00008168, 0x00000000}, | ||
| 118 | {0x0000816c, 0x00000000}, | ||
| 119 | {0x000081c0, 0x00000000}, | ||
| 120 | {0x000081c4, 0x33332210}, | ||
| 121 | {0x000081ec, 0x00000000}, | ||
| 122 | {0x000081f0, 0x00000000}, | ||
| 123 | {0x000081f4, 0x00000000}, | ||
| 124 | {0x000081f8, 0x00000000}, | ||
| 125 | {0x000081fc, 0x00000000}, | ||
| 126 | {0x00008240, 0x00100000}, | ||
| 127 | {0x00008244, 0x0010f3d7}, | ||
| 128 | {0x00008248, 0x00000852}, | ||
| 129 | {0x0000824c, 0x0001e7ae}, | ||
| 130 | {0x00008250, 0x00000000}, | ||
| 131 | {0x00008254, 0x00000000}, | ||
| 132 | {0x00008258, 0x00000000}, | ||
| 133 | {0x0000825c, 0x40000000}, | ||
| 134 | {0x00008260, 0x00080922}, | ||
| 135 | {0x00008264, 0x9d400010}, | ||
| 136 | {0x00008268, 0xffffffff}, | ||
| 137 | {0x0000826c, 0x0000ffff}, | ||
| 138 | {0x00008270, 0x00000000}, | ||
| 139 | {0x00008274, 0x40000000}, | ||
| 140 | {0x00008278, 0x003e4180}, | ||
| 141 | {0x0000827c, 0x00000004}, | ||
| 142 | {0x00008284, 0x0000002c}, | ||
| 143 | {0x00008288, 0x0000002c}, | ||
| 144 | {0x0000828c, 0x000000ff}, | ||
| 145 | {0x00008294, 0x00000000}, | ||
| 146 | {0x00008298, 0x00000000}, | ||
| 147 | {0x0000829c, 0x00000000}, | ||
| 148 | {0x00008300, 0x00001d40}, | ||
| 149 | {0x00008314, 0x00000000}, | ||
| 150 | {0x0000831c, 0x0000010d}, | ||
| 151 | {0x00008328, 0x00000000}, | ||
| 152 | {0x0000832c, 0x0000001f}, | ||
| 153 | {0x00008330, 0x00000302}, | ||
| 154 | {0x00008334, 0x00000700}, | ||
| 155 | {0x00008338, 0xffff0000}, | ||
| 156 | {0x0000833c, 0x02400000}, | ||
| 157 | {0x00008340, 0x000107ff}, | ||
| 158 | {0x00008344, 0xaa48107b}, | ||
| 159 | {0x00008348, 0x008f0000}, | ||
| 160 | {0x0000835c, 0x00000000}, | ||
| 161 | {0x00008360, 0xffffffff}, | ||
| 162 | {0x00008364, 0xffffffff}, | ||
| 163 | {0x00008368, 0x00000000}, | ||
| 164 | {0x00008370, 0x00000000}, | ||
| 165 | {0x00008374, 0x000000ff}, | ||
| 166 | {0x00008378, 0x00000000}, | ||
| 167 | {0x0000837c, 0x00000000}, | ||
| 168 | {0x00008380, 0xffffffff}, | ||
| 169 | {0x00008384, 0xffffffff}, | ||
| 170 | {0x00008390, 0xffffffff}, | ||
| 171 | {0x00008394, 0xffffffff}, | ||
| 172 | {0x00008398, 0x00000000}, | ||
| 173 | {0x0000839c, 0x00000000}, | ||
| 174 | {0x000083a0, 0x00000000}, | ||
| 175 | {0x000083a4, 0x0000fa14}, | ||
| 176 | {0x000083a8, 0x000f0c00}, | ||
| 177 | {0x000083ac, 0x33332210}, | ||
| 178 | {0x000083b0, 0x33332210}, | ||
| 179 | {0x000083b4, 0x33332210}, | ||
| 180 | {0x000083b8, 0x33332210}, | ||
| 181 | {0x000083bc, 0x00000000}, | ||
| 182 | {0x000083c0, 0x00000000}, | ||
| 183 | {0x000083c4, 0x00000000}, | ||
| 184 | {0x000083c8, 0x00000000}, | ||
| 185 | {0x000083cc, 0x00000200}, | ||
| 186 | {0x000083d0, 0x8c7901ff}, | ||
| 187 | }; | ||
| 188 | |||
| 189 | static const u32 qca953x_1p0_baseband_core[][2] = { | ||
| 190 | /* Addr allmodes */ | ||
| 191 | {0x00009800, 0xafe68e30}, | ||
| 192 | {0x00009804, 0xfd14e000}, | ||
| 193 | {0x00009808, 0x9c0a9f6b}, | ||
| 194 | {0x0000980c, 0x04900000}, | ||
| 195 | {0x00009814, 0x0280c00a}, | ||
| 196 | {0x00009818, 0x00000000}, | ||
| 197 | {0x0000981c, 0x00020028}, | ||
| 198 | {0x00009834, 0x6400a190}, | ||
| 199 | {0x00009838, 0x0108ecff}, | ||
| 200 | {0x0000983c, 0x14000600}, | ||
| 201 | {0x00009880, 0x201fff00}, | ||
| 202 | {0x00009884, 0x00001042}, | ||
| 203 | {0x000098a4, 0x00200400}, | ||
| 204 | {0x000098b0, 0x32840bbe}, | ||
| 205 | {0x000098bc, 0x00000002}, | ||
| 206 | {0x000098d0, 0x004b6a8e}, | ||
| 207 | {0x000098d4, 0x00000820}, | ||
| 208 | {0x000098dc, 0x00000000}, | ||
| 209 | {0x000098f0, 0x00000000}, | ||
| 210 | {0x000098f4, 0x00000000}, | ||
| 211 | {0x00009c04, 0xff55ff55}, | ||
| 212 | {0x00009c08, 0x0320ff55}, | ||
| 213 | {0x00009c0c, 0x00000000}, | ||
| 214 | {0x00009c10, 0x00000000}, | ||
| 215 | {0x00009c14, 0x00046384}, | ||
| 216 | {0x00009c18, 0x05b6b440}, | ||
| 217 | {0x00009c1c, 0x00b6b440}, | ||
| 218 | {0x00009d00, 0xc080a333}, | ||
| 219 | {0x00009d04, 0x40206c10}, | ||
| 220 | {0x00009d08, 0x009c4060}, | ||
| 221 | {0x00009d0c, 0x9883800a}, | ||
| 222 | {0x00009d10, 0x01884061}, | ||
| 223 | {0x00009d14, 0x00c0040b}, | ||
| 224 | {0x00009d18, 0x00000000}, | ||
| 225 | {0x00009e08, 0x0038230c}, | ||
| 226 | {0x00009e24, 0x990bb515}, | ||
| 227 | {0x00009e28, 0x0c6f0000}, | ||
| 228 | {0x00009e30, 0x06336f77}, | ||
| 229 | {0x00009e34, 0x6af6532f}, | ||
| 230 | {0x00009e38, 0x0cc80c00}, | ||
| 231 | {0x00009e40, 0x0d261820}, | ||
| 232 | {0x00009e4c, 0x00001004}, | ||
| 233 | {0x00009e50, 0x00ff03f1}, | ||
| 234 | {0x00009fc0, 0x813e4788}, | ||
| 235 | {0x00009fc4, 0x0001efb5}, | ||
| 236 | {0x00009fcc, 0x40000014}, | ||
| 237 | {0x00009fd0, 0x01193b91}, | ||
| 238 | {0x0000a20c, 0x00000000}, | ||
| 239 | {0x0000a220, 0x00000000}, | ||
| 240 | {0x0000a224, 0x00000000}, | ||
| 241 | {0x0000a228, 0x10002310}, | ||
| 242 | {0x0000a23c, 0x00000000}, | ||
| 243 | {0x0000a244, 0x0c000000}, | ||
| 244 | {0x0000a248, 0x00000140}, | ||
| 245 | {0x0000a2a0, 0x00000007}, | ||
| 246 | {0x0000a2c0, 0x00000007}, | ||
| 247 | {0x0000a2c8, 0x00000000}, | ||
| 248 | {0x0000a2d4, 0x00000000}, | ||
| 249 | {0x0000a2ec, 0x00000000}, | ||
| 250 | {0x0000a2f0, 0x00000000}, | ||
| 251 | {0x0000a2f4, 0x00000000}, | ||
| 252 | {0x0000a2f8, 0x00000000}, | ||
| 253 | {0x0000a344, 0x00000000}, | ||
| 254 | {0x0000a34c, 0x00000000}, | ||
| 255 | {0x0000a350, 0x0000a000}, | ||
| 256 | {0x0000a364, 0x00000000}, | ||
| 257 | {0x0000a370, 0x00000000}, | ||
| 258 | {0x0000a390, 0x00000001}, | ||
| 259 | {0x0000a394, 0x00000444}, | ||
| 260 | {0x0000a398, 0x1f020503}, | ||
| 261 | {0x0000a39c, 0x29180c03}, | ||
| 262 | {0x0000a3a0, 0x9a8b6844}, | ||
| 263 | {0x0000a3a4, 0x000000ff}, | ||
| 264 | {0x0000a3a8, 0x6a6a6a6a}, | ||
| 265 | {0x0000a3ac, 0x6a6a6a6a}, | ||
| 266 | {0x0000a3b0, 0x00c8641a}, | ||
| 267 | {0x0000a3b4, 0x0000001a}, | ||
| 268 | {0x0000a3b8, 0x0088642a}, | ||
| 269 | {0x0000a3bc, 0x000001fa}, | ||
| 270 | {0x0000a3c0, 0x20202020}, | ||
| 271 | {0x0000a3c4, 0x22222220}, | ||
| 272 | {0x0000a3c8, 0x20200020}, | ||
| 273 | {0x0000a3cc, 0x20202020}, | ||
| 274 | {0x0000a3d0, 0x20202020}, | ||
| 275 | {0x0000a3d4, 0x20202020}, | ||
| 276 | {0x0000a3d8, 0x20202020}, | ||
| 277 | {0x0000a3dc, 0x20202020}, | ||
| 278 | {0x0000a3e0, 0x20202020}, | ||
| 279 | {0x0000a3e4, 0x20202020}, | ||
| 280 | {0x0000a3e8, 0x20202020}, | ||
| 281 | {0x0000a3ec, 0x20202020}, | ||
| 282 | {0x0000a3f0, 0x00000000}, | ||
| 283 | {0x0000a3f4, 0x00000000}, | ||
| 284 | {0x0000a3f8, 0x0c9bd380}, | ||
| 285 | {0x0000a3fc, 0x000f0f01}, | ||
| 286 | {0x0000a400, 0x8fa91f01}, | ||
| 287 | {0x0000a404, 0x00000000}, | ||
| 288 | {0x0000a408, 0x0e79e5c6}, | ||
| 289 | {0x0000a40c, 0x00820820}, | ||
| 290 | {0x0000a414, 0x1ce42108}, | ||
| 291 | {0x0000a418, 0x2d001dce}, | ||
| 292 | {0x0000a41c, 0x1ce73908}, | ||
| 293 | {0x0000a420, 0x000001ce}, | ||
| 294 | {0x0000a424, 0x1ce738e7}, | ||
| 295 | {0x0000a428, 0x000001ce}, | ||
| 296 | {0x0000a42c, 0x1ce739ce}, | ||
| 297 | {0x0000a430, 0x1ce739ce}, | ||
| 298 | {0x0000a434, 0x00000000}, | ||
| 299 | {0x0000a438, 0x00001801}, | ||
| 300 | {0x0000a43c, 0x00100000}, | ||
| 301 | {0x0000a444, 0x00000000}, | ||
| 302 | {0x0000a448, 0x05000080}, | ||
| 303 | {0x0000a44c, 0x00000001}, | ||
| 304 | {0x0000a450, 0x00010000}, | ||
| 305 | {0x0000a458, 0x00000000}, | ||
| 306 | {0x0000a644, 0xbfad9d74}, | ||
| 307 | {0x0000a648, 0x0048060a}, | ||
| 308 | {0x0000a64c, 0x00003c37}, | ||
| 309 | {0x0000a670, 0x03020100}, | ||
| 310 | {0x0000a674, 0x09080504}, | ||
| 311 | {0x0000a678, 0x0d0c0b0a}, | ||
| 312 | {0x0000a67c, 0x13121110}, | ||
| 313 | {0x0000a680, 0x31301514}, | ||
| 314 | {0x0000a684, 0x35343332}, | ||
| 315 | {0x0000a688, 0x00000036}, | ||
| 316 | {0x0000a690, 0x08000838}, | ||
| 317 | {0x0000a7cc, 0x00000000}, | ||
| 318 | {0x0000a7d0, 0x00000000}, | ||
| 319 | {0x0000a7d4, 0x00000004}, | ||
| 320 | {0x0000a7dc, 0x00000000}, | ||
| 321 | {0x0000a8d0, 0x004b6a8e}, | ||
| 322 | {0x0000a8d4, 0x00000820}, | ||
| 323 | {0x0000a8dc, 0x00000000}, | ||
| 324 | {0x0000a8f0, 0x00000000}, | ||
| 325 | {0x0000a8f4, 0x00000000}, | ||
| 326 | {0x0000b2d0, 0x00000080}, | ||
| 327 | {0x0000b2d4, 0x00000000}, | ||
| 328 | {0x0000b2ec, 0x00000000}, | ||
| 329 | {0x0000b2f0, 0x00000000}, | ||
| 330 | {0x0000b2f4, 0x00000000}, | ||
| 331 | {0x0000b2f8, 0x00000000}, | ||
| 332 | {0x0000b408, 0x0e79e5c0}, | ||
| 333 | {0x0000b40c, 0x00820820}, | ||
| 334 | {0x0000b420, 0x00000000}, | ||
| 335 | }; | ||
| 336 | |||
| 337 | static const u32 qca953x_1p0_baseband_postamble[][5] = { | ||
| 338 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
| 339 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, | ||
| 340 | {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e}, | ||
| 341 | {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, | ||
| 342 | {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, | ||
| 343 | {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, | ||
| 344 | {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, | ||
| 345 | {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, | ||
| 346 | {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0}, | ||
| 347 | {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020}, | ||
| 348 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, | ||
| 349 | {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e}, | ||
| 350 | {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e}, | ||
| 351 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 352 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, | ||
| 353 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, | ||
| 354 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, | ||
| 355 | {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcfa10822, 0xcfa10822}, | ||
| 356 | {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, | ||
| 357 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, | ||
| 358 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, | ||
| 359 | {0x0000a204, 0x005c0ec0, 0x005c0ec4, 0x005c0ec4, 0x005c0ec0}, | ||
| 360 | {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, | ||
| 361 | {0x0000a22c, 0x07e26a2f, 0x07e26a2f, 0x01026a2f, 0x01026a2f}, | ||
| 362 | {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, | ||
| 363 | {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff}, | ||
| 364 | {0x0000a238, 0xffb01018, 0xffb01018, 0xffb01018, 0xffb01018}, | ||
| 365 | {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, | ||
| 366 | {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, | ||
| 367 | {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, | ||
| 368 | {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01010e0e, 0x01010e0e}, | ||
| 369 | {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501}, | ||
| 370 | {0x0000a264, 0x00000e0e, 0x00000e0e, 0x01000e0e, 0x01000e0e}, | ||
| 371 | {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, | ||
| 372 | {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, | ||
| 373 | {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, | ||
| 374 | {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, | ||
| 375 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, | ||
| 376 | {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33}, | ||
| 377 | {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982}, | ||
| 378 | {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, | ||
| 379 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 380 | {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, | ||
| 381 | {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000}, | ||
| 382 | {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 383 | {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, | ||
| 384 | {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, | ||
| 385 | {0x0000b284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, | ||
| 386 | }; | ||
| 387 | |||
| 388 | static const u32 qca953x_1p0_radio_core[][2] = { | ||
| 389 | /* Addr allmodes */ | ||
| 390 | {0x00016000, 0x36db6db6}, | ||
| 391 | {0x00016004, 0x6db6db40}, | ||
| 392 | {0x00016008, 0x73f00000}, | ||
| 393 | {0x0001600c, 0x00000000}, | ||
| 394 | {0x00016040, 0x3f80fff8}, | ||
| 395 | {0x0001604c, 0x000f0278}, | ||
| 396 | {0x00016050, 0x8036db6c}, | ||
| 397 | {0x00016054, 0x6db60000}, | ||
| 398 | {0x00016080, 0x00080000}, | ||
| 399 | {0x00016084, 0x0e48048c}, | ||
| 400 | {0x00016088, 0x14214514}, | ||
| 401 | {0x0001608c, 0x119f080a}, | ||
| 402 | {0x00016090, 0x24926490}, | ||
| 403 | {0x00016094, 0x00000000}, | ||
| 404 | {0x000160a0, 0xc2108ffe}, | ||
| 405 | {0x000160a4, 0x812fc370}, | ||
| 406 | {0x000160a8, 0x423c8000}, | ||
| 407 | {0x000160b4, 0x92480080}, | ||
| 408 | {0x000160c0, 0x006db6d8}, | ||
| 409 | {0x000160c4, 0x24b6db6c}, | ||
| 410 | {0x000160c8, 0x6db6db6c}, | ||
| 411 | {0x000160cc, 0x6db6fb7c}, | ||
| 412 | {0x000160d0, 0x6db6da44}, | ||
| 413 | {0x00016100, 0x07ff8001}, | ||
| 414 | {0x00016108, 0x00080010}, | ||
| 415 | {0x00016144, 0x01884080}, | ||
| 416 | {0x00016148, 0x000080d8}, | ||
| 417 | {0x00016280, 0x01000901}, | ||
| 418 | {0x00016284, 0x15d30000}, | ||
| 419 | {0x00016288, 0x00318000}, | ||
| 420 | {0x0001628c, 0x50000000}, | ||
| 421 | {0x00016380, 0x00000000}, | ||
| 422 | {0x00016384, 0x00000000}, | ||
| 423 | {0x00016388, 0x00800700}, | ||
| 424 | {0x0001638c, 0x00800700}, | ||
| 425 | {0x00016390, 0x00800700}, | ||
| 426 | {0x00016394, 0x00000000}, | ||
| 427 | {0x00016398, 0x00000000}, | ||
| 428 | {0x0001639c, 0x00000000}, | ||
| 429 | {0x000163a0, 0x00000001}, | ||
| 430 | {0x000163a4, 0x00000001}, | ||
| 431 | {0x000163a8, 0x00000000}, | ||
| 432 | {0x000163ac, 0x00000000}, | ||
| 433 | {0x000163b0, 0x00000000}, | ||
| 434 | {0x000163b4, 0x00000000}, | ||
| 435 | {0x000163b8, 0x00000000}, | ||
| 436 | {0x000163bc, 0x00000000}, | ||
| 437 | {0x000163c0, 0x000000a0}, | ||
| 438 | {0x000163c4, 0x000c0000}, | ||
| 439 | {0x000163c8, 0x14021402}, | ||
| 440 | {0x000163cc, 0x00001402}, | ||
| 441 | {0x000163d0, 0x00000000}, | ||
| 442 | {0x000163d4, 0x00000000}, | ||
| 443 | {0x00016400, 0x36db6db6}, | ||
| 444 | {0x00016404, 0x6db6db40}, | ||
| 445 | {0x00016408, 0x73f00000}, | ||
| 446 | {0x0001640c, 0x00000000}, | ||
| 447 | {0x00016440, 0x3f80fff8}, | ||
| 448 | {0x0001644c, 0x000f0278}, | ||
| 449 | {0x00016450, 0x8036db6c}, | ||
| 450 | {0x00016454, 0x6db60000}, | ||
| 451 | {0x00016500, 0x07ff8001}, | ||
| 452 | {0x00016508, 0x00080010}, | ||
| 453 | {0x00016544, 0x01884080}, | ||
| 454 | {0x00016548, 0x000080d8}, | ||
| 455 | {0x00016780, 0x00000000}, | ||
| 456 | {0x00016784, 0x00000000}, | ||
| 457 | {0x00016788, 0x00800700}, | ||
| 458 | {0x0001678c, 0x00800700}, | ||
| 459 | {0x00016790, 0x00800700}, | ||
| 460 | {0x00016794, 0x00000000}, | ||
| 461 | {0x00016798, 0x00000000}, | ||
| 462 | {0x0001679c, 0x00000000}, | ||
| 463 | {0x000167a0, 0x00000001}, | ||
| 464 | {0x000167a4, 0x00000001}, | ||
| 465 | {0x000167a8, 0x00000000}, | ||
| 466 | {0x000167ac, 0x00000000}, | ||
| 467 | {0x000167b0, 0x00000000}, | ||
| 468 | {0x000167b4, 0x00000000}, | ||
| 469 | {0x000167b8, 0x00000000}, | ||
| 470 | {0x000167bc, 0x00000000}, | ||
| 471 | {0x000167c0, 0x000000a0}, | ||
| 472 | {0x000167c4, 0x000c0000}, | ||
| 473 | {0x000167c8, 0x14021402}, | ||
| 474 | {0x000167cc, 0x00001402}, | ||
| 475 | {0x000167d0, 0x00000000}, | ||
| 476 | {0x000167d4, 0x00000000}, | ||
| 477 | }; | ||
| 478 | |||
| 479 | static const u32 qca953x_1p0_radio_postamble[][5] = { | ||
| 480 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
| 481 | {0x00016098, 0xd2dd5554, 0xd2dd5554, 0xc4128f5c, 0xc4128f5c}, | ||
| 482 | {0x0001609c, 0x0a566f3a, 0x0a566f3a, 0x0fd08f25, 0x0fd08f25}, | ||
| 483 | {0x000160ac, 0xa4647c00, 0xa4647c00, 0x24646800, 0x24646800}, | ||
| 484 | {0x000160b0, 0x01885f52, 0x01885f52, 0x00fe7f46, 0x00fe7f46}, | ||
| 485 | {0x00016104, 0xb7a00001, 0xb7a00001, 0xfff80005, 0xfff80005}, | ||
| 486 | {0x0001610c, 0xc0000000, 0xc0000000, 0x00000000, 0x00000000}, | ||
| 487 | {0x00016140, 0x10804008, 0x10804008, 0x50804000, 0x50804000}, | ||
| 488 | {0x00016504, 0xb7a00001, 0xb7a00001, 0xfff80001, 0xfff80001}, | ||
| 489 | {0x0001650c, 0xc0000000, 0xc0000000, 0x00000000, 0x00000000}, | ||
| 490 | {0x00016540, 0x10804008, 0x10804008, 0x50804000, 0x50804000}, | ||
| 491 | }; | ||
| 492 | |||
| 493 | static const u32 qca953x_1p0_soc_preamble[][2] = { | ||
| 494 | /* Addr allmodes */ | ||
| 495 | {0x00007000, 0x00000000}, | ||
| 496 | {0x00007004, 0x00000000}, | ||
| 497 | {0x00007008, 0x00000000}, | ||
| 498 | {0x0000700c, 0x00000000}, | ||
| 499 | {0x0000701c, 0x00000000}, | ||
| 500 | {0x00007020, 0x00000000}, | ||
| 501 | {0x00007024, 0x00000000}, | ||
| 502 | {0x00007028, 0x00000000}, | ||
| 503 | {0x0000702c, 0x00000000}, | ||
| 504 | {0x00007030, 0x00000000}, | ||
| 505 | {0x00007034, 0x00000002}, | ||
| 506 | {0x00007038, 0x000004c2}, | ||
| 507 | {0x00007048, 0x00000000}, | ||
| 508 | }; | ||
| 509 | |||
| 510 | static const u32 qca953x_1p0_common_rx_gain_bounds[][5] = { | ||
| 511 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
| 512 | {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, | ||
| 513 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302018, 0x50302018}, | ||
| 514 | }; | ||
| 515 | |||
| 516 | static const u32 qca953x_1p0_common_wo_xlna_rx_gain_bounds[][5] = { | ||
| 517 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
| 518 | {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, | ||
| 519 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, | ||
| 520 | }; | ||
| 521 | |||
| 522 | static const u32 qca953x_1p0_modes_xpa_tx_gain_table[][2] = { | ||
| 523 | /* Addr allmodes */ | ||
| 524 | {0x0000a2dc, 0xfffd5aaa}, | ||
| 525 | {0x0000a2e0, 0xfffe9ccc}, | ||
| 526 | {0x0000a2e4, 0xffffe0f0}, | ||
| 527 | {0x0000a2e8, 0xfffcff00}, | ||
| 528 | {0x0000a410, 0x000050da}, | ||
| 529 | {0x0000a500, 0x00000000}, | ||
| 530 | {0x0000a504, 0x04000002}, | ||
| 531 | {0x0000a508, 0x08000004}, | ||
| 532 | {0x0000a50c, 0x0c000006}, | ||
| 533 | {0x0000a510, 0x0f00000a}, | ||
| 534 | {0x0000a514, 0x1300000c}, | ||
| 535 | {0x0000a518, 0x1700000e}, | ||
| 536 | {0x0000a51c, 0x1b000064}, | ||
| 537 | {0x0000a520, 0x1f000242}, | ||
| 538 | {0x0000a524, 0x23000229}, | ||
| 539 | {0x0000a528, 0x270002a2}, | ||
| 540 | {0x0000a52c, 0x2c001203}, | ||
| 541 | {0x0000a530, 0x30001803}, | ||
| 542 | {0x0000a534, 0x33000881}, | ||
| 543 | {0x0000a538, 0x38001809}, | ||
| 544 | {0x0000a53c, 0x3a000814}, | ||
| 545 | {0x0000a540, 0x3f001a0c}, | ||
| 546 | {0x0000a544, 0x43001a0e}, | ||
| 547 | {0x0000a548, 0x46001812}, | ||
| 548 | {0x0000a54c, 0x49001884}, | ||
| 549 | {0x0000a550, 0x4d001e84}, | ||
| 550 | {0x0000a554, 0x50001e69}, | ||
| 551 | {0x0000a558, 0x550006f4}, | ||
| 552 | {0x0000a55c, 0x59000ad3}, | ||
| 553 | {0x0000a560, 0x5e000ad5}, | ||
| 554 | {0x0000a564, 0x61001ced}, | ||
| 555 | {0x0000a568, 0x660018d4}, | ||
| 556 | {0x0000a56c, 0x660018d4}, | ||
| 557 | {0x0000a570, 0x660018d4}, | ||
| 558 | {0x0000a574, 0x660018d4}, | ||
| 559 | {0x0000a578, 0x660018d4}, | ||
| 560 | {0x0000a57c, 0x660018d4}, | ||
| 561 | {0x0000a600, 0x00000000}, | ||
| 562 | {0x0000a604, 0x00000000}, | ||
| 563 | {0x0000a608, 0x00000000}, | ||
| 564 | {0x0000a60c, 0x03804000}, | ||
| 565 | {0x0000a610, 0x0300ca02}, | ||
| 566 | {0x0000a614, 0x00000e04}, | ||
| 567 | {0x0000a618, 0x03014000}, | ||
| 568 | {0x0000a61c, 0x00000000}, | ||
| 569 | {0x0000a620, 0x00000000}, | ||
| 570 | {0x0000a624, 0x03014000}, | ||
| 571 | {0x0000a628, 0x03804c05}, | ||
| 572 | {0x0000a62c, 0x0701de06}, | ||
| 573 | {0x0000a630, 0x07819c07}, | ||
| 574 | {0x0000a634, 0x0701dc07}, | ||
| 575 | {0x0000a638, 0x0701dc07}, | ||
| 576 | {0x0000a63c, 0x0701dc07}, | ||
| 577 | {0x0000b2dc, 0xfffd5aaa}, | ||
| 578 | {0x0000b2e0, 0xfffe9ccc}, | ||
| 579 | {0x0000b2e4, 0xffffe0f0}, | ||
| 580 | {0x0000b2e8, 0xfffcff00}, | ||
| 581 | {0x00016044, 0x010002d4}, | ||
| 582 | {0x00016048, 0x66482400}, | ||
| 583 | {0x00016280, 0x01000015}, | ||
| 584 | {0x00016444, 0x010002d4}, | ||
| 585 | {0x00016448, 0x66482400}, | ||
| 586 | }; | ||
| 587 | |||
| 588 | static const u32 qca953x_1p0_modes_no_xpa_tx_gain_table[][2] = { | ||
| 589 | /* Addr allmodes */ | ||
| 590 | {0x0000a2dc, 0xffd5f552}, | ||
| 591 | {0x0000a2e0, 0xffe60664}, | ||
| 592 | {0x0000a2e4, 0xfff80780}, | ||
| 593 | {0x0000a2e8, 0xfffff800}, | ||
| 594 | {0x0000a410, 0x000050d6}, | ||
| 595 | {0x0000a500, 0x00060020}, | ||
| 596 | {0x0000a504, 0x04060060}, | ||
| 597 | {0x0000a508, 0x080600a0}, | ||
| 598 | {0x0000a50c, 0x0c068020}, | ||
| 599 | {0x0000a510, 0x10068060}, | ||
| 600 | {0x0000a514, 0x140680a0}, | ||
| 601 | {0x0000a518, 0x18090040}, | ||
| 602 | {0x0000a51c, 0x1b090080}, | ||
| 603 | {0x0000a520, 0x1f0900c0}, | ||
| 604 | {0x0000a524, 0x240c0041}, | ||
| 605 | {0x0000a528, 0x280d0021}, | ||
| 606 | {0x0000a52c, 0x2d0f0061}, | ||
| 607 | {0x0000a530, 0x310f00a1}, | ||
| 608 | {0x0000a534, 0x350e00a2}, | ||
| 609 | {0x0000a538, 0x360e80a2}, | ||
| 610 | {0x0000a53c, 0x380f00a2}, | ||
| 611 | {0x0000a540, 0x3b0e00a3}, | ||
| 612 | {0x0000a544, 0x3d110083}, | ||
| 613 | {0x0000a548, 0x3e1100a3}, | ||
| 614 | {0x0000a54c, 0x401100e3}, | ||
| 615 | {0x0000a550, 0x421380e3}, | ||
| 616 | {0x0000a554, 0x431780e3}, | ||
| 617 | {0x0000a558, 0x461f80e3}, | ||
| 618 | {0x0000a55c, 0x461f80e3}, | ||
| 619 | {0x0000a560, 0x461f80e3}, | ||
| 620 | {0x0000a564, 0x461f80e3}, | ||
| 621 | {0x0000a568, 0x461f80e3}, | ||
| 622 | {0x0000a56c, 0x461f80e3}, | ||
| 623 | {0x0000a570, 0x461f80e3}, | ||
| 624 | {0x0000a574, 0x461f80e3}, | ||
| 625 | {0x0000a578, 0x461f80e3}, | ||
| 626 | {0x0000a57c, 0x461f80e3}, | ||
| 627 | {0x0000a600, 0x00000000}, | ||
| 628 | {0x0000a604, 0x00000000}, | ||
| 629 | {0x0000a608, 0x00000000}, | ||
| 630 | {0x0000a60c, 0x00804201}, | ||
| 631 | {0x0000a610, 0x01008201}, | ||
| 632 | {0x0000a614, 0x0180c402}, | ||
| 633 | {0x0000a618, 0x0180c603}, | ||
| 634 | {0x0000a61c, 0x0180c603}, | ||
| 635 | {0x0000a620, 0x01c10603}, | ||
| 636 | {0x0000a624, 0x01c10704}, | ||
| 637 | {0x0000a628, 0x02c18b05}, | ||
| 638 | {0x0000a62c, 0x0301cc07}, | ||
| 639 | {0x0000a630, 0x0301cc07}, | ||
| 640 | {0x0000a634, 0x0301cc07}, | ||
| 641 | {0x0000a638, 0x0301cc07}, | ||
| 642 | {0x0000a63c, 0x0301cc07}, | ||
| 643 | {0x0000b2dc, 0xffd5f552}, | ||
| 644 | {0x0000b2e0, 0xffe60664}, | ||
| 645 | {0x0000b2e4, 0xfff80780}, | ||
| 646 | {0x0000b2e8, 0xfffff800}, | ||
| 647 | {0x00016044, 0x049242db}, | ||
| 648 | {0x00016048, 0x6c927a70}, | ||
| 649 | {0x00016444, 0x049242db}, | ||
| 650 | {0x00016448, 0x6c927a70}, | ||
| 651 | }; | ||
| 652 | |||
| 653 | static const u32 qca953x_1p1_modes_no_xpa_tx_gain_table[][2] = { | ||
| 654 | /* Addr allmodes */ | ||
| 655 | {0x0000a2dc, 0xffd5f552}, | ||
| 656 | {0x0000a2e0, 0xffe60664}, | ||
| 657 | {0x0000a2e4, 0xfff80780}, | ||
| 658 | {0x0000a2e8, 0xfffff800}, | ||
| 659 | {0x0000a410, 0x000050de}, | ||
| 660 | {0x0000a500, 0x00000061}, | ||
| 661 | {0x0000a504, 0x04000063}, | ||
| 662 | {0x0000a508, 0x08000065}, | ||
| 663 | {0x0000a50c, 0x0c000261}, | ||
| 664 | {0x0000a510, 0x10000263}, | ||
| 665 | {0x0000a514, 0x14000265}, | ||
| 666 | {0x0000a518, 0x18000482}, | ||
| 667 | {0x0000a51c, 0x1b000484}, | ||
| 668 | {0x0000a520, 0x1f000486}, | ||
| 669 | {0x0000a524, 0x240008c2}, | ||
| 670 | {0x0000a528, 0x28000cc1}, | ||
| 671 | {0x0000a52c, 0x2d000ce3}, | ||
| 672 | {0x0000a530, 0x31000ce5}, | ||
| 673 | {0x0000a534, 0x350010e5}, | ||
| 674 | {0x0000a538, 0x360012e5}, | ||
| 675 | {0x0000a53c, 0x380014e5}, | ||
| 676 | {0x0000a540, 0x3b0018e5}, | ||
| 677 | {0x0000a544, 0x3d001d04}, | ||
| 678 | {0x0000a548, 0x3e001d05}, | ||
| 679 | {0x0000a54c, 0x40001d07}, | ||
| 680 | {0x0000a550, 0x42001f27}, | ||
| 681 | {0x0000a554, 0x43001f67}, | ||
| 682 | {0x0000a558, 0x46001fe7}, | ||
| 683 | {0x0000a55c, 0x47001f2b}, | ||
| 684 | {0x0000a560, 0x49001f0d}, | ||
| 685 | {0x0000a564, 0x4b001ed2}, | ||
| 686 | {0x0000a568, 0x4c001ed4}, | ||
| 687 | {0x0000a56c, 0x4e001f15}, | ||
| 688 | {0x0000a570, 0x4f001ff6}, | ||
| 689 | {0x0000a574, 0x4f001ff6}, | ||
| 690 | {0x0000a578, 0x4f001ff6}, | ||
| 691 | {0x0000a57c, 0x4f001ff6}, | ||
| 692 | {0x0000a600, 0x00000000}, | ||
| 693 | {0x0000a604, 0x00000000}, | ||
| 694 | {0x0000a608, 0x00000000}, | ||
| 695 | {0x0000a60c, 0x00804201}, | ||
| 696 | {0x0000a610, 0x01008201}, | ||
| 697 | {0x0000a614, 0x0180c402}, | ||
| 698 | {0x0000a618, 0x0180c603}, | ||
| 699 | {0x0000a61c, 0x0180c603}, | ||
| 700 | {0x0000a620, 0x01c10603}, | ||
| 701 | {0x0000a624, 0x01c10704}, | ||
| 702 | {0x0000a628, 0x02c18b05}, | ||
| 703 | {0x0000a62c, 0x02c14c07}, | ||
| 704 | {0x0000a630, 0x01008704}, | ||
| 705 | {0x0000a634, 0x01c10402}, | ||
| 706 | {0x0000a638, 0x0301cc07}, | ||
| 707 | {0x0000a63c, 0x0301cc07}, | ||
| 708 | {0x0000b2dc, 0xffd5f552}, | ||
| 709 | {0x0000b2e0, 0xffe60664}, | ||
| 710 | {0x0000b2e4, 0xfff80780}, | ||
| 711 | {0x0000b2e8, 0xfffff800}, | ||
| 712 | {0x00016044, 0x049242db}, | ||
| 713 | {0x00016048, 0x6c927a70}, | ||
| 714 | {0x00016444, 0x049242db}, | ||
| 715 | {0x00016448, 0x6c927a70}, | ||
| 716 | }; | ||
| 717 | |||
| 718 | #endif /* INITVALS_953X_H */ | ||
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index f2202e78fa7b..f622a986c8cc 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
| @@ -455,10 +455,8 @@ bool ath9k_csa_is_finished(struct ath_softc *sc); | |||
| 455 | 455 | ||
| 456 | void ath_tx_complete_poll_work(struct work_struct *work); | 456 | void ath_tx_complete_poll_work(struct work_struct *work); |
| 457 | void ath_reset_work(struct work_struct *work); | 457 | void ath_reset_work(struct work_struct *work); |
| 458 | void ath_hw_check(struct work_struct *work); | 458 | bool ath_hw_check(struct ath_softc *sc); |
| 459 | void ath_hw_pll_work(struct work_struct *work); | 459 | void ath_hw_pll_work(struct work_struct *work); |
| 460 | void ath_rx_poll(unsigned long data); | ||
| 461 | void ath_start_rx_poll(struct ath_softc *sc, u8 nbeacon); | ||
| 462 | void ath_paprd_calibrate(struct work_struct *work); | 460 | void ath_paprd_calibrate(struct work_struct *work); |
| 463 | void ath_ani_calibrate(unsigned long data); | 461 | void ath_ani_calibrate(unsigned long data); |
| 464 | void ath_start_ani(struct ath_softc *sc); | 462 | void ath_start_ani(struct ath_softc *sc); |
| @@ -722,12 +720,10 @@ struct ath_softc { | |||
| 722 | spinlock_t sc_pcu_lock; | 720 | spinlock_t sc_pcu_lock; |
| 723 | struct mutex mutex; | 721 | struct mutex mutex; |
| 724 | struct work_struct paprd_work; | 722 | struct work_struct paprd_work; |
| 725 | struct work_struct hw_check_work; | ||
| 726 | struct work_struct hw_reset_work; | 723 | struct work_struct hw_reset_work; |
| 727 | struct completion paprd_complete; | 724 | struct completion paprd_complete; |
| 728 | wait_queue_head_t tx_wait; | 725 | wait_queue_head_t tx_wait; |
| 729 | 726 | ||
| 730 | unsigned int hw_busy_count; | ||
| 731 | unsigned long sc_flags; | 727 | unsigned long sc_flags; |
| 732 | unsigned long driver_data; | 728 | unsigned long driver_data; |
| 733 | 729 | ||
| @@ -761,7 +757,6 @@ struct ath_softc { | |||
| 761 | struct ath_beacon_config cur_beacon_conf; | 757 | struct ath_beacon_config cur_beacon_conf; |
| 762 | struct delayed_work tx_complete_work; | 758 | struct delayed_work tx_complete_work; |
| 763 | struct delayed_work hw_pll_work; | 759 | struct delayed_work hw_pll_work; |
| 764 | struct timer_list rx_poll_timer; | ||
| 765 | struct timer_list sleep_timer; | 760 | struct timer_list sleep_timer; |
| 766 | 761 | ||
| 767 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | 762 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 112aff720e13..2e8bba0eb361 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
| @@ -337,8 +337,14 @@ void ath9k_beacon_tasklet(unsigned long data) | |||
| 337 | 337 | ||
| 338 | ath9k_hw_check_nav(ah); | 338 | ath9k_hw_check_nav(ah); |
| 339 | 339 | ||
| 340 | if (!ath9k_hw_check_alive(ah)) | 340 | /* |
| 341 | ieee80211_queue_work(sc->hw, &sc->hw_check_work); | 341 | * If the previous beacon has not been transmitted |
| 342 | * and a MAC/BB hang has been identified, return | ||
| 343 | * here because a chip reset would have been | ||
| 344 | * initiated. | ||
| 345 | */ | ||
| 346 | if (!ath_hw_check(sc)) | ||
| 347 | return; | ||
| 342 | 348 | ||
| 343 | if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) { | 349 | if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) { |
| 344 | ath_dbg(common, BSTUCK, | 350 | ath_dbg(common, BSTUCK, |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index c028df76b564..b41e008298dc 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
| @@ -1077,7 +1077,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, | |||
| 1077 | 1077 | ||
| 1078 | if (ieee80211_is_beacon(hdr->frame_control) && | 1078 | if (ieee80211_is_beacon(hdr->frame_control) && |
| 1079 | !is_zero_ether_addr(common->curbssid) && | 1079 | !is_zero_ether_addr(common->curbssid) && |
| 1080 | ether_addr_equal(hdr->addr3, common->curbssid)) { | 1080 | ether_addr_equal_64bits(hdr->addr3, common->curbssid)) { |
| 1081 | s8 rssi = rxbuf->rxstatus.rs_rssi; | 1081 | s8 rssi = rxbuf->rxstatus.rs_rssi; |
| 1082 | 1082 | ||
| 1083 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) | 1083 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) |
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index cc58a8ee1223..a47ea8423f1e 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
| @@ -107,6 +107,21 @@ static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable) | |||
| 107 | 107 | ||
| 108 | /* Private hardware call ops */ | 108 | /* Private hardware call ops */ |
| 109 | 109 | ||
| 110 | static inline void ath9k_hw_init_hang_checks(struct ath_hw *ah) | ||
| 111 | { | ||
| 112 | ath9k_hw_private_ops(ah)->init_hang_checks(ah); | ||
| 113 | } | ||
| 114 | |||
| 115 | static inline bool ath9k_hw_detect_mac_hang(struct ath_hw *ah) | ||
| 116 | { | ||
| 117 | return ath9k_hw_private_ops(ah)->detect_mac_hang(ah); | ||
| 118 | } | ||
| 119 | |||
| 120 | static inline bool ath9k_hw_detect_bb_hang(struct ath_hw *ah) | ||
| 121 | { | ||
| 122 | return ath9k_hw_private_ops(ah)->detect_bb_hang(ah); | ||
| 123 | } | ||
| 124 | |||
| 110 | /* PHY ops */ | 125 | /* PHY ops */ |
| 111 | 126 | ||
| 112 | static inline int ath9k_hw_rf_set_freq(struct ath_hw *ah, | 127 | static inline int ath9k_hw_rf_set_freq(struct ath_hw *ah, |
| @@ -232,4 +247,31 @@ static inline void ath9k_hw_set_radar_params(struct ath_hw *ah) | |||
| 232 | ath9k_hw_private_ops(ah)->set_radar_params(ah, &ah->radar_conf); | 247 | ath9k_hw_private_ops(ah)->set_radar_params(ah, &ah->radar_conf); |
| 233 | } | 248 | } |
| 234 | 249 | ||
| 250 | static inline void ath9k_hw_init_cal_settings(struct ath_hw *ah) | ||
| 251 | { | ||
| 252 | ath9k_hw_private_ops(ah)->init_cal_settings(ah); | ||
| 253 | } | ||
| 254 | |||
| 255 | static inline u32 ath9k_hw_compute_pll_control(struct ath_hw *ah, | ||
| 256 | struct ath9k_channel *chan) | ||
| 257 | { | ||
| 258 | return ath9k_hw_private_ops(ah)->compute_pll_control(ah, chan); | ||
| 259 | } | ||
| 260 | |||
| 261 | static inline void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) | ||
| 262 | { | ||
| 263 | if (!ath9k_hw_private_ops(ah)->init_mode_gain_regs) | ||
| 264 | return; | ||
| 265 | |||
| 266 | ath9k_hw_private_ops(ah)->init_mode_gain_regs(ah); | ||
| 267 | } | ||
| 268 | |||
| 269 | static inline void ath9k_hw_ani_cache_ini_regs(struct ath_hw *ah) | ||
| 270 | { | ||
| 271 | if (!ath9k_hw_private_ops(ah)->ani_cache_ini_regs) | ||
| 272 | return; | ||
| 273 | |||
| 274 | ath9k_hw_private_ops(ah)->ani_cache_ini_regs(ah); | ||
| 275 | } | ||
| 276 | |||
| 235 | #endif /* ATH9K_HW_OPS_H */ | 277 | #endif /* ATH9K_HW_OPS_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index a4b1ae026216..ce41658a6003 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
| @@ -37,57 +37,6 @@ MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards."); | |||
| 37 | MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards"); | 37 | MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards"); |
| 38 | MODULE_LICENSE("Dual BSD/GPL"); | 38 | MODULE_LICENSE("Dual BSD/GPL"); |
| 39 | 39 | ||
| 40 | static int __init ath9k_init(void) | ||
| 41 | { | ||
| 42 | return 0; | ||
| 43 | } | ||
| 44 | module_init(ath9k_init); | ||
| 45 | |||
| 46 | static void __exit ath9k_exit(void) | ||
| 47 | { | ||
| 48 | return; | ||
| 49 | } | ||
| 50 | module_exit(ath9k_exit); | ||
| 51 | |||
| 52 | /* Private hardware callbacks */ | ||
| 53 | |||
| 54 | static void ath9k_hw_init_cal_settings(struct ath_hw *ah) | ||
| 55 | { | ||
| 56 | ath9k_hw_private_ops(ah)->init_cal_settings(ah); | ||
| 57 | } | ||
| 58 | |||
| 59 | static u32 ath9k_hw_compute_pll_control(struct ath_hw *ah, | ||
| 60 | struct ath9k_channel *chan) | ||
| 61 | { | ||
| 62 | return ath9k_hw_private_ops(ah)->compute_pll_control(ah, chan); | ||
| 63 | } | ||
| 64 | |||
| 65 | static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) | ||
| 66 | { | ||
| 67 | if (!ath9k_hw_private_ops(ah)->init_mode_gain_regs) | ||
| 68 | return; | ||
| 69 | |||
| 70 | ath9k_hw_private_ops(ah)->init_mode_gain_regs(ah); | ||
| 71 | } | ||
| 72 | |||
| 73 | static void ath9k_hw_ani_cache_ini_regs(struct ath_hw *ah) | ||
| 74 | { | ||
| 75 | /* You will not have this callback if using the old ANI */ | ||
| 76 | if (!ath9k_hw_private_ops(ah)->ani_cache_ini_regs) | ||
| 77 | return; | ||
| 78 | |||
| 79 | ath9k_hw_private_ops(ah)->ani_cache_ini_regs(ah); | ||
| 80 | } | ||
| 81 | |||
| 82 | /********************/ | ||
| 83 | /* Helper Functions */ | ||
| 84 | /********************/ | ||
| 85 | |||
| 86 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
| 87 | |||
| 88 | #endif | ||
| 89 | |||
| 90 | |||
| 91 | static void ath9k_hw_set_clockrate(struct ath_hw *ah) | 40 | static void ath9k_hw_set_clockrate(struct ath_hw *ah) |
| 92 | { | 41 | { |
| 93 | struct ath_common *common = ath9k_hw_common(ah); | 42 | struct ath_common *common = ath9k_hw_common(ah); |
| @@ -296,6 +245,9 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah) | |||
| 296 | case AR9300_DEVID_QCA955X: | 245 | case AR9300_DEVID_QCA955X: |
| 297 | ah->hw_version.macVersion = AR_SREV_VERSION_9550; | 246 | ah->hw_version.macVersion = AR_SREV_VERSION_9550; |
| 298 | return; | 247 | return; |
| 248 | case AR9300_DEVID_AR953X: | ||
| 249 | ah->hw_version.macVersion = AR_SREV_VERSION_9531; | ||
| 250 | return; | ||
| 299 | } | 251 | } |
| 300 | 252 | ||
| 301 | val = REG_READ(ah, AR_SREV) & AR_SREV_ID; | 253 | val = REG_READ(ah, AR_SREV) & AR_SREV_ID; |
| @@ -397,9 +349,10 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) | |||
| 397 | 349 | ||
| 398 | static void ath9k_hw_init_config(struct ath_hw *ah) | 350 | static void ath9k_hw_init_config(struct ath_hw *ah) |
| 399 | { | 351 | { |
| 352 | struct ath_common *common = ath9k_hw_common(ah); | ||
| 353 | |||
| 400 | ah->config.dma_beacon_response_time = 1; | 354 | ah->config.dma_beacon_response_time = 1; |
| 401 | ah->config.sw_beacon_response_time = 6; | 355 | ah->config.sw_beacon_response_time = 6; |
| 402 | ah->config.ack_6mb = 0x0; | ||
| 403 | ah->config.cwm_ignore_extcca = 0; | 356 | ah->config.cwm_ignore_extcca = 0; |
| 404 | ah->config.analog_shiftreg = 1; | 357 | ah->config.analog_shiftreg = 1; |
| 405 | 358 | ||
| @@ -423,6 +376,24 @@ static void ath9k_hw_init_config(struct ath_hw *ah) | |||
| 423 | */ | 376 | */ |
| 424 | if (num_possible_cpus() > 1) | 377 | if (num_possible_cpus() > 1) |
| 425 | ah->config.serialize_regmode = SER_REG_MODE_AUTO; | 378 | ah->config.serialize_regmode = SER_REG_MODE_AUTO; |
| 379 | |||
| 380 | if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_AUTO) { | ||
| 381 | if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI || | ||
| 382 | ((AR_SREV_9160(ah) || AR_SREV_9280(ah) || AR_SREV_9287(ah)) && | ||
| 383 | !ah->is_pciexpress)) { | ||
| 384 | ah->config.serialize_regmode = SER_REG_MODE_ON; | ||
| 385 | } else { | ||
| 386 | ah->config.serialize_regmode = SER_REG_MODE_OFF; | ||
| 387 | } | ||
| 388 | } | ||
| 389 | |||
| 390 | ath_dbg(common, RESET, "serialize_regmode is %d\n", | ||
| 391 | ah->config.serialize_regmode); | ||
| 392 | |||
| 393 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) | ||
| 394 | ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD >> 1; | ||
| 395 | else | ||
| 396 | ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD; | ||
| 426 | } | 397 | } |
| 427 | 398 | ||
| 428 | static void ath9k_hw_init_defaults(struct ath_hw *ah) | 399 | static void ath9k_hw_init_defaults(struct ath_hw *ah) |
| @@ -435,15 +406,24 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) | |||
| 435 | ah->hw_version.magic = AR5416_MAGIC; | 406 | ah->hw_version.magic = AR5416_MAGIC; |
| 436 | ah->hw_version.subvendorid = 0; | 407 | ah->hw_version.subvendorid = 0; |
| 437 | 408 | ||
| 438 | ah->sta_id1_defaults = | 409 | ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE | |
| 439 | AR_STA_ID1_CRPT_MIC_ENABLE | | 410 | AR_STA_ID1_MCAST_KSRCH; |
| 440 | AR_STA_ID1_MCAST_KSRCH; | ||
| 441 | if (AR_SREV_9100(ah)) | 411 | if (AR_SREV_9100(ah)) |
| 442 | ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX; | 412 | ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX; |
| 413 | |||
| 443 | ah->slottime = ATH9K_SLOT_TIME_9; | 414 | ah->slottime = ATH9K_SLOT_TIME_9; |
| 444 | ah->globaltxtimeout = (u32) -1; | 415 | ah->globaltxtimeout = (u32) -1; |
| 445 | ah->power_mode = ATH9K_PM_UNDEFINED; | 416 | ah->power_mode = ATH9K_PM_UNDEFINED; |
| 446 | ah->htc_reset_init = true; | 417 | ah->htc_reset_init = true; |
| 418 | |||
| 419 | ah->ani_function = ATH9K_ANI_ALL; | ||
| 420 | if (!AR_SREV_9300_20_OR_LATER(ah)) | ||
| 421 | ah->ani_function &= ~ATH9K_ANI_MRC_CCK; | ||
| 422 | |||
| 423 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) | ||
| 424 | ah->tx_trig_level = (AR_FTRIG_256B >> AR_FTRIG_S); | ||
| 425 | else | ||
| 426 | ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S); | ||
| 447 | } | 427 | } |
| 448 | 428 | ||
| 449 | static int ath9k_hw_init_macaddr(struct ath_hw *ah) | 429 | static int ath9k_hw_init_macaddr(struct ath_hw *ah) |
| @@ -525,6 +505,31 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
| 525 | 505 | ||
| 526 | ath9k_hw_read_revisions(ah); | 506 | ath9k_hw_read_revisions(ah); |
| 527 | 507 | ||
| 508 | switch (ah->hw_version.macVersion) { | ||
| 509 | case AR_SREV_VERSION_5416_PCI: | ||
| 510 | case AR_SREV_VERSION_5416_PCIE: | ||
| 511 | case AR_SREV_VERSION_9160: | ||
| 512 | case AR_SREV_VERSION_9100: | ||
| 513 | case AR_SREV_VERSION_9280: | ||
| 514 | case AR_SREV_VERSION_9285: | ||
| 515 | case AR_SREV_VERSION_9287: | ||
| 516 | case AR_SREV_VERSION_9271: | ||
| 517 | case AR_SREV_VERSION_9300: | ||
| 518 | case AR_SREV_VERSION_9330: | ||
| 519 | case AR_SREV_VERSION_9485: | ||
| 520 | case AR_SREV_VERSION_9340: | ||
| 521 | case AR_SREV_VERSION_9462: | ||
| 522 | case AR_SREV_VERSION_9550: | ||
| 523 | case AR_SREV_VERSION_9565: | ||
| 524 | case AR_SREV_VERSION_9531: | ||
| 525 | break; | ||
| 526 | default: | ||
| 527 | ath_err(common, | ||
| 528 | "Mac Chip Rev 0x%02x.%x is not supported by this driver\n", | ||
| 529 | ah->hw_version.macVersion, ah->hw_version.macRev); | ||
| 530 | return -EOPNOTSUPP; | ||
| 531 | } | ||
| 532 | |||
| 528 | /* | 533 | /* |
| 529 | * Read back AR_WA into a permanent copy and set bits 14 and 17. | 534 | * Read back AR_WA into a permanent copy and set bits 14 and 17. |
| 530 | * We need to do this to avoid RMW of this register. We cannot | 535 | * We need to do this to avoid RMW of this register. We cannot |
| @@ -558,50 +563,6 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
| 558 | return -EIO; | 563 | return -EIO; |
| 559 | } | 564 | } |
| 560 | 565 | ||
| 561 | if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_AUTO) { | ||
| 562 | if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI || | ||
| 563 | ((AR_SREV_9160(ah) || AR_SREV_9280(ah) || AR_SREV_9287(ah)) && | ||
| 564 | !ah->is_pciexpress)) { | ||
| 565 | ah->config.serialize_regmode = | ||
| 566 | SER_REG_MODE_ON; | ||
| 567 | } else { | ||
| 568 | ah->config.serialize_regmode = | ||
| 569 | SER_REG_MODE_OFF; | ||
| 570 | } | ||
| 571 | } | ||
| 572 | |||
| 573 | ath_dbg(common, RESET, "serialize_regmode is %d\n", | ||
| 574 | ah->config.serialize_regmode); | ||
| 575 | |||
| 576 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) | ||
| 577 | ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD >> 1; | ||
| 578 | else | ||
| 579 | ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD; | ||
| 580 | |||
| 581 | switch (ah->hw_version.macVersion) { | ||
| 582 | case AR_SREV_VERSION_5416_PCI: | ||
| 583 | case AR_SREV_VERSION_5416_PCIE: | ||
| 584 | case AR_SREV_VERSION_9160: | ||
| 585 | case AR_SREV_VERSION_9100: | ||
| 586 | case AR_SREV_VERSION_9280: | ||
| 587 | case AR_SREV_VERSION_9285: | ||
| 588 | case AR_SREV_VERSION_9287: | ||
| 589 | case AR_SREV_VERSION_9271: | ||
| 590 | case AR_SREV_VERSION_9300: | ||
| 591 | case AR_SREV_VERSION_9330: | ||
| 592 | case AR_SREV_VERSION_9485: | ||
| 593 | case AR_SREV_VERSION_9340: | ||
| 594 | case AR_SREV_VERSION_9462: | ||
| 595 | case AR_SREV_VERSION_9550: | ||
| 596 | case AR_SREV_VERSION_9565: | ||
| 597 | break; | ||
| 598 | default: | ||
| 599 | ath_err(common, | ||
| 600 | "Mac Chip Rev 0x%02x.%x is not supported by this driver\n", | ||
| 601 | ah->hw_version.macVersion, ah->hw_version.macRev); | ||
| 602 | return -EOPNOTSUPP; | ||
| 603 | } | ||
| 604 | |||
| 605 | if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah) || | 566 | if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah) || |
| 606 | AR_SREV_9330(ah) || AR_SREV_9550(ah)) | 567 | AR_SREV_9330(ah) || AR_SREV_9550(ah)) |
| 607 | ah->is_pciexpress = false; | 568 | ah->is_pciexpress = false; |
| @@ -609,10 +570,6 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
| 609 | ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); | 570 | ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); |
| 610 | ath9k_hw_init_cal_settings(ah); | 571 | ath9k_hw_init_cal_settings(ah); |
| 611 | 572 | ||
| 612 | ah->ani_function = ATH9K_ANI_ALL; | ||
| 613 | if (!AR_SREV_9300_20_OR_LATER(ah)) | ||
| 614 | ah->ani_function &= ~ATH9K_ANI_MRC_CCK; | ||
| 615 | |||
| 616 | if (!ah->is_pciexpress) | 573 | if (!ah->is_pciexpress) |
| 617 | ath9k_hw_disablepcie(ah); | 574 | ath9k_hw_disablepcie(ah); |
| 618 | 575 | ||
| @@ -631,15 +588,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
| 631 | return r; | 588 | return r; |
| 632 | } | 589 | } |
| 633 | 590 | ||
| 634 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) | 591 | ath9k_hw_init_hang_checks(ah); |
| 635 | ah->tx_trig_level = (AR_FTRIG_256B >> AR_FTRIG_S); | ||
| 636 | else | ||
| 637 | ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S); | ||
| 638 | |||
| 639 | if (AR_SREV_9330(ah)) | ||
| 640 | ah->bb_watchdog_timeout_ms = 85; | ||
| 641 | else | ||
| 642 | ah->bb_watchdog_timeout_ms = 25; | ||
| 643 | 592 | ||
| 644 | common->state = ATH_HW_INITIALIZED; | 593 | common->state = ATH_HW_INITIALIZED; |
| 645 | 594 | ||
| @@ -672,6 +621,7 @@ int ath9k_hw_init(struct ath_hw *ah) | |||
| 672 | case AR9300_DEVID_AR9462: | 621 | case AR9300_DEVID_AR9462: |
| 673 | case AR9485_DEVID_AR1111: | 622 | case AR9485_DEVID_AR1111: |
| 674 | case AR9300_DEVID_AR9565: | 623 | case AR9300_DEVID_AR9565: |
| 624 | case AR9300_DEVID_AR953X: | ||
| 675 | break; | 625 | break; |
| 676 | default: | 626 | default: |
| 677 | if (common->bus_ops->ath_bus_type == ATH_USB) | 627 | if (common->bus_ops->ath_bus_type == ATH_USB) |
| @@ -807,7 +757,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, | |||
| 807 | /* program BB PLL phase_shift */ | 757 | /* program BB PLL phase_shift */ |
| 808 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, | 758 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, |
| 809 | AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x1); | 759 | AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x1); |
| 810 | } else if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) { | 760 | } else if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) { |
| 811 | u32 regval, pll2_divint, pll2_divfrac, refdiv; | 761 | u32 regval, pll2_divint, pll2_divfrac, refdiv; |
| 812 | 762 | ||
| 813 | REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); | 763 | REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); |
| @@ -817,9 +767,15 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, | |||
| 817 | udelay(100); | 767 | udelay(100); |
| 818 | 768 | ||
| 819 | if (ah->is_clk_25mhz) { | 769 | if (ah->is_clk_25mhz) { |
| 820 | pll2_divint = 0x54; | 770 | if (AR_SREV_9531(ah)) { |
| 821 | pll2_divfrac = 0x1eb85; | 771 | pll2_divint = 0x1c; |
| 822 | refdiv = 3; | 772 | pll2_divfrac = 0xa3d2; |
| 773 | refdiv = 1; | ||
| 774 | } else { | ||
| 775 | pll2_divint = 0x54; | ||
| 776 | pll2_divfrac = 0x1eb85; | ||
| 777 | refdiv = 3; | ||
| 778 | } | ||
| 823 | } else { | 779 | } else { |
| 824 | if (AR_SREV_9340(ah)) { | 780 | if (AR_SREV_9340(ah)) { |
| 825 | pll2_divint = 88; | 781 | pll2_divint = 88; |
| @@ -833,7 +789,10 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, | |||
| 833 | } | 789 | } |
| 834 | 790 | ||
| 835 | regval = REG_READ(ah, AR_PHY_PLL_MODE); | 791 | regval = REG_READ(ah, AR_PHY_PLL_MODE); |
| 836 | regval |= (0x1 << 16); | 792 | if (AR_SREV_9531(ah)) |
| 793 | regval |= (0x1 << 22); | ||
| 794 | else | ||
| 795 | regval |= (0x1 << 16); | ||
| 837 | REG_WRITE(ah, AR_PHY_PLL_MODE, regval); | 796 | REG_WRITE(ah, AR_PHY_PLL_MODE, regval); |
| 838 | udelay(100); | 797 | udelay(100); |
| 839 | 798 | ||
| @@ -843,14 +802,33 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, | |||
| 843 | 802 | ||
| 844 | regval = REG_READ(ah, AR_PHY_PLL_MODE); | 803 | regval = REG_READ(ah, AR_PHY_PLL_MODE); |
| 845 | if (AR_SREV_9340(ah)) | 804 | if (AR_SREV_9340(ah)) |
| 846 | regval = (regval & 0x80071fff) | (0x1 << 30) | | 805 | regval = (regval & 0x80071fff) | |
| 847 | (0x1 << 13) | (0x4 << 26) | (0x18 << 19); | 806 | (0x1 << 30) | |
| 807 | (0x1 << 13) | | ||
| 808 | (0x4 << 26) | | ||
| 809 | (0x18 << 19); | ||
| 810 | else if (AR_SREV_9531(ah)) | ||
| 811 | regval = (regval & 0x01c00fff) | | ||
| 812 | (0x1 << 31) | | ||
| 813 | (0x2 << 29) | | ||
| 814 | (0xa << 25) | | ||
| 815 | (0x1 << 19) | | ||
| 816 | (0x6 << 12); | ||
| 848 | else | 817 | else |
| 849 | regval = (regval & 0x80071fff) | (0x3 << 30) | | 818 | regval = (regval & 0x80071fff) | |
| 850 | (0x1 << 13) | (0x4 << 26) | (0x60 << 19); | 819 | (0x3 << 30) | |
| 820 | (0x1 << 13) | | ||
| 821 | (0x4 << 26) | | ||
| 822 | (0x60 << 19); | ||
| 851 | REG_WRITE(ah, AR_PHY_PLL_MODE, regval); | 823 | REG_WRITE(ah, AR_PHY_PLL_MODE, regval); |
| 852 | REG_WRITE(ah, AR_PHY_PLL_MODE, | 824 | |
| 853 | REG_READ(ah, AR_PHY_PLL_MODE) & 0xfffeffff); | 825 | if (AR_SREV_9531(ah)) |
| 826 | REG_WRITE(ah, AR_PHY_PLL_MODE, | ||
| 827 | REG_READ(ah, AR_PHY_PLL_MODE) & 0xffbfffff); | ||
| 828 | else | ||
| 829 | REG_WRITE(ah, AR_PHY_PLL_MODE, | ||
| 830 | REG_READ(ah, AR_PHY_PLL_MODE) & 0xfffeffff); | ||
| 831 | |||
| 854 | udelay(1000); | 832 | udelay(1000); |
| 855 | } | 833 | } |
| 856 | 834 | ||
| @@ -1532,76 +1510,6 @@ static void ath9k_hw_apply_gpio_override(struct ath_hw *ah) | |||
| 1532 | } | 1510 | } |
| 1533 | } | 1511 | } |
| 1534 | 1512 | ||
| 1535 | static bool ath9k_hw_check_dcs(u32 dma_dbg, u32 num_dcu_states, | ||
| 1536 | int *hang_state, int *hang_pos) | ||
| 1537 | { | ||
| 1538 | static u32 dcu_chain_state[] = {5, 6, 9}; /* DCU chain stuck states */ | ||
| 1539 | u32 chain_state, dcs_pos, i; | ||
| 1540 | |||
| 1541 | for (dcs_pos = 0; dcs_pos < num_dcu_states; dcs_pos++) { | ||
| 1542 | chain_state = (dma_dbg >> (5 * dcs_pos)) & 0x1f; | ||
| 1543 | for (i = 0; i < 3; i++) { | ||
| 1544 | if (chain_state == dcu_chain_state[i]) { | ||
| 1545 | *hang_state = chain_state; | ||
| 1546 | *hang_pos = dcs_pos; | ||
| 1547 | return true; | ||
| 1548 | } | ||
| 1549 | } | ||
| 1550 | } | ||
| 1551 | return false; | ||
| 1552 | } | ||
| 1553 | |||
| 1554 | #define DCU_COMPLETE_STATE 1 | ||
| 1555 | #define DCU_COMPLETE_STATE_MASK 0x3 | ||
| 1556 | #define NUM_STATUS_READS 50 | ||
| 1557 | static bool ath9k_hw_detect_mac_hang(struct ath_hw *ah) | ||
| 1558 | { | ||
| 1559 | u32 chain_state, comp_state, dcs_reg = AR_DMADBG_4; | ||
| 1560 | u32 i, hang_pos, hang_state, num_state = 6; | ||
| 1561 | |||
| 1562 | comp_state = REG_READ(ah, AR_DMADBG_6); | ||
| 1563 | |||
| 1564 | if ((comp_state & DCU_COMPLETE_STATE_MASK) != DCU_COMPLETE_STATE) { | ||
| 1565 | ath_dbg(ath9k_hw_common(ah), RESET, | ||
| 1566 | "MAC Hang signature not found at DCU complete\n"); | ||
| 1567 | return false; | ||
| 1568 | } | ||
| 1569 | |||
| 1570 | chain_state = REG_READ(ah, dcs_reg); | ||
| 1571 | if (ath9k_hw_check_dcs(chain_state, num_state, &hang_state, &hang_pos)) | ||
| 1572 | goto hang_check_iter; | ||
| 1573 | |||
| 1574 | dcs_reg = AR_DMADBG_5; | ||
| 1575 | num_state = 4; | ||
| 1576 | chain_state = REG_READ(ah, dcs_reg); | ||
| 1577 | if (ath9k_hw_check_dcs(chain_state, num_state, &hang_state, &hang_pos)) | ||
| 1578 | goto hang_check_iter; | ||
| 1579 | |||
| 1580 | ath_dbg(ath9k_hw_common(ah), RESET, | ||
| 1581 | "MAC Hang signature 1 not found\n"); | ||
| 1582 | return false; | ||
| 1583 | |||
| 1584 | hang_check_iter: | ||
| 1585 | ath_dbg(ath9k_hw_common(ah), RESET, | ||
| 1586 | "DCU registers: chain %08x complete %08x Hang: state %d pos %d\n", | ||
| 1587 | chain_state, comp_state, hang_state, hang_pos); | ||
| 1588 | |||
| 1589 | for (i = 0; i < NUM_STATUS_READS; i++) { | ||
| 1590 | chain_state = REG_READ(ah, dcs_reg); | ||
| 1591 | chain_state = (chain_state >> (5 * hang_pos)) & 0x1f; | ||
| 1592 | comp_state = REG_READ(ah, AR_DMADBG_6); | ||
| 1593 | |||
| 1594 | if (((comp_state & DCU_COMPLETE_STATE_MASK) != | ||
| 1595 | DCU_COMPLETE_STATE) || | ||
| 1596 | (chain_state != hang_state)) | ||
| 1597 | return false; | ||
| 1598 | } | ||
| 1599 | |||
| 1600 | ath_dbg(ath9k_hw_common(ah), RESET, "MAC Hang signature 1 found\n"); | ||
| 1601 | |||
| 1602 | return true; | ||
| 1603 | } | ||
| 1604 | |||
| 1605 | void ath9k_hw_check_nav(struct ath_hw *ah) | 1513 | void ath9k_hw_check_nav(struct ath_hw *ah) |
| 1606 | { | 1514 | { |
| 1607 | struct ath_common *common = ath9k_hw_common(ah); | 1515 | struct ath_common *common = ath9k_hw_common(ah); |
| @@ -1676,7 +1584,6 @@ static void ath9k_hw_reset_opmode(struct ath_hw *ah, | |||
| 1676 | 1584 | ||
| 1677 | REG_RMW(ah, AR_STA_ID1, macStaId1 | 1585 | REG_RMW(ah, AR_STA_ID1, macStaId1 |
| 1678 | | AR_STA_ID1_RTS_USE_DEF | 1586 | | AR_STA_ID1_RTS_USE_DEF |
| 1679 | | (ah->config.ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0) | ||
| 1680 | | ah->sta_id1_defaults, | 1587 | | ah->sta_id1_defaults, |
| 1681 | ~AR_STA_ID1_SADH_MASK); | 1588 | ~AR_STA_ID1_SADH_MASK); |
| 1682 | ath_hw_setbssidmask(common); | 1589 | ath_hw_setbssidmask(common); |
| @@ -1735,7 +1642,7 @@ static void ath9k_hw_init_desc(struct ath_hw *ah) | |||
| 1735 | } | 1642 | } |
| 1736 | #ifdef __BIG_ENDIAN | 1643 | #ifdef __BIG_ENDIAN |
| 1737 | else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) || | 1644 | else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) || |
| 1738 | AR_SREV_9550(ah)) | 1645 | AR_SREV_9550(ah) || AR_SREV_9531(ah)) |
| 1739 | REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0); | 1646 | REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0); |
| 1740 | else | 1647 | else |
| 1741 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | 1648 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); |
| @@ -1865,7 +1772,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 1865 | /* Save TSF before chip reset, a cold reset clears it */ | 1772 | /* Save TSF before chip reset, a cold reset clears it */ |
| 1866 | tsf = ath9k_hw_gettsf64(ah); | 1773 | tsf = ath9k_hw_gettsf64(ah); |
| 1867 | getrawmonotonic(&ts); | 1774 | getrawmonotonic(&ts); |
| 1868 | usec = ts.tv_sec * 1000 + ts.tv_nsec / 1000; | 1775 | usec = ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000; |
| 1869 | 1776 | ||
| 1870 | saveLedState = REG_READ(ah, AR_CFG_LED) & | 1777 | saveLedState = REG_READ(ah, AR_CFG_LED) & |
| 1871 | (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | | 1778 | (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | |
| @@ -1899,7 +1806,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 1899 | 1806 | ||
| 1900 | /* Restore TSF */ | 1807 | /* Restore TSF */ |
| 1901 | getrawmonotonic(&ts); | 1808 | getrawmonotonic(&ts); |
| 1902 | usec = ts.tv_sec * 1000 + ts.tv_nsec / 1000 - usec; | 1809 | usec = ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000 - usec; |
| 1903 | ath9k_hw_settsf64(ah, tsf + usec); | 1810 | ath9k_hw_settsf64(ah, tsf + usec); |
| 1904 | 1811 | ||
| 1905 | if (AR_SREV_9280_20_OR_LATER(ah)) | 1812 | if (AR_SREV_9280_20_OR_LATER(ah)) |
| @@ -2008,10 +1915,11 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 2008 | ath9k_hw_loadnf(ah, chan); | 1915 | ath9k_hw_loadnf(ah, chan); |
| 2009 | ath9k_hw_start_nfcal(ah, true); | 1916 | ath9k_hw_start_nfcal(ah, true); |
| 2010 | 1917 | ||
| 2011 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 1918 | if (AR_SREV_9300_20_OR_LATER(ah)) |
| 2012 | ar9003_hw_bb_watchdog_config(ah); | 1919 | ar9003_hw_bb_watchdog_config(ah); |
| 1920 | |||
| 1921 | if (ah->config.hw_hang_checks & HW_PHYRESTART_CLC_WAR) | ||
| 2013 | ar9003_hw_disable_phy_restart(ah); | 1922 | ar9003_hw_disable_phy_restart(ah); |
| 2014 | } | ||
| 2015 | 1923 | ||
| 2016 | ath9k_hw_apply_gpio_override(ah); | 1924 | ath9k_hw_apply_gpio_override(ah); |
| 2017 | 1925 | ||
| @@ -2135,7 +2043,11 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah) | |||
| 2135 | 2043 | ||
| 2136 | REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, | 2044 | REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, |
| 2137 | AR_RTC_FORCE_WAKE_EN); | 2045 | AR_RTC_FORCE_WAKE_EN); |
| 2138 | udelay(50); | 2046 | |
| 2047 | if (AR_SREV_9100(ah)) | ||
| 2048 | udelay(10000); | ||
| 2049 | else | ||
| 2050 | udelay(50); | ||
| 2139 | 2051 | ||
| 2140 | for (i = POWER_UP_TIME / 50; i > 0; i--) { | 2052 | for (i = POWER_UP_TIME / 50; i > 0; i--) { |
| 2141 | val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; | 2053 | val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; |
| @@ -2564,13 +2476,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
| 2564 | ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) | 2476 | ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) |
| 2565 | pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; | 2477 | pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; |
| 2566 | 2478 | ||
| 2567 | /* | ||
| 2568 | * Fast channel change across bands is available | ||
| 2569 | * only for AR9462 and AR9565. | ||
| 2570 | */ | ||
| 2571 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) | ||
| 2572 | pCap->hw_caps |= ATH9K_HW_CAP_FCC_BAND_SWITCH; | ||
| 2573 | |||
| 2574 | return 0; | 2479 | return 0; |
| 2575 | } | 2480 | } |
| 2576 | 2481 | ||
| @@ -3084,14 +2989,14 @@ void ath_gen_timer_isr(struct ath_hw *ah) | |||
| 3084 | trigger_mask &= timer_table->timer_mask; | 2989 | trigger_mask &= timer_table->timer_mask; |
| 3085 | thresh_mask &= timer_table->timer_mask; | 2990 | thresh_mask &= timer_table->timer_mask; |
| 3086 | 2991 | ||
| 3087 | trigger_mask &= ~thresh_mask; | ||
| 3088 | |||
| 3089 | for_each_set_bit(index, &thresh_mask, ARRAY_SIZE(timer_table->timers)) { | 2992 | for_each_set_bit(index, &thresh_mask, ARRAY_SIZE(timer_table->timers)) { |
| 3090 | timer = timer_table->timers[index]; | 2993 | timer = timer_table->timers[index]; |
| 3091 | if (!timer) | 2994 | if (!timer) |
| 3092 | continue; | 2995 | continue; |
| 3093 | if (!timer->overflow) | 2996 | if (!timer->overflow) |
| 3094 | continue; | 2997 | continue; |
| 2998 | |||
| 2999 | trigger_mask &= ~BIT(index); | ||
| 3095 | timer->overflow(timer->arg); | 3000 | timer->overflow(timer->arg); |
| 3096 | } | 3001 | } |
| 3097 | 3002 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 6132ffeb3048..e766399bdcda 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
| @@ -52,6 +52,7 @@ | |||
| 52 | #define AR9300_DEVID_QCA955X 0x0038 | 52 | #define AR9300_DEVID_QCA955X 0x0038 |
| 53 | #define AR9485_DEVID_AR1111 0x0037 | 53 | #define AR9485_DEVID_AR1111 0x0037 |
| 54 | #define AR9300_DEVID_AR9565 0x0036 | 54 | #define AR9300_DEVID_AR9565 0x0036 |
| 55 | #define AR9300_DEVID_AR953X 0x003d | ||
| 55 | 56 | ||
| 56 | #define AR5416_AR9100_DEVID 0x000b | 57 | #define AR5416_AR9100_DEVID 0x000b |
| 57 | 58 | ||
| @@ -277,10 +278,24 @@ struct ath9k_hw_capabilities { | |||
| 277 | u8 txs_len; | 278 | u8 txs_len; |
| 278 | }; | 279 | }; |
| 279 | 280 | ||
| 281 | #define AR_NO_SPUR 0x8000 | ||
| 282 | #define AR_BASE_FREQ_2GHZ 2300 | ||
| 283 | #define AR_BASE_FREQ_5GHZ 4900 | ||
| 284 | #define AR_SPUR_FEEQ_BOUND_HT40 19 | ||
| 285 | #define AR_SPUR_FEEQ_BOUND_HT20 10 | ||
| 286 | |||
| 287 | enum ath9k_hw_hang_checks { | ||
| 288 | HW_BB_WATCHDOG = BIT(0), | ||
| 289 | HW_PHYRESTART_CLC_WAR = BIT(1), | ||
| 290 | HW_BB_RIFS_HANG = BIT(2), | ||
| 291 | HW_BB_DFS_HANG = BIT(3), | ||
| 292 | HW_BB_RX_CLEAR_STUCK_HANG = BIT(4), | ||
| 293 | HW_MAC_HANG = BIT(5), | ||
| 294 | }; | ||
| 295 | |||
| 280 | struct ath9k_ops_config { | 296 | struct ath9k_ops_config { |
| 281 | int dma_beacon_response_time; | 297 | int dma_beacon_response_time; |
| 282 | int sw_beacon_response_time; | 298 | int sw_beacon_response_time; |
| 283 | int ack_6mb; | ||
| 284 | u32 cwm_ignore_extcca; | 299 | u32 cwm_ignore_extcca; |
| 285 | u32 pcie_waen; | 300 | u32 pcie_waen; |
| 286 | u8 analog_shiftreg; | 301 | u8 analog_shiftreg; |
| @@ -292,13 +307,9 @@ struct ath9k_ops_config { | |||
| 292 | int serialize_regmode; | 307 | int serialize_regmode; |
| 293 | bool rx_intr_mitigation; | 308 | bool rx_intr_mitigation; |
| 294 | bool tx_intr_mitigation; | 309 | bool tx_intr_mitigation; |
| 295 | #define AR_NO_SPUR 0x8000 | ||
| 296 | #define AR_BASE_FREQ_2GHZ 2300 | ||
| 297 | #define AR_BASE_FREQ_5GHZ 4900 | ||
| 298 | #define AR_SPUR_FEEQ_BOUND_HT40 19 | ||
| 299 | #define AR_SPUR_FEEQ_BOUND_HT20 10 | ||
| 300 | u8 max_txtrig_level; | 310 | u8 max_txtrig_level; |
| 301 | u16 ani_poll_interval; /* ANI poll interval in ms */ | 311 | u16 ani_poll_interval; /* ANI poll interval in ms */ |
| 312 | u16 hw_hang_checks; | ||
| 302 | 313 | ||
| 303 | /* Platform specific config */ | 314 | /* Platform specific config */ |
| 304 | u32 aspm_l1_fix; | 315 | u32 aspm_l1_fix; |
| @@ -573,6 +584,10 @@ struct ath_hw_radar_conf { | |||
| 573 | * register settings through the register initialization. | 584 | * register settings through the register initialization. |
| 574 | */ | 585 | */ |
| 575 | struct ath_hw_private_ops { | 586 | struct ath_hw_private_ops { |
| 587 | void (*init_hang_checks)(struct ath_hw *ah); | ||
| 588 | bool (*detect_mac_hang)(struct ath_hw *ah); | ||
| 589 | bool (*detect_bb_hang)(struct ath_hw *ah); | ||
| 590 | |||
| 576 | /* Calibration ops */ | 591 | /* Calibration ops */ |
| 577 | void (*init_cal_settings)(struct ath_hw *ah); | 592 | void (*init_cal_settings)(struct ath_hw *ah); |
| 578 | bool (*init_cal)(struct ath_hw *ah, struct ath9k_channel *chan); | 593 | bool (*init_cal)(struct ath_hw *ah, struct ath9k_channel *chan); |
| @@ -1029,6 +1044,7 @@ void ar9002_hw_enable_async_fifo(struct ath_hw *ah); | |||
| 1029 | * Code specific to AR9003, we stuff these here to avoid callbacks | 1044 | * Code specific to AR9003, we stuff these here to avoid callbacks |
| 1030 | * for older families | 1045 | * for older families |
| 1031 | */ | 1046 | */ |
| 1047 | bool ar9003_hw_bb_watchdog_check(struct ath_hw *ah); | ||
| 1032 | void ar9003_hw_bb_watchdog_config(struct ath_hw *ah); | 1048 | void ar9003_hw_bb_watchdog_config(struct ath_hw *ah); |
| 1033 | void ar9003_hw_bb_watchdog_read(struct ath_hw *ah); | 1049 | void ar9003_hw_bb_watchdog_read(struct ath_hw *ah); |
| 1034 | void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah); | 1050 | void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah); |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index e63465b7eab9..f2a17fcf1ae4 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
| @@ -763,10 +763,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
| 763 | 763 | ||
| 764 | setup_timer(&sc->sleep_timer, ath_ps_full_sleep, (unsigned long)sc); | 764 | setup_timer(&sc->sleep_timer, ath_ps_full_sleep, (unsigned long)sc); |
| 765 | INIT_WORK(&sc->hw_reset_work, ath_reset_work); | 765 | INIT_WORK(&sc->hw_reset_work, ath_reset_work); |
| 766 | INIT_WORK(&sc->hw_check_work, ath_hw_check); | ||
| 767 | INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); | 766 | INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); |
| 768 | INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); | 767 | INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); |
| 769 | setup_timer(&sc->rx_poll_timer, ath_rx_poll, (unsigned long)sc); | ||
| 770 | 768 | ||
| 771 | /* | 769 | /* |
| 772 | * Cache line size is used to size and align various | 770 | * Cache line size is used to size and align various |
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index aed7e29dc50f..30dcef5aba10 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c | |||
| @@ -65,50 +65,26 @@ void ath_tx_complete_poll_work(struct work_struct *work) | |||
| 65 | /* | 65 | /* |
| 66 | * Checks if the BB/MAC is hung. | 66 | * Checks if the BB/MAC is hung. |
| 67 | */ | 67 | */ |
| 68 | void ath_hw_check(struct work_struct *work) | 68 | bool ath_hw_check(struct ath_softc *sc) |
| 69 | { | 69 | { |
| 70 | struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work); | ||
| 71 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 70 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
| 72 | unsigned long flags; | ||
| 73 | int busy; | ||
| 74 | u8 is_alive, nbeacon = 1; | ||
| 75 | enum ath_reset_type type; | 71 | enum ath_reset_type type; |
| 72 | bool is_alive; | ||
| 76 | 73 | ||
| 77 | ath9k_ps_wakeup(sc); | 74 | ath9k_ps_wakeup(sc); |
| 75 | |||
| 78 | is_alive = ath9k_hw_check_alive(sc->sc_ah); | 76 | is_alive = ath9k_hw_check_alive(sc->sc_ah); |
| 79 | 77 | ||
| 80 | if ((is_alive && !AR_SREV_9300(sc->sc_ah)) || sc->tx99_state) | 78 | if (!is_alive) { |
| 81 | goto out; | ||
| 82 | else if (!is_alive && AR_SREV_9300(sc->sc_ah)) { | ||
| 83 | ath_dbg(common, RESET, | 79 | ath_dbg(common, RESET, |
| 84 | "DCU stuck is detected. Schedule chip reset\n"); | 80 | "HW hang detected, schedule chip reset\n"); |
| 85 | type = RESET_TYPE_MAC_HANG; | 81 | type = RESET_TYPE_MAC_HANG; |
| 86 | goto sched_reset; | 82 | ath9k_queue_reset(sc, type); |
| 87 | } | ||
| 88 | |||
| 89 | spin_lock_irqsave(&common->cc_lock, flags); | ||
| 90 | busy = ath_update_survey_stats(sc); | ||
| 91 | spin_unlock_irqrestore(&common->cc_lock, flags); | ||
| 92 | |||
| 93 | ath_dbg(common, RESET, "Possible baseband hang, busy=%d (try %d)\n", | ||
| 94 | busy, sc->hw_busy_count + 1); | ||
| 95 | if (busy >= 99) { | ||
| 96 | if (++sc->hw_busy_count >= 3) { | ||
| 97 | type = RESET_TYPE_BB_HANG; | ||
| 98 | goto sched_reset; | ||
| 99 | } | ||
| 100 | } else if (busy >= 0) { | ||
| 101 | sc->hw_busy_count = 0; | ||
| 102 | nbeacon = 3; | ||
| 103 | } | 83 | } |
| 104 | 84 | ||
| 105 | ath_start_rx_poll(sc, nbeacon); | ||
| 106 | goto out; | ||
| 107 | |||
| 108 | sched_reset: | ||
| 109 | ath9k_queue_reset(sc, type); | ||
| 110 | out: | ||
| 111 | ath9k_ps_restore(sc); | 85 | ath9k_ps_restore(sc); |
| 86 | |||
| 87 | return is_alive; | ||
| 112 | } | 88 | } |
| 113 | 89 | ||
| 114 | /* | 90 | /* |
| @@ -162,29 +138,6 @@ void ath_hw_pll_work(struct work_struct *work) | |||
| 162 | } | 138 | } |
| 163 | 139 | ||
| 164 | /* | 140 | /* |
| 165 | * RX Polling - monitors baseband hangs. | ||
| 166 | */ | ||
| 167 | void ath_start_rx_poll(struct ath_softc *sc, u8 nbeacon) | ||
| 168 | { | ||
| 169 | if (!AR_SREV_9300(sc->sc_ah)) | ||
| 170 | return; | ||
| 171 | |||
| 172 | if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) | ||
| 173 | return; | ||
| 174 | |||
| 175 | mod_timer(&sc->rx_poll_timer, jiffies + msecs_to_jiffies | ||
| 176 | (nbeacon * sc->cur_beacon_conf.beacon_interval)); | ||
| 177 | } | ||
| 178 | |||
| 179 | void ath_rx_poll(unsigned long data) | ||
| 180 | { | ||
| 181 | struct ath_softc *sc = (struct ath_softc *)data; | ||
| 182 | |||
| 183 | if (!test_bit(SC_OP_INVALID, &sc->sc_flags)) | ||
| 184 | ieee80211_queue_work(sc->hw, &sc->hw_check_work); | ||
| 185 | } | ||
| 186 | |||
| 187 | /* | ||
| 188 | * PA Pre-distortion. | 141 | * PA Pre-distortion. |
| 189 | */ | 142 | */ |
| 190 | static void ath_paprd_activate(struct ath_softc *sc) | 143 | static void ath_paprd_activate(struct ath_softc *sc) |
| @@ -409,10 +362,10 @@ void ath_ani_calibrate(unsigned long data) | |||
| 409 | 362 | ||
| 410 | /* Call ANI routine if necessary */ | 363 | /* Call ANI routine if necessary */ |
| 411 | if (aniflag) { | 364 | if (aniflag) { |
| 412 | spin_lock_irqsave(&common->cc_lock, flags); | 365 | spin_lock(&common->cc_lock); |
| 413 | ath9k_hw_ani_monitor(ah, ah->curchan); | 366 | ath9k_hw_ani_monitor(ah, ah->curchan); |
| 414 | ath_update_survey_stats(sc); | 367 | ath_update_survey_stats(sc); |
| 415 | spin_unlock_irqrestore(&common->cc_lock, flags); | 368 | spin_unlock(&common->cc_lock); |
| 416 | } | 369 | } |
| 417 | 370 | ||
| 418 | /* Perform calibration if necessary */ | 371 | /* Perform calibration if necessary */ |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 89d7e206992b..5f727588ca27 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
| @@ -922,11 +922,29 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah) | |||
| 922 | mask2 |= AR_IMR_S2_CST; | 922 | mask2 |= AR_IMR_S2_CST; |
| 923 | } | 923 | } |
| 924 | 924 | ||
| 925 | if (ah->config.hw_hang_checks & HW_BB_WATCHDOG) { | ||
| 926 | if (ints & ATH9K_INT_BB_WATCHDOG) { | ||
| 927 | mask |= AR_IMR_BCNMISC; | ||
| 928 | mask2 |= AR_IMR_S2_BB_WATCHDOG; | ||
| 929 | } | ||
| 930 | } | ||
| 931 | |||
| 925 | ath_dbg(common, INTERRUPT, "new IMR 0x%x\n", mask); | 932 | ath_dbg(common, INTERRUPT, "new IMR 0x%x\n", mask); |
| 926 | REG_WRITE(ah, AR_IMR, mask); | 933 | REG_WRITE(ah, AR_IMR, mask); |
| 927 | ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC | | 934 | ah->imrs2_reg &= ~(AR_IMR_S2_TIM | |
| 928 | AR_IMR_S2_CABEND | AR_IMR_S2_CABTO | | 935 | AR_IMR_S2_DTIM | |
| 929 | AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST); | 936 | AR_IMR_S2_DTIMSYNC | |
| 937 | AR_IMR_S2_CABEND | | ||
| 938 | AR_IMR_S2_CABTO | | ||
| 939 | AR_IMR_S2_TSFOOR | | ||
| 940 | AR_IMR_S2_GTT | | ||
| 941 | AR_IMR_S2_CST); | ||
| 942 | |||
| 943 | if (ah->config.hw_hang_checks & HW_BB_WATCHDOG) { | ||
| 944 | if (ints & ATH9K_INT_BB_WATCHDOG) | ||
| 945 | ah->imrs2_reg &= ~AR_IMR_S2_BB_WATCHDOG; | ||
| 946 | } | ||
| 947 | |||
| 930 | ah->imrs2_reg |= mask2; | 948 | ah->imrs2_reg |= mask2; |
| 931 | REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); | 949 | REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); |
| 932 | 950 | ||
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 21b764ba6400..d0c3aec7c74e 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
| @@ -170,7 +170,6 @@ void ath9k_ps_restore(struct ath_softc *sc) | |||
| 170 | static void __ath_cancel_work(struct ath_softc *sc) | 170 | static void __ath_cancel_work(struct ath_softc *sc) |
| 171 | { | 171 | { |
| 172 | cancel_work_sync(&sc->paprd_work); | 172 | cancel_work_sync(&sc->paprd_work); |
| 173 | cancel_work_sync(&sc->hw_check_work); | ||
| 174 | cancel_delayed_work_sync(&sc->tx_complete_work); | 173 | cancel_delayed_work_sync(&sc->tx_complete_work); |
| 175 | cancel_delayed_work_sync(&sc->hw_pll_work); | 174 | cancel_delayed_work_sync(&sc->hw_pll_work); |
| 176 | 175 | ||
| @@ -194,7 +193,6 @@ void ath_restart_work(struct ath_softc *sc) | |||
| 194 | ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, | 193 | ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, |
| 195 | msecs_to_jiffies(ATH_PLL_WORK_INTERVAL)); | 194 | msecs_to_jiffies(ATH_PLL_WORK_INTERVAL)); |
| 196 | 195 | ||
| 197 | ath_start_rx_poll(sc, 3); | ||
| 198 | ath_start_ani(sc); | 196 | ath_start_ani(sc); |
| 199 | } | 197 | } |
| 200 | 198 | ||
| @@ -204,11 +202,7 @@ static bool ath_prepare_reset(struct ath_softc *sc) | |||
| 204 | bool ret = true; | 202 | bool ret = true; |
| 205 | 203 | ||
| 206 | ieee80211_stop_queues(sc->hw); | 204 | ieee80211_stop_queues(sc->hw); |
| 207 | |||
| 208 | sc->hw_busy_count = 0; | ||
| 209 | ath_stop_ani(sc); | 205 | ath_stop_ani(sc); |
| 210 | del_timer_sync(&sc->rx_poll_timer); | ||
| 211 | |||
| 212 | ath9k_hw_disable_interrupts(ah); | 206 | ath9k_hw_disable_interrupts(ah); |
| 213 | 207 | ||
| 214 | if (!ath_drain_all_txq(sc)) | 208 | if (!ath_drain_all_txq(sc)) |
| @@ -336,7 +330,6 @@ static int ath_set_channel(struct ath_softc *sc, struct cfg80211_chan_def *chand | |||
| 336 | struct ieee80211_hw *hw = sc->hw; | 330 | struct ieee80211_hw *hw = sc->hw; |
| 337 | struct ath9k_channel *hchan; | 331 | struct ath9k_channel *hchan; |
| 338 | struct ieee80211_channel *chan = chandef->chan; | 332 | struct ieee80211_channel *chan = chandef->chan; |
| 339 | unsigned long flags; | ||
| 340 | bool offchannel; | 333 | bool offchannel; |
| 341 | int pos = chan->hw_value; | 334 | int pos = chan->hw_value; |
| 342 | int old_pos = -1; | 335 | int old_pos = -1; |
| @@ -354,9 +347,9 @@ static int ath_set_channel(struct ath_softc *sc, struct cfg80211_chan_def *chand | |||
| 354 | chan->center_freq, chandef->width); | 347 | chan->center_freq, chandef->width); |
| 355 | 348 | ||
| 356 | /* update survey stats for the old channel before switching */ | 349 | /* update survey stats for the old channel before switching */ |
| 357 | spin_lock_irqsave(&common->cc_lock, flags); | 350 | spin_lock_bh(&common->cc_lock); |
| 358 | ath_update_survey_stats(sc); | 351 | ath_update_survey_stats(sc); |
| 359 | spin_unlock_irqrestore(&common->cc_lock, flags); | 352 | spin_unlock_bh(&common->cc_lock); |
| 360 | 353 | ||
| 361 | ath9k_cmn_get_channel(hw, ah, chandef); | 354 | ath9k_cmn_get_channel(hw, ah, chandef); |
| 362 | 355 | ||
| @@ -427,12 +420,6 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
| 427 | an->vif = vif; | 420 | an->vif = vif; |
| 428 | 421 | ||
| 429 | ath_tx_node_init(sc, an); | 422 | ath_tx_node_init(sc, an); |
| 430 | |||
| 431 | if (sta->ht_cap.ht_supported) { | ||
| 432 | an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + | ||
| 433 | sta->ht_cap.ampdu_factor); | ||
| 434 | an->mpdudensity = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density); | ||
| 435 | } | ||
| 436 | } | 423 | } |
| 437 | 424 | ||
| 438 | static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) | 425 | static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) |
| @@ -454,14 +441,8 @@ void ath9k_tasklet(unsigned long data) | |||
| 454 | ath9k_ps_wakeup(sc); | 441 | ath9k_ps_wakeup(sc); |
| 455 | spin_lock(&sc->sc_pcu_lock); | 442 | spin_lock(&sc->sc_pcu_lock); |
| 456 | 443 | ||
| 457 | if ((status & ATH9K_INT_FATAL) || | 444 | if (status & ATH9K_INT_FATAL) { |
| 458 | (status & ATH9K_INT_BB_WATCHDOG)) { | 445 | type = RESET_TYPE_FATAL_INT; |
| 459 | |||
| 460 | if (status & ATH9K_INT_FATAL) | ||
| 461 | type = RESET_TYPE_FATAL_INT; | ||
| 462 | else | ||
| 463 | type = RESET_TYPE_BB_WATCHDOG; | ||
| 464 | |||
| 465 | ath9k_queue_reset(sc, type); | 446 | ath9k_queue_reset(sc, type); |
| 466 | 447 | ||
| 467 | /* | 448 | /* |
| @@ -473,6 +454,28 @@ void ath9k_tasklet(unsigned long data) | |||
| 473 | goto out; | 454 | goto out; |
| 474 | } | 455 | } |
| 475 | 456 | ||
| 457 | if ((ah->config.hw_hang_checks & HW_BB_WATCHDOG) && | ||
| 458 | (status & ATH9K_INT_BB_WATCHDOG)) { | ||
| 459 | spin_lock(&common->cc_lock); | ||
| 460 | ath_hw_cycle_counters_update(common); | ||
| 461 | ar9003_hw_bb_watchdog_dbg_info(ah); | ||
| 462 | spin_unlock(&common->cc_lock); | ||
| 463 | |||
| 464 | if (ar9003_hw_bb_watchdog_check(ah)) { | ||
| 465 | type = RESET_TYPE_BB_WATCHDOG; | ||
| 466 | ath9k_queue_reset(sc, type); | ||
| 467 | |||
| 468 | /* | ||
| 469 | * Increment the ref. counter here so that | ||
| 470 | * interrupts are enabled in the reset routine. | ||
| 471 | */ | ||
| 472 | atomic_inc(&ah->intr_ref_cnt); | ||
| 473 | ath_dbg(common, ANY, | ||
| 474 | "BB_WATCHDOG: Skipping interrupts\n"); | ||
| 475 | goto out; | ||
| 476 | } | ||
| 477 | } | ||
| 478 | |||
| 476 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | 479 | spin_lock_irqsave(&sc->sc_pm_lock, flags); |
| 477 | if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) { | 480 | if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) { |
| 478 | /* | 481 | /* |
| @@ -541,7 +544,7 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
| 541 | struct ath_hw *ah = sc->sc_ah; | 544 | struct ath_hw *ah = sc->sc_ah; |
| 542 | struct ath_common *common = ath9k_hw_common(ah); | 545 | struct ath_common *common = ath9k_hw_common(ah); |
| 543 | enum ath9k_int status; | 546 | enum ath9k_int status; |
| 544 | u32 sync_cause; | 547 | u32 sync_cause = 0; |
| 545 | bool sched = false; | 548 | bool sched = false; |
| 546 | 549 | ||
| 547 | /* | 550 | /* |
| @@ -593,16 +596,9 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
| 593 | !(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA))) | 596 | !(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA))) |
| 594 | goto chip_reset; | 597 | goto chip_reset; |
| 595 | 598 | ||
| 596 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && | 599 | if ((ah->config.hw_hang_checks & HW_BB_WATCHDOG) && |
| 597 | (status & ATH9K_INT_BB_WATCHDOG)) { | 600 | (status & ATH9K_INT_BB_WATCHDOG)) |
| 598 | |||
| 599 | spin_lock(&common->cc_lock); | ||
| 600 | ath_hw_cycle_counters_update(common); | ||
| 601 | ar9003_hw_bb_watchdog_dbg_info(ah); | ||
| 602 | spin_unlock(&common->cc_lock); | ||
| 603 | |||
| 604 | goto chip_reset; | 601 | goto chip_reset; |
| 605 | } | ||
| 606 | 602 | ||
| 607 | #ifdef CONFIG_ATH9K_WOW | 603 | #ifdef CONFIG_ATH9K_WOW |
| 608 | if (status & ATH9K_INT_BMISS) { | 604 | if (status & ATH9K_INT_BMISS) { |
| @@ -732,11 +728,13 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
| 732 | 728 | ||
| 733 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | 729 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) |
| 734 | ah->imask |= ATH9K_INT_RXHP | | 730 | ah->imask |= ATH9K_INT_RXHP | |
| 735 | ATH9K_INT_RXLP | | 731 | ATH9K_INT_RXLP; |
| 736 | ATH9K_INT_BB_WATCHDOG; | ||
| 737 | else | 732 | else |
| 738 | ah->imask |= ATH9K_INT_RX; | 733 | ah->imask |= ATH9K_INT_RX; |
| 739 | 734 | ||
| 735 | if (ah->config.hw_hang_checks & HW_BB_WATCHDOG) | ||
| 736 | ah->imask |= ATH9K_INT_BB_WATCHDOG; | ||
| 737 | |||
| 740 | ah->imask |= ATH9K_INT_GTT; | 738 | ah->imask |= ATH9K_INT_GTT; |
| 741 | 739 | ||
| 742 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) | 740 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) |
| @@ -860,7 +858,6 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
| 860 | mutex_lock(&sc->mutex); | 858 | mutex_lock(&sc->mutex); |
| 861 | 859 | ||
| 862 | ath_cancel_work(sc); | 860 | ath_cancel_work(sc); |
| 863 | del_timer_sync(&sc->rx_poll_timer); | ||
| 864 | 861 | ||
| 865 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { | 862 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { |
| 866 | ath_dbg(common, ANY, "Device not present\n"); | 863 | ath_dbg(common, ANY, "Device not present\n"); |
| @@ -1791,13 +1788,12 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx, | |||
| 1791 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1788 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
| 1792 | struct ieee80211_supported_band *sband; | 1789 | struct ieee80211_supported_band *sband; |
| 1793 | struct ieee80211_channel *chan; | 1790 | struct ieee80211_channel *chan; |
| 1794 | unsigned long flags; | ||
| 1795 | int pos; | 1791 | int pos; |
| 1796 | 1792 | ||
| 1797 | if (config_enabled(CONFIG_ATH9K_TX99)) | 1793 | if (config_enabled(CONFIG_ATH9K_TX99)) |
| 1798 | return -EOPNOTSUPP; | 1794 | return -EOPNOTSUPP; |
| 1799 | 1795 | ||
| 1800 | spin_lock_irqsave(&common->cc_lock, flags); | 1796 | spin_lock_bh(&common->cc_lock); |
| 1801 | if (idx == 0) | 1797 | if (idx == 0) |
| 1802 | ath_update_survey_stats(sc); | 1798 | ath_update_survey_stats(sc); |
| 1803 | 1799 | ||
| @@ -1811,7 +1807,7 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx, | |||
| 1811 | sband = hw->wiphy->bands[IEEE80211_BAND_5GHZ]; | 1807 | sband = hw->wiphy->bands[IEEE80211_BAND_5GHZ]; |
| 1812 | 1808 | ||
| 1813 | if (!sband || idx >= sband->n_channels) { | 1809 | if (!sband || idx >= sband->n_channels) { |
| 1814 | spin_unlock_irqrestore(&common->cc_lock, flags); | 1810 | spin_unlock_bh(&common->cc_lock); |
| 1815 | return -ENOENT; | 1811 | return -ENOENT; |
| 1816 | } | 1812 | } |
| 1817 | 1813 | ||
| @@ -1819,7 +1815,7 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx, | |||
| 1819 | pos = chan->hw_value; | 1815 | pos = chan->hw_value; |
| 1820 | memcpy(survey, &sc->survey[pos], sizeof(*survey)); | 1816 | memcpy(survey, &sc->survey[pos], sizeof(*survey)); |
| 1821 | survey->channel = chan; | 1817 | survey->channel = chan; |
| 1822 | spin_unlock_irqrestore(&common->cc_lock, flags); | 1818 | spin_unlock_bh(&common->cc_lock); |
| 1823 | 1819 | ||
| 1824 | return 0; | 1820 | return 0; |
| 1825 | } | 1821 | } |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index e9a585758941..55724b02316b 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
| @@ -412,6 +412,16 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | |||
| 412 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 412 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 413 | 0x0036, | 413 | 0x0036, |
| 414 | 0x11AD, /* LITEON */ | 414 | 0x11AD, /* LITEON */ |
| 415 | 0x06B2), | ||
| 416 | .driver_data = ATH9K_PCI_AR9565_1ANT }, | ||
| 417 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 418 | 0x0036, | ||
| 419 | 0x11AD, /* LITEON */ | ||
| 420 | 0x0842), | ||
| 421 | .driver_data = ATH9K_PCI_AR9565_1ANT }, | ||
| 422 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 423 | 0x0036, | ||
| 424 | 0x11AD, /* LITEON */ | ||
| 415 | 0x6671), | 425 | 0x6671), |
| 416 | .driver_data = ATH9K_PCI_AR9565_1ANT }, | 426 | .driver_data = ATH9K_PCI_AR9565_1ANT }, |
| 417 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 427 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| @@ -424,6 +434,16 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | |||
| 424 | 0x1B9A, /* XAVI */ | 434 | 0x1B9A, /* XAVI */ |
| 425 | 0x2812), | 435 | 0x2812), |
| 426 | .driver_data = ATH9K_PCI_AR9565_1ANT }, | 436 | .driver_data = ATH9K_PCI_AR9565_1ANT }, |
| 437 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 438 | 0x0036, | ||
| 439 | 0x1B9A, /* XAVI */ | ||
| 440 | 0x28A1), | ||
| 441 | .driver_data = ATH9K_PCI_AR9565_1ANT }, | ||
| 442 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 443 | 0x0036, | ||
| 444 | PCI_VENDOR_ID_AZWAVE, | ||
| 445 | 0x218A), | ||
| 446 | .driver_data = ATH9K_PCI_AR9565_1ANT }, | ||
| 427 | 447 | ||
| 428 | /* WB335 1-ANT / Antenna Diversity */ | 448 | /* WB335 1-ANT / Antenna Diversity */ |
| 429 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 449 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| @@ -469,22 +489,17 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | |||
| 469 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 489 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 470 | 0x0036, | 490 | 0x0036, |
| 471 | 0x11AD, /* LITEON */ | 491 | 0x11AD, /* LITEON */ |
| 472 | 0x0682), | 492 | 0x06A2), |
| 473 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | 493 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, |
| 474 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 494 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 475 | 0x0036, | 495 | 0x0036, |
| 476 | PCI_VENDOR_ID_AZWAVE, | 496 | 0x11AD, /* LITEON */ |
| 477 | 0x213A), | 497 | 0x0682), |
| 478 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 479 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 480 | 0x0036, | ||
| 481 | PCI_VENDOR_ID_LENOVO, | ||
| 482 | 0x3026), | ||
| 483 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | 498 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, |
| 484 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 499 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 485 | 0x0036, | 500 | 0x0036, |
| 486 | PCI_VENDOR_ID_LENOVO, | 501 | PCI_VENDOR_ID_AZWAVE, |
| 487 | 0x4026), | 502 | 0x213A), |
| 488 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | 503 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, |
| 489 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 504 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 490 | 0x0036, | 505 | 0x0036, |
| @@ -504,37 +519,35 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | |||
| 504 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 519 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 505 | 0x0036, | 520 | 0x0036, |
| 506 | PCI_VENDOR_ID_DELL, | 521 | PCI_VENDOR_ID_DELL, |
| 507 | 0x020E), | 522 | 0x020C), |
| 508 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | 523 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, |
| 509 | 524 | ||
| 510 | /* WB335 2-ANT */ | 525 | /* WB335 2-ANT / Antenna-Diversity */ |
| 511 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 526 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 512 | 0x0036, | 527 | 0x0036, |
| 513 | PCI_VENDOR_ID_SAMSUNG, | 528 | PCI_VENDOR_ID_SAMSUNG, |
| 514 | 0x411A), | 529 | 0x411A), |
| 515 | .driver_data = ATH9K_PCI_AR9565_2ANT }, | 530 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
| 516 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 531 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 517 | 0x0036, | 532 | 0x0036, |
| 518 | PCI_VENDOR_ID_SAMSUNG, | 533 | PCI_VENDOR_ID_SAMSUNG, |
| 519 | 0x411B), | 534 | 0x411B), |
| 520 | .driver_data = ATH9K_PCI_AR9565_2ANT }, | 535 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
| 521 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 536 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 522 | 0x0036, | 537 | 0x0036, |
| 523 | PCI_VENDOR_ID_SAMSUNG, | 538 | PCI_VENDOR_ID_SAMSUNG, |
| 524 | 0x411C), | 539 | 0x411C), |
| 525 | .driver_data = ATH9K_PCI_AR9565_2ANT }, | 540 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
| 526 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 541 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 527 | 0x0036, | 542 | 0x0036, |
| 528 | PCI_VENDOR_ID_SAMSUNG, | 543 | PCI_VENDOR_ID_SAMSUNG, |
| 529 | 0x411D), | 544 | 0x411D), |
| 530 | .driver_data = ATH9K_PCI_AR9565_2ANT }, | 545 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
| 531 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 546 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 532 | 0x0036, | 547 | 0x0036, |
| 533 | PCI_VENDOR_ID_SAMSUNG, | 548 | PCI_VENDOR_ID_SAMSUNG, |
| 534 | 0x411E), | 549 | 0x411E), |
| 535 | .driver_data = ATH9K_PCI_AR9565_2ANT }, | 550 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
| 536 | |||
| 537 | /* WB335 2-ANT / Antenna-Diversity */ | ||
| 538 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 551 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 539 | 0x0036, | 552 | 0x0036, |
| 540 | PCI_VENDOR_ID_ATHEROS, | 553 | PCI_VENDOR_ID_ATHEROS, |
| @@ -562,11 +575,31 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | |||
| 562 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | 575 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
| 563 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 576 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 564 | 0x0036, | 577 | 0x0036, |
| 578 | 0x11AD, /* LITEON */ | ||
| 579 | 0x0832), | ||
| 580 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 581 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 582 | 0x0036, | ||
| 583 | 0x11AD, /* LITEON */ | ||
| 584 | 0x0692), | ||
| 585 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 586 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 587 | 0x0036, | ||
| 565 | PCI_VENDOR_ID_AZWAVE, | 588 | PCI_VENDOR_ID_AZWAVE, |
| 566 | 0x2130), | 589 | 0x2130), |
| 567 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | 590 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
| 568 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 591 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 569 | 0x0036, | 592 | 0x0036, |
| 593 | PCI_VENDOR_ID_AZWAVE, | ||
| 594 | 0x213B), | ||
| 595 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 596 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 597 | 0x0036, | ||
| 598 | PCI_VENDOR_ID_AZWAVE, | ||
| 599 | 0x2182), | ||
| 600 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 601 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 602 | 0x0036, | ||
| 570 | 0x144F, /* ASKEY */ | 603 | 0x144F, /* ASKEY */ |
| 571 | 0x7202), | 604 | 0x7202), |
| 572 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | 605 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
| @@ -577,6 +610,11 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | |||
| 577 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | 610 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
| 578 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 611 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 579 | 0x0036, | 612 | 0x0036, |
| 613 | 0x1B9A, /* XAVI */ | ||
| 614 | 0x28A2), | ||
| 615 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 616 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 617 | 0x0036, | ||
| 580 | 0x185F, /* WNC */ | 618 | 0x185F, /* WNC */ |
| 581 | 0x3027), | 619 | 0x3027), |
| 582 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | 620 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
| @@ -590,6 +628,31 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | |||
| 590 | PCI_VENDOR_ID_FOXCONN, | 628 | PCI_VENDOR_ID_FOXCONN, |
| 591 | 0xE07F), | 629 | 0xE07F), |
| 592 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | 630 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
| 631 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 632 | 0x0036, | ||
| 633 | PCI_VENDOR_ID_FOXCONN, | ||
| 634 | 0xE081), | ||
| 635 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 636 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 637 | 0x0036, | ||
| 638 | PCI_VENDOR_ID_LENOVO, | ||
| 639 | 0x3026), | ||
| 640 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 641 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 642 | 0x0036, | ||
| 643 | PCI_VENDOR_ID_LENOVO, | ||
| 644 | 0x4026), | ||
| 645 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 646 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 647 | 0x0036, | ||
| 648 | PCI_VENDOR_ID_ASUSTEK, | ||
| 649 | 0x85F2), | ||
| 650 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 651 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 652 | 0x0036, | ||
| 653 | PCI_VENDOR_ID_DELL, | ||
| 654 | 0x020E), | ||
| 655 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 593 | 656 | ||
| 594 | /* PCI-E AR9565 (WB335) */ | 657 | /* PCI-E AR9565 (WB335) */ |
| 595 | { PCI_VDEVICE(ATHEROS, 0x0036), | 658 | { PCI_VDEVICE(ATHEROS, 0x0036), |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 3692b2a501a2..f7cc5b37a18f 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
| @@ -419,7 +419,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
| 419 | rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL; | 419 | rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL; |
| 420 | } | 420 | } |
| 421 | 421 | ||
| 422 | if (AR_SREV_9550(sc->sc_ah)) | 422 | if (AR_SREV_9550(sc->sc_ah) || AR_SREV_9531(sc->sc_ah)) |
| 423 | rfilt |= ATH9K_RX_FILTER_4ADDRESS; | 423 | rfilt |= ATH9K_RX_FILTER_4ADDRESS; |
| 424 | 424 | ||
| 425 | return rfilt; | 425 | return rfilt; |
| @@ -850,20 +850,15 @@ static int ath9k_process_rate(struct ath_common *common, | |||
| 850 | enum ieee80211_band band; | 850 | enum ieee80211_band band; |
| 851 | unsigned int i = 0; | 851 | unsigned int i = 0; |
| 852 | struct ath_softc __maybe_unused *sc = common->priv; | 852 | struct ath_softc __maybe_unused *sc = common->priv; |
| 853 | struct ath_hw *ah = sc->sc_ah; | ||
| 853 | 854 | ||
| 854 | band = hw->conf.chandef.chan->band; | 855 | band = ah->curchan->chan->band; |
| 855 | sband = hw->wiphy->bands[band]; | 856 | sband = hw->wiphy->bands[band]; |
| 856 | 857 | ||
| 857 | switch (hw->conf.chandef.width) { | 858 | if (IS_CHAN_QUARTER_RATE(ah->curchan)) |
| 858 | case NL80211_CHAN_WIDTH_5: | ||
| 859 | rxs->flag |= RX_FLAG_5MHZ; | 859 | rxs->flag |= RX_FLAG_5MHZ; |
| 860 | break; | 860 | else if (IS_CHAN_HALF_RATE(ah->curchan)) |
| 861 | case NL80211_CHAN_WIDTH_10: | ||
| 862 | rxs->flag |= RX_FLAG_10MHZ; | 861 | rxs->flag |= RX_FLAG_10MHZ; |
| 863 | break; | ||
| 864 | default: | ||
| 865 | break; | ||
| 866 | } | ||
| 867 | 862 | ||
| 868 | if (rx_stats->rs_rate & 0x80) { | 863 | if (rx_stats->rs_rate & 0x80) { |
| 869 | /* HT rate */ | 864 | /* HT rate */ |
| @@ -982,7 +977,7 @@ static bool ath9k_is_mybeacon(struct ath_softc *sc, struct ieee80211_hdr *hdr) | |||
| 982 | if (ieee80211_is_beacon(hdr->frame_control)) { | 977 | if (ieee80211_is_beacon(hdr->frame_control)) { |
| 983 | RX_STAT_INC(rx_beacons); | 978 | RX_STAT_INC(rx_beacons); |
| 984 | if (!is_zero_ether_addr(common->curbssid) && | 979 | if (!is_zero_ether_addr(common->curbssid) && |
| 985 | ether_addr_equal(hdr->addr3, common->curbssid)) | 980 | ether_addr_equal_64bits(hdr->addr3, common->curbssid)) |
| 986 | return true; | 981 | return true; |
| 987 | } | 982 | } |
| 988 | 983 | ||
| @@ -1077,9 +1072,13 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc, | |||
| 1077 | } | 1072 | } |
| 1078 | 1073 | ||
| 1079 | rx_stats->is_mybeacon = ath9k_is_mybeacon(sc, hdr); | 1074 | rx_stats->is_mybeacon = ath9k_is_mybeacon(sc, hdr); |
| 1080 | if (rx_stats->is_mybeacon) { | 1075 | |
| 1081 | sc->hw_busy_count = 0; | 1076 | /* |
| 1082 | ath_start_rx_poll(sc, 3); | 1077 | * This shouldn't happen, but have a safety check anyway. |
| 1078 | */ | ||
| 1079 | if (WARN_ON(!ah->curchan)) { | ||
| 1080 | ret = -EINVAL; | ||
| 1081 | goto exit; | ||
| 1083 | } | 1082 | } |
| 1084 | 1083 | ||
| 1085 | if (ath9k_process_rate(common, hw, rx_stats, rx_status)) { | 1084 | if (ath9k_process_rate(common, hw, rx_stats, rx_status)) { |
| @@ -1089,8 +1088,8 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc, | |||
| 1089 | 1088 | ||
| 1090 | ath9k_process_rssi(common, hw, rx_stats, rx_status); | 1089 | ath9k_process_rssi(common, hw, rx_stats, rx_status); |
| 1091 | 1090 | ||
| 1092 | rx_status->band = hw->conf.chandef.chan->band; | 1091 | rx_status->band = ah->curchan->chan->band; |
| 1093 | rx_status->freq = hw->conf.chandef.chan->center_freq; | 1092 | rx_status->freq = ah->curchan->chan->center_freq; |
| 1094 | rx_status->antenna = rx_stats->rs_antenna; | 1093 | rx_status->antenna = rx_stats->rs_antenna; |
| 1095 | rx_status->flag |= RX_FLAG_MACTIME_END; | 1094 | rx_status->flag |= RX_FLAG_MACTIME_END; |
| 1096 | 1095 | ||
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 9ad007312c9d..b1fd3fa84983 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
| @@ -304,6 +304,7 @@ | |||
| 304 | #define AR_IMR_S2 0x00ac | 304 | #define AR_IMR_S2 0x00ac |
| 305 | #define AR_IMR_S2_QCU_TXURN 0x000003FF | 305 | #define AR_IMR_S2_QCU_TXURN 0x000003FF |
| 306 | #define AR_IMR_S2_QCU_TXURN_S 0 | 306 | #define AR_IMR_S2_QCU_TXURN_S 0 |
| 307 | #define AR_IMR_S2_BB_WATCHDOG 0x00010000 | ||
| 307 | #define AR_IMR_S2_CST 0x00400000 | 308 | #define AR_IMR_S2_CST 0x00400000 |
| 308 | #define AR_IMR_S2_GTT 0x00800000 | 309 | #define AR_IMR_S2_GTT 0x00800000 |
| 309 | #define AR_IMR_S2_TIM 0x01000000 | 310 | #define AR_IMR_S2_TIM 0x01000000 |
| @@ -812,6 +813,9 @@ | |||
| 812 | #define AR_SREV_REVISION_9565_101 1 | 813 | #define AR_SREV_REVISION_9565_101 1 |
| 813 | #define AR_SREV_REVISION_9565_11 2 | 814 | #define AR_SREV_REVISION_9565_11 2 |
| 814 | #define AR_SREV_VERSION_9550 0x400 | 815 | #define AR_SREV_VERSION_9550 0x400 |
| 816 | #define AR_SREV_VERSION_9531 0x500 | ||
| 817 | #define AR_SREV_REVISION_9531_10 0 | ||
| 818 | #define AR_SREV_REVISION_9531_11 1 | ||
| 815 | 819 | ||
| 816 | #define AR_SREV_5416(_ah) \ | 820 | #define AR_SREV_5416(_ah) \ |
| 817 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ | 821 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ |
| @@ -945,11 +949,19 @@ | |||
| 945 | #define AR_SREV_9580(_ah) \ | 949 | #define AR_SREV_9580(_ah) \ |
| 946 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \ | 950 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \ |
| 947 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9580_10)) | 951 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9580_10)) |
| 948 | |||
| 949 | #define AR_SREV_9580_10(_ah) \ | 952 | #define AR_SREV_9580_10(_ah) \ |
| 950 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \ | 953 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \ |
| 951 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9580_10)) | 954 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9580_10)) |
| 952 | 955 | ||
| 956 | #define AR_SREV_9531(_ah) \ | ||
| 957 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9531)) | ||
| 958 | #define AR_SREV_9531_10(_ah) \ | ||
| 959 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9531) && \ | ||
| 960 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9531_10)) | ||
| 961 | #define AR_SREV_9531_11(_ah) \ | ||
| 962 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9531) && \ | ||
| 963 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9531_11)) | ||
| 964 | |||
| 953 | /* NOTE: When adding chips newer than Peacock, add chip check here */ | 965 | /* NOTE: When adding chips newer than Peacock, add chip check here */ |
| 954 | #define AR_SREV_9580_10_OR_LATER(_ah) \ | 966 | #define AR_SREV_9580_10_OR_LATER(_ah) \ |
| 955 | (AR_SREV_9580(_ah)) | 967 | (AR_SREV_9580(_ah)) |
diff --git a/drivers/net/wireless/ath/ath9k/spectral.c b/drivers/net/wireless/ath/ath9k/spectral.c index 11adb5eb51cc..99f4de95c264 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.c +++ b/drivers/net/wireless/ath/ath9k/spectral.c | |||
| @@ -497,7 +497,7 @@ static int remove_buf_file_handler(struct dentry *dentry) | |||
| 497 | return 0; | 497 | return 0; |
| 498 | } | 498 | } |
| 499 | 499 | ||
| 500 | struct rchan_callbacks rfs_spec_scan_cb = { | 500 | static struct rchan_callbacks rfs_spec_scan_cb = { |
| 501 | .create_buf_file = create_buf_file_handler, | 501 | .create_buf_file = create_buf_file_handler, |
| 502 | .remove_buf_file = remove_buf_file_handler, | 502 | .remove_buf_file = remove_buf_file_handler, |
| 503 | }; | 503 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/wow.c b/drivers/net/wireless/ath/ath9k/wow.c index f1cde81bb7a2..1b3230fa3651 100644 --- a/drivers/net/wireless/ath/ath9k/wow.c +++ b/drivers/net/wireless/ath/ath9k/wow.c | |||
| @@ -197,7 +197,6 @@ int ath9k_suspend(struct ieee80211_hw *hw, | |||
| 197 | 197 | ||
| 198 | ath_cancel_work(sc); | 198 | ath_cancel_work(sc); |
| 199 | ath_stop_ani(sc); | 199 | ath_stop_ani(sc); |
| 200 | del_timer_sync(&sc->rx_poll_timer); | ||
| 201 | 200 | ||
| 202 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { | 201 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { |
| 203 | ath_dbg(common, ANY, "Device not present\n"); | 202 | ath_dbg(common, ANY, "Device not present\n"); |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 9d735c55a0f3..e8d0e7fc77da 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
| @@ -774,11 +774,6 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, | |||
| 774 | if (bt_aggr_limit) | 774 | if (bt_aggr_limit) |
| 775 | aggr_limit = bt_aggr_limit; | 775 | aggr_limit = bt_aggr_limit; |
| 776 | 776 | ||
| 777 | /* | ||
| 778 | * h/w can accept aggregates up to 16 bit lengths (65535). | ||
| 779 | * The IE, however can hold up to 65536, which shows up here | ||
| 780 | * as zero. Ignore 65536 since we are constrained by hw. | ||
| 781 | */ | ||
| 782 | if (tid->an->maxampdu) | 777 | if (tid->an->maxampdu) |
| 783 | aggr_limit = min(aggr_limit, tid->an->maxampdu); | 778 | aggr_limit = min(aggr_limit, tid->an->maxampdu); |
| 784 | 779 | ||
| @@ -1403,8 +1398,8 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
| 1403 | * has already been added. | 1398 | * has already been added. |
| 1404 | */ | 1399 | */ |
| 1405 | if (sta->ht_cap.ht_supported) { | 1400 | if (sta->ht_cap.ht_supported) { |
| 1406 | an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + | 1401 | an->maxampdu = (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + |
| 1407 | sta->ht_cap.ampdu_factor); | 1402 | sta->ht_cap.ampdu_factor)) - 1; |
| 1408 | density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density); | 1403 | density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density); |
| 1409 | an->mpdudensity = density; | 1404 | an->mpdudensity = density; |
| 1410 | } | 1405 | } |
diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c index 3d70cd277fd7..1c0af9cd9a85 100644 --- a/drivers/net/wireless/ath/carl9170/debug.c +++ b/drivers/net/wireless/ath/carl9170/debug.c | |||
| @@ -37,7 +37,6 @@ | |||
| 37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 38 | */ | 38 | */ |
| 39 | 39 | ||
| 40 | #include <linux/init.h> | ||
| 41 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
| 42 | #include <linux/module.h> | 41 | #include <linux/module.h> |
| 43 | #include <linux/seq_file.h> | 42 | #include <linux/seq_file.h> |
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 349fa22a921a..4c3f576c3144 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c | |||
| @@ -37,7 +37,6 @@ | |||
| 37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 38 | */ | 38 | */ |
| 39 | 39 | ||
| 40 | #include <linux/init.h> | ||
| 41 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
| 42 | #include <linux/module.h> | 41 | #include <linux/module.h> |
| 43 | #include <linux/etherdevice.h> | 42 | #include <linux/etherdevice.h> |
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c index e935f61c7fad..1b1b20751ead 100644 --- a/drivers/net/wireless/ath/carl9170/rx.c +++ b/drivers/net/wireless/ath/carl9170/rx.c | |||
| @@ -37,7 +37,6 @@ | |||
| 37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 38 | */ | 38 | */ |
| 39 | 39 | ||
| 40 | #include <linux/init.h> | ||
| 41 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
| 42 | #include <linux/module.h> | 41 | #include <linux/module.h> |
| 43 | #include <linux/etherdevice.h> | 42 | #include <linux/etherdevice.h> |
| @@ -536,7 +535,7 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len) | |||
| 536 | return; | 535 | return; |
| 537 | 536 | ||
| 538 | /* and only beacons from the associated BSSID, please */ | 537 | /* and only beacons from the associated BSSID, please */ |
| 539 | if (!ether_addr_equal(hdr->addr3, ar->common.curbssid) || | 538 | if (!ether_addr_equal_64bits(hdr->addr3, ar->common.curbssid) || |
| 540 | !ar->common.curaid) | 539 | !ar->common.curaid) |
| 541 | return; | 540 | return; |
| 542 | 541 | ||
| @@ -602,8 +601,8 @@ static void carl9170_ba_check(struct ar9170 *ar, void *data, unsigned int len) | |||
| 602 | 601 | ||
| 603 | if (bar->start_seq_num == entry_bar->start_seq_num && | 602 | if (bar->start_seq_num == entry_bar->start_seq_num && |
| 604 | TID_CHECK(bar->control, entry_bar->control) && | 603 | TID_CHECK(bar->control, entry_bar->control) && |
| 605 | ether_addr_equal(bar->ra, entry_bar->ta) && | 604 | ether_addr_equal_64bits(bar->ra, entry_bar->ta) && |
| 606 | ether_addr_equal(bar->ta, entry_bar->ra)) { | 605 | ether_addr_equal_64bits(bar->ta, entry_bar->ra)) { |
| 607 | struct ieee80211_tx_info *tx_info; | 606 | struct ieee80211_tx_info *tx_info; |
| 608 | 607 | ||
| 609 | tx_info = IEEE80211_SKB_CB(entry_skb); | 608 | tx_info = IEEE80211_SKB_CB(entry_skb); |
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index e3f696ee4d23..4cadfd48ffdf 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c | |||
| @@ -37,7 +37,6 @@ | |||
| 37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 38 | */ | 38 | */ |
| 39 | 39 | ||
| 40 | #include <linux/init.h> | ||
| 41 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
| 42 | #include <linux/module.h> | 41 | #include <linux/module.h> |
| 43 | #include <linux/etherdevice.h> | 42 | #include <linux/etherdevice.h> |
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index 8205d3e4ab66..10919f95a83c 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c | |||
| @@ -156,6 +156,19 @@ void wil6210_enable_irq(struct wil6210_priv *wil) | |||
| 156 | iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) + | 156 | iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) + |
| 157 | offsetof(struct RGF_ICR, ICC)); | 157 | offsetof(struct RGF_ICR, ICC)); |
| 158 | 158 | ||
| 159 | /* interrupt moderation parameters */ | ||
| 160 | if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { | ||
| 161 | /* disable interrupt moderation for monitor | ||
| 162 | * to get better timestamp precision | ||
| 163 | */ | ||
| 164 | iowrite32(0, wil->csr + HOSTADDR(RGF_DMA_ITR_CNT_CRL)); | ||
| 165 | } else { | ||
| 166 | iowrite32(WIL6210_ITR_TRSH, | ||
| 167 | wil->csr + HOSTADDR(RGF_DMA_ITR_CNT_TRSH)); | ||
| 168 | iowrite32(BIT_DMA_ITR_CNT_CRL_EN, | ||
| 169 | wil->csr + HOSTADDR(RGF_DMA_ITR_CNT_CRL)); | ||
| 170 | } | ||
| 171 | |||
| 159 | wil6210_unmask_irq_pseudo(wil); | 172 | wil6210_unmask_irq_pseudo(wil); |
| 160 | wil6210_unmask_irq_tx(wil); | 173 | wil6210_unmask_irq_tx(wil); |
| 161 | wil6210_unmask_irq_rx(wil); | 174 | wil6210_unmask_irq_rx(wil); |
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index d505b2676a73..9b88440ef05b 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/ip.h> | 21 | #include <linux/ip.h> |
| 22 | #include <linux/ipv6.h> | 22 | #include <linux/ipv6.h> |
| 23 | #include <net/ipv6.h> | 23 | #include <net/ipv6.h> |
| 24 | #include <asm/processor.h> | ||
| 24 | 25 | ||
| 25 | #include "wil6210.h" | 26 | #include "wil6210.h" |
| 26 | #include "wmi.h" | 27 | #include "wmi.h" |
| @@ -377,6 +378,8 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, | |||
| 377 | } | 378 | } |
| 378 | skb_trim(skb, dmalen); | 379 | skb_trim(skb, dmalen); |
| 379 | 380 | ||
| 381 | prefetch(skb->data); | ||
| 382 | |||
| 380 | wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1, | 383 | wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1, |
| 381 | skb->data, skb_headlen(skb), false); | 384 | skb->data, skb_headlen(skb), false); |
| 382 | 385 | ||
| @@ -673,9 +676,12 @@ static int wil_tx_desc_offload_cksum_set(struct wil6210_priv *wil, | |||
| 673 | if (skb->ip_summed != CHECKSUM_PARTIAL) | 676 | if (skb->ip_summed != CHECKSUM_PARTIAL) |
| 674 | return 0; | 677 | return 0; |
| 675 | 678 | ||
| 679 | d->dma.b11 = ETH_HLEN; /* MAC header length */ | ||
| 680 | |||
| 676 | switch (skb->protocol) { | 681 | switch (skb->protocol) { |
| 677 | case cpu_to_be16(ETH_P_IP): | 682 | case cpu_to_be16(ETH_P_IP): |
| 678 | protocol = ip_hdr(skb)->protocol; | 683 | protocol = ip_hdr(skb)->protocol; |
| 684 | d->dma.b11 |= BIT(DMA_CFG_DESC_TX_OFFLOAD_CFG_L3T_IPV4_POS); | ||
| 679 | break; | 685 | break; |
| 680 | case cpu_to_be16(ETH_P_IPV6): | 686 | case cpu_to_be16(ETH_P_IPV6): |
| 681 | protocol = ipv6_hdr(skb)->nexthdr; | 687 | protocol = ipv6_hdr(skb)->nexthdr; |
| @@ -701,8 +707,6 @@ static int wil_tx_desc_offload_cksum_set(struct wil6210_priv *wil, | |||
| 701 | } | 707 | } |
| 702 | 708 | ||
| 703 | d->dma.ip_length = skb_network_header_len(skb); | 709 | d->dma.ip_length = skb_network_header_len(skb); |
| 704 | d->dma.b11 = ETH_HLEN; /* MAC header length */ | ||
| 705 | d->dma.b11 |= BIT(DMA_CFG_DESC_TX_OFFLOAD_CFG_L3T_IPV4_POS); | ||
| 706 | /* Enable TCP/UDP checksum */ | 710 | /* Enable TCP/UDP checksum */ |
| 707 | d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_POS); | 711 | d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_POS); |
| 708 | /* Calculate pseudo-header */ | 712 | /* Calculate pseudo-header */ |
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index c4a51638736a..1f91eaf95bbe 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
| @@ -39,6 +39,7 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) | |||
| 39 | #define WIL6210_MAX_TX_RINGS (24) /* HW limit */ | 39 | #define WIL6210_MAX_TX_RINGS (24) /* HW limit */ |
| 40 | #define WIL6210_MAX_CID (8) /* HW limit */ | 40 | #define WIL6210_MAX_CID (8) /* HW limit */ |
| 41 | #define WIL6210_NAPI_BUDGET (16) /* arbitrary */ | 41 | #define WIL6210_NAPI_BUDGET (16) /* arbitrary */ |
| 42 | #define WIL6210_ITR_TRSH (10000) /* arbitrary - about 15 IRQs/msec */ | ||
| 42 | 43 | ||
| 43 | /* Hardware definitions begin */ | 44 | /* Hardware definitions begin */ |
| 44 | 45 | ||
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index b73b7e3e2196..bf93ea859f2d 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c | |||
| @@ -39,7 +39,6 @@ | |||
| 39 | 39 | ||
| 40 | ******************************************************************************/ | 40 | ******************************************************************************/ |
| 41 | 41 | ||
| 42 | #include <linux/init.h> | ||
| 43 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
| 44 | 43 | ||
| 45 | #include <linux/kernel.h> | 44 | #include <linux/kernel.h> |
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 5e2749dd1124..4cfb4d99ced0 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c | |||
| @@ -32,7 +32,6 @@ | |||
| 32 | #ifdef __IN_PCMCIA_PACKAGE__ | 32 | #ifdef __IN_PCMCIA_PACKAGE__ |
| 33 | #include <pcmcia/k_compat.h> | 33 | #include <pcmcia/k_compat.h> |
| 34 | #endif | 34 | #endif |
| 35 | #include <linux/init.h> | ||
| 36 | #include <linux/kernel.h> | 35 | #include <linux/kernel.h> |
| 37 | #include <linux/module.h> | 36 | #include <linux/module.h> |
| 38 | #include <linux/ptrace.h> | 37 | #include <linux/ptrace.h> |
diff --git a/drivers/net/wireless/atmel_pci.c b/drivers/net/wireless/atmel_pci.c index 64d5973ec28b..5cd97e3cbee3 100644 --- a/drivers/net/wireless/atmel_pci.c +++ b/drivers/net/wireless/atmel_pci.c | |||
| @@ -22,7 +22,6 @@ | |||
| 22 | #include <linux/pci.h> | 22 | #include <linux/pci.h> |
| 23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
| 24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
| 25 | #include <linux/init.h> | ||
| 26 | #include <linux/netdevice.h> | 25 | #include <linux/netdevice.h> |
| 27 | #include "atmel.h" | 26 | #include "atmel.h" |
| 28 | 27 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c index 12c27d13df7f..c229210d50ba 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c | |||
| @@ -41,9 +41,6 @@ struct brcmf_proto_bcdc_dcmd { | |||
| 41 | __le32 status; /* status code returned from the device */ | 41 | __le32 status; /* status code returned from the device */ |
| 42 | }; | 42 | }; |
| 43 | 43 | ||
| 44 | /* Max valid buffer size that can be sent to the dongle */ | ||
| 45 | #define BCDC_MAX_MSG_SIZE (ETH_FRAME_LEN+ETH_FCS_LEN) | ||
| 46 | |||
| 47 | /* BCDC flag definitions */ | 44 | /* BCDC flag definitions */ |
| 48 | #define BCDC_DCMD_ERROR 0x01 /* 1=cmd failed */ | 45 | #define BCDC_DCMD_ERROR 0x01 /* 1=cmd failed */ |
| 49 | #define BCDC_DCMD_SET 0x02 /* 0=get, 1=set cmd */ | 46 | #define BCDC_DCMD_SET 0x02 /* 0=get, 1=set cmd */ |
| @@ -133,9 +130,12 @@ brcmf_proto_bcdc_msg(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, | |||
| 133 | if (buf) | 130 | if (buf) |
| 134 | memcpy(bcdc->buf, buf, len); | 131 | memcpy(bcdc->buf, buf, len); |
| 135 | 132 | ||
| 133 | len += sizeof(*msg); | ||
| 134 | if (len > BRCMF_TX_IOCTL_MAX_MSG_SIZE) | ||
| 135 | len = BRCMF_TX_IOCTL_MAX_MSG_SIZE; | ||
| 136 | |||
| 136 | /* Send request */ | 137 | /* Send request */ |
| 137 | return brcmf_bus_txctl(drvr->bus_if, (unsigned char *)&bcdc->msg, | 138 | return brcmf_bus_txctl(drvr->bus_if, (unsigned char *)&bcdc->msg, len); |
| 138 | len + sizeof(struct brcmf_proto_bcdc_dcmd)); | ||
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | static int brcmf_proto_bcdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) | 141 | static int brcmf_proto_bcdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 2b5cde67e728..34c993dd0602 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
| @@ -47,8 +47,6 @@ | |||
| 47 | 47 | ||
| 48 | #define SDIOH_API_ACCESS_RETRY_LIMIT 2 | 48 | #define SDIOH_API_ACCESS_RETRY_LIMIT 2 |
| 49 | 49 | ||
| 50 | #define SDIO_VENDOR_ID_BROADCOM 0x02d0 | ||
| 51 | |||
| 52 | #define DMA_ALIGN_MASK 0x03 | 50 | #define DMA_ALIGN_MASK 0x03 |
| 53 | 51 | ||
| 54 | #define SDIO_FUNC1_BLOCKSIZE 64 | 52 | #define SDIO_FUNC1_BLOCKSIZE 64 |
| @@ -216,94 +214,104 @@ static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func, | |||
| 216 | return err_ret; | 214 | return err_ret; |
| 217 | } | 215 | } |
| 218 | 216 | ||
| 219 | static int brcmf_sdiod_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, | 217 | static int brcmf_sdiod_request_data(struct brcmf_sdio_dev *sdiodev, u8 fn, |
| 220 | uint func, uint regaddr, u8 *byte) | 218 | u32 addr, u8 regsz, void *data, bool write) |
| 221 | { | 219 | { |
| 222 | int err_ret; | 220 | struct sdio_func *func; |
| 221 | int ret; | ||
| 223 | 222 | ||
| 224 | brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr); | 223 | brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", |
| 224 | write, fn, addr, regsz); | ||
| 225 | 225 | ||
| 226 | brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait); | 226 | brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_word_wait); |
| 227 | if (brcmf_sdiod_pm_resume_error(sdiodev)) | 227 | if (brcmf_sdiod_pm_resume_error(sdiodev)) |
| 228 | return -EIO; | 228 | return -EIO; |
| 229 | 229 | ||
| 230 | if (rw && func == 0) { | 230 | /* only allow byte access on F0 */ |
| 231 | /* handle F0 separately */ | 231 | if (WARN_ON(regsz > 1 && !fn)) |
| 232 | err_ret = brcmf_sdiod_f0_writeb(sdiodev->func[func], | 232 | return -EINVAL; |
| 233 | regaddr, *byte); | 233 | func = sdiodev->func[fn]; |
| 234 | } else { | 234 | |
| 235 | if (rw) /* CMD52 Write */ | 235 | switch (regsz) { |
| 236 | sdio_writeb(sdiodev->func[func], *byte, regaddr, | 236 | case sizeof(u8): |
| 237 | &err_ret); | 237 | if (write) { |
| 238 | else if (func == 0) { | 238 | if (fn) |
| 239 | *byte = sdio_f0_readb(sdiodev->func[func], regaddr, | 239 | sdio_writeb(func, *(u8 *)data, addr, &ret); |
| 240 | &err_ret); | 240 | else |
| 241 | ret = brcmf_sdiod_f0_writeb(func, addr, | ||
| 242 | *(u8 *)data); | ||
| 241 | } else { | 243 | } else { |
| 242 | *byte = sdio_readb(sdiodev->func[func], regaddr, | 244 | if (fn) |
| 243 | &err_ret); | 245 | *(u8 *)data = sdio_readb(func, addr, &ret); |
| 246 | else | ||
| 247 | *(u8 *)data = sdio_f0_readb(func, addr, &ret); | ||
| 244 | } | 248 | } |
| 249 | break; | ||
| 250 | case sizeof(u16): | ||
| 251 | if (write) | ||
| 252 | sdio_writew(func, *(u16 *)data, addr, &ret); | ||
| 253 | else | ||
| 254 | *(u16 *)data = sdio_readw(func, addr, &ret); | ||
| 255 | break; | ||
| 256 | case sizeof(u32): | ||
| 257 | if (write) | ||
| 258 | sdio_writel(func, *(u32 *)data, addr, &ret); | ||
| 259 | else | ||
| 260 | *(u32 *)data = sdio_readl(func, addr, &ret); | ||
| 261 | break; | ||
| 262 | default: | ||
| 263 | brcmf_err("invalid size: %d\n", regsz); | ||
| 264 | break; | ||
| 245 | } | 265 | } |
| 246 | 266 | ||
| 247 | if (err_ret) { | 267 | if (ret) { |
| 248 | /* | 268 | /* |
| 249 | * SleepCSR register access can fail when | 269 | * SleepCSR register access can fail when |
| 250 | * waking up the device so reduce this noise | 270 | * waking up the device so reduce this noise |
| 251 | * in the logs. | 271 | * in the logs. |
| 252 | */ | 272 | */ |
| 253 | if (regaddr != SBSDIO_FUNC1_SLEEPCSR) | 273 | if (addr != SBSDIO_FUNC1_SLEEPCSR) |
| 254 | brcmf_err("Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n", | 274 | brcmf_err("failed to %s data F%d@0x%05x, err: %d\n", |
| 255 | rw ? "write" : "read", func, regaddr, *byte, | 275 | write ? "write" : "read", fn, addr, ret); |
| 256 | err_ret); | ||
| 257 | else | 276 | else |
| 258 | brcmf_dbg(SDIO, "Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n", | 277 | brcmf_dbg(SDIO, "failed to %s data F%d@0x%05x, err: %d\n", |
| 259 | rw ? "write" : "read", func, regaddr, *byte, | 278 | write ? "write" : "read", fn, addr, ret); |
| 260 | err_ret); | ||
| 261 | } | 279 | } |
| 262 | return err_ret; | 280 | return ret; |
| 263 | } | 281 | } |
| 264 | 282 | ||
| 265 | static int brcmf_sdiod_request_word(struct brcmf_sdio_dev *sdiodev, uint rw, | 283 | static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, |
| 266 | uint func, uint addr, u32 *word, | 284 | u8 regsz, void *data, bool write) |
| 267 | uint nbytes) | ||
| 268 | { | 285 | { |
| 269 | int err_ret = -EIO; | 286 | u8 func_num; |
| 270 | 287 | s32 retry = 0; | |
| 271 | if (func == 0) { | 288 | int ret; |
| 272 | brcmf_err("Only CMD52 allowed to F0\n"); | ||
| 273 | return -EINVAL; | ||
| 274 | } | ||
| 275 | |||
| 276 | brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", | ||
| 277 | rw, func, addr, nbytes); | ||
| 278 | 289 | ||
| 279 | brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_word_wait); | 290 | /* |
| 280 | if (brcmf_sdiod_pm_resume_error(sdiodev)) | 291 | * figure out how to read the register based on address range |
| 281 | return -EIO; | 292 | * 0x00 ~ 0x7FF: function 0 CCCR and FBR |
| 293 | * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers | ||
| 294 | * The rest: function 1 silicon backplane core registers | ||
| 295 | */ | ||
| 296 | if ((addr & ~REG_F0_REG_MASK) == 0) | ||
| 297 | func_num = SDIO_FUNC_0; | ||
| 298 | else | ||
| 299 | func_num = SDIO_FUNC_1; | ||
| 282 | 300 | ||
| 283 | if (rw) { /* CMD52 Write */ | 301 | do { |
| 284 | if (nbytes == 4) | 302 | if (!write) |
| 285 | sdio_writel(sdiodev->func[func], *word, addr, | 303 | memset(data, 0, regsz); |
| 286 | &err_ret); | 304 | /* for retry wait for 1 ms till bus get settled down */ |
| 287 | else if (nbytes == 2) | 305 | if (retry) |
| 288 | sdio_writew(sdiodev->func[func], (*word & 0xFFFF), | 306 | usleep_range(1000, 2000); |
| 289 | addr, &err_ret); | 307 | ret = brcmf_sdiod_request_data(sdiodev, func_num, addr, regsz, |
| 290 | else | 308 | data, write); |
| 291 | brcmf_err("Invalid nbytes: %d\n", nbytes); | 309 | } while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); |
| 292 | } else { /* CMD52 Read */ | ||
| 293 | if (nbytes == 4) | ||
| 294 | *word = sdio_readl(sdiodev->func[func], addr, &err_ret); | ||
| 295 | else if (nbytes == 2) | ||
| 296 | *word = sdio_readw(sdiodev->func[func], addr, | ||
| 297 | &err_ret) & 0xFFFF; | ||
| 298 | else | ||
| 299 | brcmf_err("Invalid nbytes: %d\n", nbytes); | ||
| 300 | } | ||
| 301 | 310 | ||
| 302 | if (err_ret) | 311 | if (ret != 0) |
| 303 | brcmf_err("Failed to %s word, Err: 0x%08x\n", | 312 | brcmf_err("failed with %d\n", ret); |
| 304 | rw ? "write" : "read", err_ret); | ||
| 305 | 313 | ||
| 306 | return err_ret; | 314 | return ret; |
| 307 | } | 315 | } |
| 308 | 316 | ||
| 309 | static int | 317 | static int |
| @@ -311,24 +319,17 @@ brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) | |||
| 311 | { | 319 | { |
| 312 | int err = 0, i; | 320 | int err = 0, i; |
| 313 | u8 addr[3]; | 321 | u8 addr[3]; |
| 314 | s32 retry; | ||
| 315 | 322 | ||
| 316 | addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK; | 323 | addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK; |
| 317 | addr[1] = (address >> 16) & SBSDIO_SBADDRMID_MASK; | 324 | addr[1] = (address >> 16) & SBSDIO_SBADDRMID_MASK; |
| 318 | addr[2] = (address >> 24) & SBSDIO_SBADDRHIGH_MASK; | 325 | addr[2] = (address >> 24) & SBSDIO_SBADDRHIGH_MASK; |
| 319 | 326 | ||
| 320 | for (i = 0; i < 3; i++) { | 327 | for (i = 0; i < 3; i++) { |
| 321 | retry = 0; | 328 | err = brcmf_sdiod_regrw_helper(sdiodev, |
| 322 | do { | 329 | SBSDIO_FUNC1_SBADDRLOW + i, |
| 323 | if (retry) | 330 | sizeof(u8), &addr[i], true); |
| 324 | usleep_range(1000, 2000); | ||
| 325 | err = brcmf_sdiod_request_byte(sdiodev, SDIOH_WRITE, | ||
| 326 | SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW + i, | ||
| 327 | &addr[i]); | ||
| 328 | } while (err != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); | ||
| 329 | |||
| 330 | if (err) { | 331 | if (err) { |
| 331 | brcmf_err("failed at addr:0x%0x\n", | 332 | brcmf_err("failed at addr: 0x%0x\n", |
| 332 | SBSDIO_FUNC1_SBADDRLOW + i); | 333 | SBSDIO_FUNC1_SBADDRLOW + i); |
| 333 | break; | 334 | break; |
| 334 | } | 335 | } |
| @@ -359,61 +360,14 @@ brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, uint width, u32 *addr) | |||
| 359 | return 0; | 360 | return 0; |
| 360 | } | 361 | } |
| 361 | 362 | ||
| 362 | static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | ||
| 363 | void *data, bool write) | ||
| 364 | { | ||
| 365 | u8 func_num, reg_size; | ||
| 366 | s32 retry = 0; | ||
| 367 | int ret; | ||
| 368 | |||
| 369 | /* | ||
| 370 | * figure out how to read the register based on address range | ||
| 371 | * 0x00 ~ 0x7FF: function 0 CCCR and FBR | ||
| 372 | * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers | ||
| 373 | * The rest: function 1 silicon backplane core registers | ||
| 374 | */ | ||
| 375 | if ((addr & ~REG_F0_REG_MASK) == 0) { | ||
| 376 | func_num = SDIO_FUNC_0; | ||
| 377 | reg_size = 1; | ||
| 378 | } else if ((addr & ~REG_F1_MISC_MASK) == 0) { | ||
| 379 | func_num = SDIO_FUNC_1; | ||
| 380 | reg_size = 1; | ||
| 381 | } else { | ||
| 382 | func_num = SDIO_FUNC_1; | ||
| 383 | reg_size = 4; | ||
| 384 | |||
| 385 | ret = brcmf_sdiod_addrprep(sdiodev, reg_size, &addr); | ||
| 386 | if (ret) | ||
| 387 | goto done; | ||
| 388 | } | ||
| 389 | |||
| 390 | do { | ||
| 391 | if (!write) | ||
| 392 | memset(data, 0, reg_size); | ||
| 393 | if (retry) /* wait for 1 ms till bus get settled down */ | ||
| 394 | usleep_range(1000, 2000); | ||
| 395 | if (reg_size == 1) | ||
| 396 | ret = brcmf_sdiod_request_byte(sdiodev, write, | ||
| 397 | func_num, addr, data); | ||
| 398 | else | ||
| 399 | ret = brcmf_sdiod_request_word(sdiodev, write, | ||
| 400 | func_num, addr, data, 4); | ||
| 401 | } while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); | ||
| 402 | |||
| 403 | done: | ||
| 404 | if (ret != 0) | ||
| 405 | brcmf_err("failed with %d\n", ret); | ||
| 406 | |||
| 407 | return ret; | ||
| 408 | } | ||
| 409 | |||
| 410 | u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) | 363 | u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) |
| 411 | { | 364 | { |
| 412 | u8 data; | 365 | u8 data; |
| 413 | int retval; | 366 | int retval; |
| 414 | 367 | ||
| 415 | brcmf_dbg(SDIO, "addr:0x%08x\n", addr); | 368 | brcmf_dbg(SDIO, "addr:0x%08x\n", addr); |
| 416 | retval = brcmf_sdiod_regrw_helper(sdiodev, addr, &data, false); | 369 | retval = brcmf_sdiod_regrw_helper(sdiodev, addr, sizeof(data), &data, |
| 370 | false); | ||
| 417 | brcmf_dbg(SDIO, "data:0x%02x\n", data); | 371 | brcmf_dbg(SDIO, "data:0x%02x\n", data); |
| 418 | 372 | ||
| 419 | if (ret) | 373 | if (ret) |
| @@ -428,9 +382,14 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) | |||
| 428 | int retval; | 382 | int retval; |
| 429 | 383 | ||
| 430 | brcmf_dbg(SDIO, "addr:0x%08x\n", addr); | 384 | brcmf_dbg(SDIO, "addr:0x%08x\n", addr); |
| 431 | retval = brcmf_sdiod_regrw_helper(sdiodev, addr, &data, false); | 385 | retval = brcmf_sdiod_addrprep(sdiodev, sizeof(data), &addr); |
| 386 | if (retval) | ||
| 387 | goto done; | ||
| 388 | retval = brcmf_sdiod_regrw_helper(sdiodev, addr, sizeof(data), &data, | ||
| 389 | false); | ||
| 432 | brcmf_dbg(SDIO, "data:0x%08x\n", data); | 390 | brcmf_dbg(SDIO, "data:0x%08x\n", data); |
| 433 | 391 | ||
| 392 | done: | ||
| 434 | if (ret) | 393 | if (ret) |
| 435 | *ret = retval; | 394 | *ret = retval; |
| 436 | 395 | ||
| @@ -443,8 +402,8 @@ void brcmf_sdiod_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
| 443 | int retval; | 402 | int retval; |
| 444 | 403 | ||
| 445 | brcmf_dbg(SDIO, "addr:0x%08x, data:0x%02x\n", addr, data); | 404 | brcmf_dbg(SDIO, "addr:0x%08x, data:0x%02x\n", addr, data); |
| 446 | retval = brcmf_sdiod_regrw_helper(sdiodev, addr, &data, true); | 405 | retval = brcmf_sdiod_regrw_helper(sdiodev, addr, sizeof(data), &data, |
| 447 | 406 | true); | |
| 448 | if (ret) | 407 | if (ret) |
| 449 | *ret = retval; | 408 | *ret = retval; |
| 450 | } | 409 | } |
| @@ -455,8 +414,13 @@ void brcmf_sdiod_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
| 455 | int retval; | 414 | int retval; |
| 456 | 415 | ||
| 457 | brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data); | 416 | brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data); |
| 458 | retval = brcmf_sdiod_regrw_helper(sdiodev, addr, &data, true); | 417 | retval = brcmf_sdiod_addrprep(sdiodev, sizeof(data), &addr); |
| 418 | if (retval) | ||
| 419 | goto done; | ||
| 420 | retval = brcmf_sdiod_regrw_helper(sdiodev, addr, sizeof(data), &data, | ||
| 421 | true); | ||
| 459 | 422 | ||
| 423 | done: | ||
| 460 | if (ret) | 424 | if (ret) |
| 461 | *ret = retval; | 425 | *ret = retval; |
| 462 | } | 426 | } |
| @@ -879,8 +843,8 @@ int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn) | |||
| 879 | brcmf_dbg(SDIO, "Enter\n"); | 843 | brcmf_dbg(SDIO, "Enter\n"); |
| 880 | 844 | ||
| 881 | /* issue abort cmd52 command through F0 */ | 845 | /* issue abort cmd52 command through F0 */ |
| 882 | brcmf_sdiod_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0, | 846 | brcmf_sdiod_request_data(sdiodev, SDIO_FUNC_0, SDIO_CCCR_ABORT, |
| 883 | SDIO_CCCR_ABORT, &t_func); | 847 | sizeof(t_func), &t_func, true); |
| 884 | 848 | ||
| 885 | brcmf_dbg(SDIO, "Exit\n"); | 849 | brcmf_dbg(SDIO, "Exit\n"); |
| 886 | return 0; | 850 | return 0; |
| @@ -981,6 +945,7 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = { | |||
| 981 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, | 945 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, |
| 982 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)}, | 946 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)}, |
| 983 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)}, | 947 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)}, |
| 948 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43362)}, | ||
| 984 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, | 949 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, |
| 985 | SDIO_DEVICE_ID_BROADCOM_4335_4339)}, | 950 | SDIO_DEVICE_ID_BROADCOM_4335_4339)}, |
| 986 | { /* end: all zeroes */ }, | 951 | { /* end: all zeroes */ }, |
| @@ -1037,7 +1002,6 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, | |||
| 1037 | sdiodev->pdata = brcmfmac_sdio_pdata; | 1002 | sdiodev->pdata = brcmfmac_sdio_pdata; |
| 1038 | 1003 | ||
| 1039 | atomic_set(&sdiodev->suspend, false); | 1004 | atomic_set(&sdiodev->suspend, false); |
| 1040 | init_waitqueue_head(&sdiodev->request_byte_wait); | ||
| 1041 | init_waitqueue_head(&sdiodev->request_word_wait); | 1005 | init_waitqueue_head(&sdiodev->request_word_wait); |
| 1042 | init_waitqueue_head(&sdiodev->request_buffer_wait); | 1006 | init_waitqueue_head(&sdiodev->request_buffer_wait); |
| 1043 | 1007 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index 252024bcbc3b..939d6b132922 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h | |||
| @@ -21,8 +21,6 @@ | |||
| 21 | #ifndef _BRCMF_H_ | 21 | #ifndef _BRCMF_H_ |
| 22 | #define _BRCMF_H_ | 22 | #define _BRCMF_H_ |
| 23 | 23 | ||
| 24 | #define BRCMF_VERSION_STR "4.218.248.5" | ||
| 25 | |||
| 26 | #include "fweh.h" | 24 | #include "fweh.h" |
| 27 | 25 | ||
| 28 | #define TOE_TX_CSUM_OL 0x00000001 | 26 | #define TOE_TX_CSUM_OL 0x00000001 |
| @@ -39,6 +37,11 @@ | |||
| 39 | #define BRCMF_DCMD_MEDLEN 1536 | 37 | #define BRCMF_DCMD_MEDLEN 1536 |
| 40 | #define BRCMF_DCMD_MAXLEN 8192 | 38 | #define BRCMF_DCMD_MAXLEN 8192 |
| 41 | 39 | ||
| 40 | /* IOCTL from host to device are limited in lenght. A device can only handle | ||
| 41 | * ethernet frame size. This limitation is to be applied by protocol layer. | ||
| 42 | */ | ||
| 43 | #define BRCMF_TX_IOCTL_MAX_MSG_SIZE (ETH_FRAME_LEN+ETH_FCS_LEN) | ||
| 44 | |||
| 42 | #define BRCMF_AMPDU_RX_REORDER_MAXFLOWS 256 | 45 | #define BRCMF_AMPDU_RX_REORDER_MAXFLOWS 256 |
| 43 | 46 | ||
| 44 | /* Length of firmware version string stored for | 47 | /* Length of firmware version string stored for |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 548dbb5542c6..6a8983a1fb9c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c | |||
| @@ -32,15 +32,6 @@ | |||
| 32 | #define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40 | 32 | #define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40 |
| 33 | #define BRCMF_DEFAULT_PACKET_FILTER "100 0 0 0 0x01 0x00" | 33 | #define BRCMF_DEFAULT_PACKET_FILTER "100 0 0 0 0x01 0x00" |
| 34 | 34 | ||
| 35 | #ifdef DEBUG | ||
| 36 | static const char brcmf_version[] = | ||
| 37 | "Dongle Host Driver, version " BRCMF_VERSION_STR "\nCompiled on " | ||
| 38 | __DATE__ " at " __TIME__; | ||
| 39 | #else | ||
| 40 | static const char brcmf_version[] = | ||
| 41 | "Dongle Host Driver, version " BRCMF_VERSION_STR; | ||
| 42 | #endif | ||
| 43 | |||
| 44 | 35 | ||
| 45 | bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, | 36 | bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, |
| 46 | struct sk_buff *pkt, int prec) | 37 | struct sk_buff *pkt, int prec) |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index bce0b8e511fd..af39edae8c62 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | |||
| @@ -702,7 +702,7 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked) | |||
| 702 | 702 | ||
| 703 | brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name); | 703 | brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name); |
| 704 | 704 | ||
| 705 | ndev->destructor = free_netdev; | 705 | ndev->destructor = brcmf_cfg80211_free_netdev; |
| 706 | return 0; | 706 | return 0; |
| 707 | 707 | ||
| 708 | fail: | 708 | fail: |
| @@ -859,8 +859,6 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) | |||
| 859 | } | 859 | } |
| 860 | /* unregister will take care of freeing it */ | 860 | /* unregister will take care of freeing it */ |
| 861 | unregister_netdev(ifp->ndev); | 861 | unregister_netdev(ifp->ndev); |
| 862 | if (bssidx == 0) | ||
| 863 | brcmf_cfg80211_detach(drvr->config); | ||
| 864 | } else { | 862 | } else { |
| 865 | kfree(ifp); | 863 | kfree(ifp); |
| 866 | } | 864 | } |
| @@ -963,8 +961,7 @@ int brcmf_bus_start(struct device *dev) | |||
| 963 | fail: | 961 | fail: |
| 964 | if (ret < 0) { | 962 | if (ret < 0) { |
| 965 | brcmf_err("failed: %d\n", ret); | 963 | brcmf_err("failed: %d\n", ret); |
| 966 | if (drvr->config) | 964 | brcmf_cfg80211_detach(drvr->config); |
| 967 | brcmf_cfg80211_detach(drvr->config); | ||
| 968 | if (drvr->fws) { | 965 | if (drvr->fws) { |
| 969 | brcmf_fws_del_interface(ifp); | 966 | brcmf_fws_del_interface(ifp); |
| 970 | brcmf_fws_deinit(drvr); | 967 | brcmf_fws_deinit(drvr); |
| @@ -1039,6 +1036,8 @@ void brcmf_detach(struct device *dev) | |||
| 1039 | brcmf_del_if(drvr, i); | 1036 | brcmf_del_if(drvr, i); |
| 1040 | } | 1037 | } |
| 1041 | 1038 | ||
| 1039 | brcmf_cfg80211_detach(drvr->config); | ||
| 1040 | |||
| 1042 | brcmf_bus_detach(drvr); | 1041 | brcmf_bus_detach(drvr); |
| 1043 | 1042 | ||
| 1044 | brcmf_proto_detach(drvr); | 1043 | brcmf_proto_detach(drvr); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index f214510e3bee..9c7f08a13105 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
| @@ -509,6 +509,8 @@ enum brcmf_sdio_frmtype { | |||
| 509 | #define BCM4334_NVRAM_NAME "brcm/brcmfmac4334-sdio.txt" | 509 | #define BCM4334_NVRAM_NAME "brcm/brcmfmac4334-sdio.txt" |
| 510 | #define BCM4335_FIRMWARE_NAME "brcm/brcmfmac4335-sdio.bin" | 510 | #define BCM4335_FIRMWARE_NAME "brcm/brcmfmac4335-sdio.bin" |
| 511 | #define BCM4335_NVRAM_NAME "brcm/brcmfmac4335-sdio.txt" | 511 | #define BCM4335_NVRAM_NAME "brcm/brcmfmac4335-sdio.txt" |
| 512 | #define BCM43362_FIRMWARE_NAME "brcm/brcmfmac43362-sdio.bin" | ||
| 513 | #define BCM43362_NVRAM_NAME "brcm/brcmfmac43362-sdio.txt" | ||
| 512 | #define BCM4339_FIRMWARE_NAME "brcm/brcmfmac4339-sdio.bin" | 514 | #define BCM4339_FIRMWARE_NAME "brcm/brcmfmac4339-sdio.bin" |
| 513 | #define BCM4339_NVRAM_NAME "brcm/brcmfmac4339-sdio.txt" | 515 | #define BCM4339_NVRAM_NAME "brcm/brcmfmac4339-sdio.txt" |
| 514 | 516 | ||
| @@ -526,6 +528,8 @@ MODULE_FIRMWARE(BCM4334_FIRMWARE_NAME); | |||
| 526 | MODULE_FIRMWARE(BCM4334_NVRAM_NAME); | 528 | MODULE_FIRMWARE(BCM4334_NVRAM_NAME); |
| 527 | MODULE_FIRMWARE(BCM4335_FIRMWARE_NAME); | 529 | MODULE_FIRMWARE(BCM4335_FIRMWARE_NAME); |
| 528 | MODULE_FIRMWARE(BCM4335_NVRAM_NAME); | 530 | MODULE_FIRMWARE(BCM4335_NVRAM_NAME); |
| 531 | MODULE_FIRMWARE(BCM43362_FIRMWARE_NAME); | ||
| 532 | MODULE_FIRMWARE(BCM43362_NVRAM_NAME); | ||
| 529 | MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME); | 533 | MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME); |
| 530 | MODULE_FIRMWARE(BCM4339_NVRAM_NAME); | 534 | MODULE_FIRMWARE(BCM4339_NVRAM_NAME); |
| 531 | 535 | ||
| @@ -552,6 +556,7 @@ static const struct brcmf_firmware_names brcmf_fwname_data[] = { | |||
| 552 | { BCM4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) }, | 556 | { BCM4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) }, |
| 553 | { BCM4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) }, | 557 | { BCM4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) }, |
| 554 | { BCM4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) }, | 558 | { BCM4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) }, |
| 559 | { BCM43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) }, | ||
| 555 | { BCM4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) } | 560 | { BCM4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) } |
| 556 | }; | 561 | }; |
| 557 | 562 | ||
| @@ -3384,7 +3389,8 @@ err: | |||
| 3384 | 3389 | ||
| 3385 | static bool brcmf_sdio_sr_capable(struct brcmf_sdio *bus) | 3390 | static bool brcmf_sdio_sr_capable(struct brcmf_sdio *bus) |
| 3386 | { | 3391 | { |
| 3387 | u32 addr, reg; | 3392 | u32 addr, reg, pmu_cc3_mask = ~0; |
| 3393 | int err; | ||
| 3388 | 3394 | ||
| 3389 | brcmf_dbg(TRACE, "Enter\n"); | 3395 | brcmf_dbg(TRACE, "Enter\n"); |
| 3390 | 3396 | ||
| @@ -3392,13 +3398,27 @@ static bool brcmf_sdio_sr_capable(struct brcmf_sdio *bus) | |||
| 3392 | if (bus->ci->pmurev < 17) | 3398 | if (bus->ci->pmurev < 17) |
| 3393 | return false; | 3399 | return false; |
| 3394 | 3400 | ||
| 3395 | /* read PMU chipcontrol register 3*/ | 3401 | switch (bus->ci->chip) { |
| 3396 | addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_addr); | 3402 | case BCM43241_CHIP_ID: |
| 3397 | brcmf_sdiod_regwl(bus->sdiodev, addr, 3, NULL); | 3403 | case BCM4335_CHIP_ID: |
| 3398 | addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_data); | 3404 | case BCM4339_CHIP_ID: |
| 3399 | reg = brcmf_sdiod_regrl(bus->sdiodev, addr, NULL); | 3405 | /* read PMU chipcontrol register 3 */ |
| 3406 | addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_addr); | ||
| 3407 | brcmf_sdiod_regwl(bus->sdiodev, addr, 3, NULL); | ||
| 3408 | addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_data); | ||
| 3409 | reg = brcmf_sdiod_regrl(bus->sdiodev, addr, NULL); | ||
| 3410 | return (reg & pmu_cc3_mask) != 0; | ||
| 3411 | default: | ||
| 3412 | addr = CORE_CC_REG(bus->ci->c_inf[0].base, pmucapabilities_ext); | ||
| 3413 | reg = brcmf_sdiod_regrl(bus->sdiodev, addr, &err); | ||
| 3414 | if ((reg & PCAPEXT_SR_SUPPORTED_MASK) == 0) | ||
| 3415 | return false; | ||
| 3400 | 3416 | ||
| 3401 | return (bool)reg; | 3417 | addr = CORE_CC_REG(bus->ci->c_inf[0].base, retention_ctl); |
| 3418 | reg = brcmf_sdiod_regrl(bus->sdiodev, addr, NULL); | ||
| 3419 | return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK | | ||
| 3420 | PMU_RCTL_LOGIC_DISABLE_MASK)) == 0; | ||
| 3421 | } | ||
| 3402 | } | 3422 | } |
| 3403 | 3423 | ||
| 3404 | static void brcmf_sdio_sr_init(struct brcmf_sdio *bus) | 3424 | static void brcmf_sdio_sr_init(struct brcmf_sdio *bus) |
| @@ -3615,7 +3635,7 @@ static int brcmf_sdio_bus_init(struct device *dev) | |||
| 3615 | } | 3635 | } |
| 3616 | 3636 | ||
| 3617 | /* If we didn't come up, turn off backplane clock */ | 3637 | /* If we didn't come up, turn off backplane clock */ |
| 3618 | if (bus_if->state != BRCMF_BUS_DATA) | 3638 | if (ret != 0) |
| 3619 | brcmf_sdio_clkctl(bus, CLK_NONE, false); | 3639 | brcmf_sdio_clkctl(bus, CLK_NONE, false); |
| 3620 | 3640 | ||
| 3621 | exit: | 3641 | exit: |
| @@ -3750,31 +3770,6 @@ static void brcmf_sdio_dataworker(struct work_struct *work) | |||
| 3750 | } | 3770 | } |
| 3751 | } | 3771 | } |
| 3752 | 3772 | ||
| 3753 | static void brcmf_sdio_release_malloc(struct brcmf_sdio *bus) | ||
| 3754 | { | ||
| 3755 | brcmf_dbg(TRACE, "Enter\n"); | ||
| 3756 | |||
| 3757 | kfree(bus->rxbuf); | ||
| 3758 | bus->rxctl = bus->rxbuf = NULL; | ||
| 3759 | bus->rxlen = 0; | ||
| 3760 | } | ||
| 3761 | |||
| 3762 | static bool brcmf_sdio_probe_malloc(struct brcmf_sdio *bus) | ||
| 3763 | { | ||
| 3764 | brcmf_dbg(TRACE, "Enter\n"); | ||
| 3765 | |||
| 3766 | if (bus->sdiodev->bus_if->maxctl) { | ||
| 3767 | bus->rxblen = | ||
| 3768 | roundup((bus->sdiodev->bus_if->maxctl + SDPCM_HDRLEN), | ||
| 3769 | ALIGNMENT) + bus->head_align; | ||
| 3770 | bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC); | ||
| 3771 | if (!(bus->rxbuf)) | ||
| 3772 | return false; | ||
| 3773 | } | ||
| 3774 | |||
| 3775 | return true; | ||
| 3776 | } | ||
| 3777 | |||
| 3778 | static bool | 3773 | static bool |
| 3779 | brcmf_sdio_probe_attach(struct brcmf_sdio *bus) | 3774 | brcmf_sdio_probe_attach(struct brcmf_sdio *bus) |
| 3780 | { | 3775 | { |
| @@ -3888,39 +3883,6 @@ fail: | |||
| 3888 | return false; | 3883 | return false; |
| 3889 | } | 3884 | } |
| 3890 | 3885 | ||
| 3891 | static bool brcmf_sdio_probe_init(struct brcmf_sdio *bus) | ||
| 3892 | { | ||
| 3893 | brcmf_dbg(TRACE, "Enter\n"); | ||
| 3894 | |||
| 3895 | sdio_claim_host(bus->sdiodev->func[1]); | ||
| 3896 | |||
| 3897 | /* Disable F2 to clear any intermediate frame state on the dongle */ | ||
| 3898 | sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]); | ||
| 3899 | |||
| 3900 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | ||
| 3901 | bus->rxflow = false; | ||
| 3902 | |||
| 3903 | /* Done with backplane-dependent accesses, can drop clock... */ | ||
| 3904 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); | ||
| 3905 | |||
| 3906 | sdio_release_host(bus->sdiodev->func[1]); | ||
| 3907 | |||
| 3908 | /* ...and initialize clock/power states */ | ||
| 3909 | bus->clkstate = CLK_SDONLY; | ||
| 3910 | bus->idletime = BRCMF_IDLE_INTERVAL; | ||
| 3911 | bus->idleclock = BRCMF_IDLE_ACTIVE; | ||
| 3912 | |||
| 3913 | /* Query the F2 block size, set roundup accordingly */ | ||
| 3914 | bus->blocksize = bus->sdiodev->func[2]->cur_blksize; | ||
| 3915 | bus->roundup = min(max_roundup, bus->blocksize); | ||
| 3916 | |||
| 3917 | /* SR state */ | ||
| 3918 | bus->sleeping = false; | ||
| 3919 | bus->sr_enabled = false; | ||
| 3920 | |||
| 3921 | return true; | ||
| 3922 | } | ||
| 3923 | |||
| 3924 | static int | 3886 | static int |
| 3925 | brcmf_sdio_watchdog_thread(void *data) | 3887 | brcmf_sdio_watchdog_thread(void *data) |
| 3926 | { | 3888 | { |
| @@ -3955,24 +3917,6 @@ brcmf_sdio_watchdog(unsigned long data) | |||
| 3955 | } | 3917 | } |
| 3956 | } | 3918 | } |
| 3957 | 3919 | ||
| 3958 | static void brcmf_sdio_release_dongle(struct brcmf_sdio *bus) | ||
| 3959 | { | ||
| 3960 | brcmf_dbg(TRACE, "Enter\n"); | ||
| 3961 | |||
| 3962 | if (bus->ci) { | ||
| 3963 | sdio_claim_host(bus->sdiodev->func[1]); | ||
| 3964 | brcmf_sdio_clkctl(bus, CLK_AVAIL, false); | ||
| 3965 | brcmf_sdio_clkctl(bus, CLK_NONE, false); | ||
| 3966 | sdio_release_host(bus->sdiodev->func[1]); | ||
| 3967 | brcmf_sdio_chip_detach(&bus->ci); | ||
| 3968 | if (bus->vars && bus->varsz) | ||
| 3969 | kfree(bus->vars); | ||
| 3970 | bus->vars = NULL; | ||
| 3971 | } | ||
| 3972 | |||
| 3973 | brcmf_dbg(TRACE, "Disconnected\n"); | ||
| 3974 | } | ||
| 3975 | |||
| 3976 | static struct brcmf_bus_ops brcmf_sdio_bus_ops = { | 3920 | static struct brcmf_bus_ops brcmf_sdio_bus_ops = { |
| 3977 | .stop = brcmf_sdio_bus_stop, | 3921 | .stop = brcmf_sdio_bus_stop, |
| 3978 | .preinit = brcmf_sdio_bus_preinit, | 3922 | .preinit = brcmf_sdio_bus_preinit, |
| @@ -4066,15 +4010,42 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) | |||
| 4066 | } | 4010 | } |
| 4067 | 4011 | ||
| 4068 | /* Allocate buffers */ | 4012 | /* Allocate buffers */ |
| 4069 | if (!(brcmf_sdio_probe_malloc(bus))) { | 4013 | if (bus->sdiodev->bus_if->maxctl) { |
| 4070 | brcmf_err("brcmf_sdio_probe_malloc failed\n"); | 4014 | bus->rxblen = |
| 4071 | goto fail; | 4015 | roundup((bus->sdiodev->bus_if->maxctl + SDPCM_HDRLEN), |
| 4016 | ALIGNMENT) + bus->head_align; | ||
| 4017 | bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC); | ||
| 4018 | if (!(bus->rxbuf)) { | ||
| 4019 | brcmf_err("rxbuf allocation failed\n"); | ||
| 4020 | goto fail; | ||
| 4021 | } | ||
| 4072 | } | 4022 | } |
| 4073 | 4023 | ||
| 4074 | if (!(brcmf_sdio_probe_init(bus))) { | 4024 | sdio_claim_host(bus->sdiodev->func[1]); |
| 4075 | brcmf_err("brcmf_sdio_probe_init failed\n"); | 4025 | |
| 4076 | goto fail; | 4026 | /* Disable F2 to clear any intermediate frame state on the dongle */ |
| 4077 | } | 4027 | sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]); |
| 4028 | |||
| 4029 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | ||
| 4030 | bus->rxflow = false; | ||
| 4031 | |||
| 4032 | /* Done with backplane-dependent accesses, can drop clock... */ | ||
| 4033 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); | ||
| 4034 | |||
| 4035 | sdio_release_host(bus->sdiodev->func[1]); | ||
| 4036 | |||
| 4037 | /* ...and initialize clock/power states */ | ||
| 4038 | bus->clkstate = CLK_SDONLY; | ||
| 4039 | bus->idletime = BRCMF_IDLE_INTERVAL; | ||
| 4040 | bus->idleclock = BRCMF_IDLE_ACTIVE; | ||
| 4041 | |||
| 4042 | /* Query the F2 block size, set roundup accordingly */ | ||
| 4043 | bus->blocksize = bus->sdiodev->func[2]->cur_blksize; | ||
| 4044 | bus->roundup = min(max_roundup, bus->blocksize); | ||
| 4045 | |||
| 4046 | /* SR state */ | ||
| 4047 | bus->sleeping = false; | ||
| 4048 | bus->sr_enabled = false; | ||
| 4078 | 4049 | ||
| 4079 | brcmf_sdio_debugfs_create(bus); | 4050 | brcmf_sdio_debugfs_create(bus); |
| 4080 | brcmf_dbg(INFO, "completed!!\n"); | 4051 | brcmf_dbg(INFO, "completed!!\n"); |
| @@ -4108,12 +4079,20 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus) | |||
| 4108 | 4079 | ||
| 4109 | if (bus->sdiodev->bus_if->drvr) { | 4080 | if (bus->sdiodev->bus_if->drvr) { |
| 4110 | brcmf_detach(bus->sdiodev->dev); | 4081 | brcmf_detach(bus->sdiodev->dev); |
| 4111 | brcmf_sdio_release_dongle(bus); | 4082 | } |
| 4083 | |||
| 4084 | if (bus->ci) { | ||
| 4085 | sdio_claim_host(bus->sdiodev->func[1]); | ||
| 4086 | brcmf_sdio_clkctl(bus, CLK_AVAIL, false); | ||
| 4087 | brcmf_sdio_clkctl(bus, CLK_NONE, false); | ||
| 4088 | sdio_release_host(bus->sdiodev->func[1]); | ||
| 4089 | brcmf_sdio_chip_detach(&bus->ci); | ||
| 4112 | } | 4090 | } |
| 4113 | 4091 | ||
| 4114 | brcmu_pkt_buf_free_skb(bus->txglom_sgpad); | 4092 | brcmu_pkt_buf_free_skb(bus->txglom_sgpad); |
| 4115 | brcmf_sdio_release_malloc(bus); | 4093 | kfree(bus->rxbuf); |
| 4116 | kfree(bus->hdrbuf); | 4094 | kfree(bus->hdrbuf); |
| 4095 | kfree(bus->vars); | ||
| 4117 | kfree(bus); | 4096 | kfree(bus); |
| 4118 | } | 4097 | } |
| 4119 | 4098 | ||
| @@ -4131,7 +4110,7 @@ void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, uint wdtick) | |||
| 4131 | } | 4110 | } |
| 4132 | 4111 | ||
| 4133 | /* don't start the wd until fw is loaded */ | 4112 | /* don't start the wd until fw is loaded */ |
| 4134 | if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) | 4113 | if (bus->sdiodev->bus_if->state != BRCMF_BUS_DATA) |
| 4135 | return; | 4114 | return; |
| 4136 | 4115 | ||
| 4137 | if (wdtick) { | 4116 | if (wdtick) { |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 7918c1033662..c3e7d76dbf35 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | |||
| @@ -1873,7 +1873,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) | |||
| 1873 | brcmf_dbg(DATA, "tx proto=0x%X\n", ntohs(eh->h_proto)); | 1873 | brcmf_dbg(DATA, "tx proto=0x%X\n", ntohs(eh->h_proto)); |
| 1874 | /* determine the priority */ | 1874 | /* determine the priority */ |
| 1875 | if (!skb->priority) | 1875 | if (!skb->priority) |
| 1876 | skb->priority = cfg80211_classify8021d(skb); | 1876 | skb->priority = cfg80211_classify8021d(skb, NULL); |
| 1877 | 1877 | ||
| 1878 | drvr->tx_multicast += !!multicast; | 1878 | drvr->tx_multicast += !!multicast; |
| 1879 | if (pae) | 1879 | if (pae) |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index 185af8a84c9a..fc4f98b275d7 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c | |||
| @@ -1955,21 +1955,21 @@ s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg) | |||
| 1955 | err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1); | 1955 | err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1); |
| 1956 | if (err < 0) { | 1956 | if (err < 0) { |
| 1957 | brcmf_err("set p2p_disc error\n"); | 1957 | brcmf_err("set p2p_disc error\n"); |
| 1958 | brcmf_free_vif(cfg, p2p_vif); | 1958 | brcmf_free_vif(p2p_vif); |
| 1959 | goto exit; | 1959 | goto exit; |
| 1960 | } | 1960 | } |
| 1961 | /* obtain bsscfg index for P2P discovery */ | 1961 | /* obtain bsscfg index for P2P discovery */ |
| 1962 | err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx); | 1962 | err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx); |
| 1963 | if (err < 0) { | 1963 | if (err < 0) { |
| 1964 | brcmf_err("retrieving discover bsscfg index failed\n"); | 1964 | brcmf_err("retrieving discover bsscfg index failed\n"); |
| 1965 | brcmf_free_vif(cfg, p2p_vif); | 1965 | brcmf_free_vif(p2p_vif); |
| 1966 | goto exit; | 1966 | goto exit; |
| 1967 | } | 1967 | } |
| 1968 | /* Verify that firmware uses same bssidx as driver !! */ | 1968 | /* Verify that firmware uses same bssidx as driver !! */ |
| 1969 | if (p2p_ifp->bssidx != bssidx) { | 1969 | if (p2p_ifp->bssidx != bssidx) { |
| 1970 | brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n", | 1970 | brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n", |
| 1971 | bssidx, p2p_ifp->bssidx); | 1971 | bssidx, p2p_ifp->bssidx); |
| 1972 | brcmf_free_vif(cfg, p2p_vif); | 1972 | brcmf_free_vif(p2p_vif); |
| 1973 | goto exit; | 1973 | goto exit; |
| 1974 | } | 1974 | } |
| 1975 | 1975 | ||
| @@ -1997,7 +1997,7 @@ void brcmf_p2p_detach(struct brcmf_p2p_info *p2p) | |||
| 1997 | brcmf_p2p_cancel_remain_on_channel(vif->ifp); | 1997 | brcmf_p2p_cancel_remain_on_channel(vif->ifp); |
| 1998 | brcmf_p2p_deinit_discovery(p2p); | 1998 | brcmf_p2p_deinit_discovery(p2p); |
| 1999 | /* remove discovery interface */ | 1999 | /* remove discovery interface */ |
| 2000 | brcmf_free_vif(p2p->cfg, vif); | 2000 | brcmf_free_vif(vif); |
| 2001 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; | 2001 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; |
| 2002 | } | 2002 | } |
| 2003 | /* just set it all to zero */ | 2003 | /* just set it all to zero */ |
| @@ -2222,7 +2222,7 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p, | |||
| 2222 | return &p2p_vif->wdev; | 2222 | return &p2p_vif->wdev; |
| 2223 | 2223 | ||
| 2224 | fail: | 2224 | fail: |
| 2225 | brcmf_free_vif(p2p->cfg, p2p_vif); | 2225 | brcmf_free_vif(p2p_vif); |
| 2226 | return ERR_PTR(err); | 2226 | return ERR_PTR(err); |
| 2227 | } | 2227 | } |
| 2228 | 2228 | ||
| @@ -2231,31 +2231,12 @@ fail: | |||
| 2231 | * | 2231 | * |
| 2232 | * @vif: virtual interface object to delete. | 2232 | * @vif: virtual interface object to delete. |
| 2233 | */ | 2233 | */ |
| 2234 | static void brcmf_p2p_delete_p2pdev(struct brcmf_cfg80211_info *cfg, | 2234 | static void brcmf_p2p_delete_p2pdev(struct brcmf_p2p_info *p2p, |
| 2235 | struct brcmf_cfg80211_vif *vif) | 2235 | struct brcmf_cfg80211_vif *vif) |
| 2236 | { | 2236 | { |
| 2237 | cfg80211_unregister_wdev(&vif->wdev); | 2237 | cfg80211_unregister_wdev(&vif->wdev); |
| 2238 | cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; | 2238 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; |
| 2239 | brcmf_free_vif(cfg, vif); | 2239 | brcmf_free_vif(vif); |
| 2240 | } | ||
| 2241 | |||
| 2242 | /** | ||
| 2243 | * brcmf_p2p_free_p2p_if() - free up net device related data. | ||
| 2244 | * | ||
| 2245 | * @ndev: net device that needs to be freed. | ||
| 2246 | */ | ||
| 2247 | static void brcmf_p2p_free_p2p_if(struct net_device *ndev) | ||
| 2248 | { | ||
| 2249 | struct brcmf_cfg80211_info *cfg; | ||
| 2250 | struct brcmf_cfg80211_vif *vif; | ||
| 2251 | struct brcmf_if *ifp; | ||
| 2252 | |||
| 2253 | ifp = netdev_priv(ndev); | ||
| 2254 | cfg = ifp->drvr->config; | ||
| 2255 | vif = ifp->vif; | ||
| 2256 | |||
| 2257 | brcmf_free_vif(cfg, vif); | ||
| 2258 | free_netdev(ifp->ndev); | ||
| 2259 | } | 2240 | } |
| 2260 | 2241 | ||
| 2261 | /** | 2242 | /** |
| @@ -2335,8 +2316,6 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, | |||
| 2335 | brcmf_err("Registering netdevice failed\n"); | 2316 | brcmf_err("Registering netdevice failed\n"); |
| 2336 | goto fail; | 2317 | goto fail; |
| 2337 | } | 2318 | } |
| 2338 | /* override destructor */ | ||
| 2339 | ifp->ndev->destructor = brcmf_p2p_free_p2p_if; | ||
| 2340 | 2319 | ||
| 2341 | cfg->p2p.bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = vif; | 2320 | cfg->p2p.bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = vif; |
| 2342 | /* Disable firmware roaming for P2P interface */ | 2321 | /* Disable firmware roaming for P2P interface */ |
| @@ -2349,7 +2328,7 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, | |||
| 2349 | return &ifp->vif->wdev; | 2328 | return &ifp->vif->wdev; |
| 2350 | 2329 | ||
| 2351 | fail: | 2330 | fail: |
| 2352 | brcmf_free_vif(cfg, vif); | 2331 | brcmf_free_vif(vif); |
| 2353 | return ERR_PTR(err); | 2332 | return ERR_PTR(err); |
| 2354 | } | 2333 | } |
| 2355 | 2334 | ||
| @@ -2358,8 +2337,6 @@ fail: | |||
| 2358 | * | 2337 | * |
| 2359 | * @wiphy: wiphy device of interface. | 2338 | * @wiphy: wiphy device of interface. |
| 2360 | * @wdev: wireless device of interface. | 2339 | * @wdev: wireless device of interface. |
| 2361 | * | ||
| 2362 | * TODO: not yet supported. | ||
| 2363 | */ | 2340 | */ |
| 2364 | int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) | 2341 | int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) |
| 2365 | { | 2342 | { |
| @@ -2385,7 +2362,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
| 2385 | break; | 2362 | break; |
| 2386 | 2363 | ||
| 2387 | case NL80211_IFTYPE_P2P_DEVICE: | 2364 | case NL80211_IFTYPE_P2P_DEVICE: |
| 2388 | brcmf_p2p_delete_p2pdev(cfg, vif); | 2365 | brcmf_p2p_delete_p2pdev(p2p, vif); |
| 2389 | return 0; | 2366 | return 0; |
| 2390 | default: | 2367 | default: |
| 2391 | return -ENOTSUPP; | 2368 | return -ENOTSUPP; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c index 5f39f28e6efb..9fd40675f18e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/netdevice.h> | 19 | #include <linux/netdevice.h> |
| 20 | #include <linux/mmc/card.h> | 20 | #include <linux/mmc/card.h> |
| 21 | #include <linux/mmc/sdio_func.h> | 21 | #include <linux/mmc/sdio_func.h> |
| 22 | #include <linux/mmc/sdio_ids.h> | ||
| 22 | #include <linux/ssb/ssb_regs.h> | 23 | #include <linux/ssb/ssb_regs.h> |
| 23 | #include <linux/bcma/bcma.h> | 24 | #include <linux/bcma/bcma.h> |
| 24 | 25 | ||
| @@ -83,6 +84,24 @@ static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8[] = { | |||
| 83 | {0, 0x1} | 84 | {0, 0x1} |
| 84 | }; | 85 | }; |
| 85 | 86 | ||
| 87 | /* SDIO Drive Strength to sel value table for PMU Rev 13 (1.8v) */ | ||
| 88 | static const struct sdiod_drive_str sdiod_drive_strength_tab5_1v8[] = { | ||
| 89 | {6, 0x7}, | ||
| 90 | {5, 0x6}, | ||
| 91 | {4, 0x5}, | ||
| 92 | {3, 0x4}, | ||
| 93 | {2, 0x2}, | ||
| 94 | {1, 0x1}, | ||
| 95 | {0, 0x0} | ||
| 96 | }; | ||
| 97 | |||
| 98 | /* SDIO Drive Strength to sel value table for PMU Rev 17 (1.8v) */ | ||
| 99 | static const struct sdiod_drive_str sdiod_drvstr_tab6_1v8[] = { | ||
| 100 | {3, 0x3}, | ||
| 101 | {2, 0x2}, | ||
| 102 | {1, 0x1}, | ||
| 103 | {0, 0x0} }; | ||
| 104 | |||
| 86 | /* SDIO Drive Strength to sel value table for 43143 PMU Rev 17 (3.3V) */ | 105 | /* SDIO Drive Strength to sel value table for 43143 PMU Rev 17 (3.3V) */ |
| 87 | static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = { | 106 | static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = { |
| 88 | {16, 0x7}, | 107 | {16, 0x7}, |
| @@ -569,6 +588,23 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev, | |||
| 569 | ci->ramsize = 0xc0000; | 588 | ci->ramsize = 0xc0000; |
| 570 | ci->rambase = 0x180000; | 589 | ci->rambase = 0x180000; |
| 571 | break; | 590 | break; |
| 591 | case BCM43362_CHIP_ID: | ||
| 592 | ci->c_inf[0].wrapbase = 0x18100000; | ||
| 593 | ci->c_inf[0].cib = 0x27004211; | ||
| 594 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; | ||
| 595 | ci->c_inf[1].base = 0x18002000; | ||
| 596 | ci->c_inf[1].wrapbase = 0x18102000; | ||
| 597 | ci->c_inf[1].cib = 0x0a004211; | ||
| 598 | ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; | ||
| 599 | ci->c_inf[2].base = 0x18004000; | ||
| 600 | ci->c_inf[2].wrapbase = 0x18104000; | ||
| 601 | ci->c_inf[2].cib = 0x08080401; | ||
| 602 | ci->c_inf[3].id = BCMA_CORE_ARM_CM3; | ||
| 603 | ci->c_inf[3].base = 0x18003000; | ||
| 604 | ci->c_inf[3].wrapbase = 0x18103000; | ||
| 605 | ci->c_inf[3].cib = 0x03004211; | ||
| 606 | ci->ramsize = 0x3C000; | ||
| 607 | break; | ||
| 572 | default: | 608 | default: |
| 573 | brcmf_err("chipid 0x%x is not supported\n", ci->chip); | 609 | brcmf_err("chipid 0x%x is not supported\n", ci->chip); |
| 574 | return -ENODEV; | 610 | return -ENODEV; |
| @@ -757,6 +793,11 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, | |||
| 757 | str_mask = 0x00003800; | 793 | str_mask = 0x00003800; |
| 758 | str_shift = 11; | 794 | str_shift = 11; |
| 759 | break; | 795 | break; |
| 796 | case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17): | ||
| 797 | str_tab = sdiod_drvstr_tab6_1v8; | ||
| 798 | str_mask = 0x00001800; | ||
| 799 | str_shift = 11; | ||
| 800 | break; | ||
| 760 | case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17): | 801 | case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17): |
| 761 | /* note: 43143 does not support tristate */ | 802 | /* note: 43143 does not support tristate */ |
| 762 | i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1; | 803 | i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1; |
| @@ -769,6 +810,11 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, | |||
| 769 | brcmf_sdio_chip_name(ci->chip, chn, 8), | 810 | brcmf_sdio_chip_name(ci->chip, chn, 8), |
| 770 | drivestrength); | 811 | drivestrength); |
| 771 | break; | 812 | break; |
| 813 | case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13): | ||
| 814 | str_tab = sdiod_drive_strength_tab5_1v8; | ||
| 815 | str_mask = 0x00003800; | ||
| 816 | str_shift = 11; | ||
| 817 | break; | ||
| 772 | default: | 818 | default: |
| 773 | brcmf_err("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n", | 819 | brcmf_err("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n", |
| 774 | brcmf_sdio_chip_name(ci->chip, chn, 8), | 820 | brcmf_sdio_chip_name(ci->chip, chn, 8), |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h index d0f4b45b24c7..7ea424e20773 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h | |||
| @@ -54,14 +54,6 @@ | |||
| 54 | 54 | ||
| 55 | #define BRCMF_MAX_CORENUM 6 | 55 | #define BRCMF_MAX_CORENUM 6 |
| 56 | 56 | ||
| 57 | /* SDIO device ID */ | ||
| 58 | #define SDIO_DEVICE_ID_BROADCOM_43143 43143 | ||
| 59 | #define SDIO_DEVICE_ID_BROADCOM_43241 0x4324 | ||
| 60 | #define SDIO_DEVICE_ID_BROADCOM_4329 0x4329 | ||
| 61 | #define SDIO_DEVICE_ID_BROADCOM_4330 0x4330 | ||
| 62 | #define SDIO_DEVICE_ID_BROADCOM_4334 0x4334 | ||
| 63 | #define SDIO_DEVICE_ID_BROADCOM_4335_4339 0x4335 | ||
| 64 | |||
| 65 | struct chip_core_info { | 57 | struct chip_core_info { |
| 66 | u16 id; | 58 | u16 id; |
| 67 | u16 rev; | 59 | u16 rev; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h index a0981b32c729..092e9c824992 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h | |||
| @@ -167,7 +167,6 @@ struct brcmf_sdio_dev { | |||
| 167 | u32 sbwad; /* Save backplane window address */ | 167 | u32 sbwad; /* Save backplane window address */ |
| 168 | struct brcmf_sdio *bus; | 168 | struct brcmf_sdio *bus; |
| 169 | atomic_t suspend; /* suspend flag */ | 169 | atomic_t suspend; /* suspend flag */ |
| 170 | wait_queue_head_t request_byte_wait; | ||
| 171 | wait_queue_head_t request_word_wait; | 170 | wait_queue_head_t request_word_wait; |
| 172 | wait_queue_head_t request_buffer_wait; | 171 | wait_queue_head_t request_buffer_wait; |
| 173 | struct device *dev; | 172 | struct device *dev; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 3966fe0fcfd9..aad83aef7d93 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
| @@ -1095,10 +1095,10 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif) | |||
| 1095 | BRCMF_C_DISASSOC, NULL, 0); | 1095 | BRCMF_C_DISASSOC, NULL, 0); |
| 1096 | if (err) { | 1096 | if (err) { |
| 1097 | brcmf_err("WLC_DISASSOC failed (%d)\n", err); | 1097 | brcmf_err("WLC_DISASSOC failed (%d)\n", err); |
| 1098 | cfg80211_disconnected(vif->wdev.netdev, 0, | ||
| 1099 | NULL, 0, GFP_KERNEL); | ||
| 1100 | } | 1098 | } |
| 1101 | clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state); | 1099 | clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state); |
| 1100 | cfg80211_disconnected(vif->wdev.netdev, 0, NULL, 0, GFP_KERNEL); | ||
| 1101 | |||
| 1102 | } | 1102 | } |
| 1103 | clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state); | 1103 | clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state); |
| 1104 | clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status); | 1104 | clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status); |
| @@ -1758,6 +1758,7 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, | |||
| 1758 | return -EIO; | 1758 | return -EIO; |
| 1759 | 1759 | ||
| 1760 | clear_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state); | 1760 | clear_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state); |
| 1761 | cfg80211_disconnected(ndev, reason_code, NULL, 0, GFP_KERNEL); | ||
| 1761 | 1762 | ||
| 1762 | memcpy(&scbval.ea, &profile->bssid, ETH_ALEN); | 1763 | memcpy(&scbval.ea, &profile->bssid, ETH_ALEN); |
| 1763 | scbval.val = cpu_to_le32(reason_code); | 1764 | scbval.val = cpu_to_le32(reason_code); |
| @@ -4359,9 +4360,6 @@ struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, | |||
| 4359 | { | 4360 | { |
| 4360 | struct brcmf_cfg80211_vif *vif; | 4361 | struct brcmf_cfg80211_vif *vif; |
| 4361 | 4362 | ||
| 4362 | if (cfg->vif_cnt == BRCMF_IFACE_MAX_CNT) | ||
| 4363 | return ERR_PTR(-ENOSPC); | ||
| 4364 | |||
| 4365 | brcmf_dbg(TRACE, "allocating virtual interface (size=%zu)\n", | 4363 | brcmf_dbg(TRACE, "allocating virtual interface (size=%zu)\n", |
| 4366 | sizeof(*vif)); | 4364 | sizeof(*vif)); |
| 4367 | vif = kzalloc(sizeof(*vif), GFP_KERNEL); | 4365 | vif = kzalloc(sizeof(*vif), GFP_KERNEL); |
| @@ -4378,21 +4376,25 @@ struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, | |||
| 4378 | brcmf_init_prof(&vif->profile); | 4376 | brcmf_init_prof(&vif->profile); |
| 4379 | 4377 | ||
| 4380 | list_add_tail(&vif->list, &cfg->vif_list); | 4378 | list_add_tail(&vif->list, &cfg->vif_list); |
| 4381 | cfg->vif_cnt++; | ||
| 4382 | return vif; | 4379 | return vif; |
| 4383 | } | 4380 | } |
| 4384 | 4381 | ||
| 4385 | void brcmf_free_vif(struct brcmf_cfg80211_info *cfg, | 4382 | void brcmf_free_vif(struct brcmf_cfg80211_vif *vif) |
| 4386 | struct brcmf_cfg80211_vif *vif) | ||
| 4387 | { | 4383 | { |
| 4388 | list_del(&vif->list); | 4384 | list_del(&vif->list); |
| 4389 | cfg->vif_cnt--; | ||
| 4390 | |||
| 4391 | kfree(vif); | 4385 | kfree(vif); |
| 4392 | if (!cfg->vif_cnt) { | 4386 | } |
| 4393 | wiphy_unregister(cfg->wiphy); | 4387 | |
| 4394 | wiphy_free(cfg->wiphy); | 4388 | void brcmf_cfg80211_free_netdev(struct net_device *ndev) |
| 4395 | } | 4389 | { |
| 4390 | struct brcmf_cfg80211_vif *vif; | ||
| 4391 | struct brcmf_if *ifp; | ||
| 4392 | |||
| 4393 | ifp = netdev_priv(ndev); | ||
| 4394 | vif = ifp->vif; | ||
| 4395 | |||
| 4396 | brcmf_free_vif(vif); | ||
| 4397 | free_netdev(ndev); | ||
| 4396 | } | 4398 | } |
| 4397 | 4399 | ||
| 4398 | static bool brcmf_is_linkup(const struct brcmf_event_msg *e) | 4400 | static bool brcmf_is_linkup(const struct brcmf_event_msg *e) |
| @@ -4979,20 +4981,20 @@ cfg80211_p2p_attach_out: | |||
| 4979 | wl_deinit_priv(cfg); | 4981 | wl_deinit_priv(cfg); |
| 4980 | 4982 | ||
| 4981 | cfg80211_attach_out: | 4983 | cfg80211_attach_out: |
| 4982 | brcmf_free_vif(cfg, vif); | 4984 | brcmf_free_vif(vif); |
| 4983 | return NULL; | 4985 | return NULL; |
| 4984 | } | 4986 | } |
| 4985 | 4987 | ||
| 4986 | void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) | 4988 | void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) |
| 4987 | { | 4989 | { |
| 4988 | struct brcmf_cfg80211_vif *vif; | 4990 | if (!cfg) |
| 4989 | struct brcmf_cfg80211_vif *tmp; | 4991 | return; |
| 4990 | 4992 | ||
| 4991 | wl_deinit_priv(cfg); | 4993 | WARN_ON(!list_empty(&cfg->vif_list)); |
| 4994 | wiphy_unregister(cfg->wiphy); | ||
| 4992 | brcmf_btcoex_detach(cfg); | 4995 | brcmf_btcoex_detach(cfg); |
| 4993 | list_for_each_entry_safe(vif, tmp, &cfg->vif_list, list) { | 4996 | wl_deinit_priv(cfg); |
| 4994 | brcmf_free_vif(cfg, vif); | 4997 | wiphy_free(cfg->wiphy); |
| 4995 | } | ||
| 4996 | } | 4998 | } |
| 4997 | 4999 | ||
| 4998 | static s32 | 5000 | static s32 |
| @@ -5087,7 +5089,8 @@ dongle_scantime_out: | |||
| 5087 | } | 5089 | } |
| 5088 | 5090 | ||
| 5089 | 5091 | ||
| 5090 | static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap) | 5092 | static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, |
| 5093 | u32 bw_cap[]) | ||
| 5091 | { | 5094 | { |
| 5092 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | 5095 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); |
| 5093 | struct ieee80211_channel *band_chan_arr; | 5096 | struct ieee80211_channel *band_chan_arr; |
| @@ -5100,7 +5103,6 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap) | |||
| 5100 | enum ieee80211_band band; | 5103 | enum ieee80211_band band; |
| 5101 | u32 channel; | 5104 | u32 channel; |
| 5102 | u32 *n_cnt; | 5105 | u32 *n_cnt; |
| 5103 | bool ht40_allowed; | ||
| 5104 | u32 index; | 5106 | u32 index; |
| 5105 | u32 ht40_flag; | 5107 | u32 ht40_flag; |
| 5106 | bool update; | 5108 | bool update; |
| @@ -5133,18 +5135,17 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap) | |||
| 5133 | array_size = ARRAY_SIZE(__wl_2ghz_channels); | 5135 | array_size = ARRAY_SIZE(__wl_2ghz_channels); |
| 5134 | n_cnt = &__wl_band_2ghz.n_channels; | 5136 | n_cnt = &__wl_band_2ghz.n_channels; |
| 5135 | band = IEEE80211_BAND_2GHZ; | 5137 | band = IEEE80211_BAND_2GHZ; |
| 5136 | ht40_allowed = (bw_cap == WLC_N_BW_40ALL); | ||
| 5137 | } else if (ch.band == BRCMU_CHAN_BAND_5G) { | 5138 | } else if (ch.band == BRCMU_CHAN_BAND_5G) { |
| 5138 | band_chan_arr = __wl_5ghz_a_channels; | 5139 | band_chan_arr = __wl_5ghz_a_channels; |
| 5139 | array_size = ARRAY_SIZE(__wl_5ghz_a_channels); | 5140 | array_size = ARRAY_SIZE(__wl_5ghz_a_channels); |
| 5140 | n_cnt = &__wl_band_5ghz_a.n_channels; | 5141 | n_cnt = &__wl_band_5ghz_a.n_channels; |
| 5141 | band = IEEE80211_BAND_5GHZ; | 5142 | band = IEEE80211_BAND_5GHZ; |
| 5142 | ht40_allowed = !(bw_cap == WLC_N_BW_20ALL); | ||
| 5143 | } else { | 5143 | } else { |
| 5144 | brcmf_err("Invalid channel Sepc. 0x%x.\n", ch.chspec); | 5144 | brcmf_err("Invalid channel Spec. 0x%x.\n", ch.chspec); |
| 5145 | continue; | 5145 | continue; |
| 5146 | } | 5146 | } |
| 5147 | if (!ht40_allowed && ch.bw == BRCMU_CHAN_BW_40) | 5147 | if (!(bw_cap[band] & WLC_BW_40MHZ_BIT) && |
| 5148 | ch.bw == BRCMU_CHAN_BW_40) | ||
| 5148 | continue; | 5149 | continue; |
| 5149 | update = false; | 5150 | update = false; |
| 5150 | for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) { | 5151 | for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) { |
| @@ -5162,7 +5163,10 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap) | |||
| 5162 | ieee80211_channel_to_frequency(ch.chnum, band); | 5163 | ieee80211_channel_to_frequency(ch.chnum, band); |
| 5163 | band_chan_arr[index].hw_value = ch.chnum; | 5164 | band_chan_arr[index].hw_value = ch.chnum; |
| 5164 | 5165 | ||
| 5165 | if (ch.bw == BRCMU_CHAN_BW_40 && ht40_allowed) { | 5166 | brcmf_err("channel %d: f=%d bw=%d sb=%d\n", |
| 5167 | ch.chnum, band_chan_arr[index].center_freq, | ||
| 5168 | ch.bw, ch.sb); | ||
| 5169 | if (ch.bw == BRCMU_CHAN_BW_40) { | ||
| 5166 | /* assuming the order is HT20, HT40 Upper, | 5170 | /* assuming the order is HT20, HT40 Upper, |
| 5167 | * HT40 lower from chanspecs | 5171 | * HT40 lower from chanspecs |
| 5168 | */ | 5172 | */ |
| @@ -5213,6 +5217,46 @@ exit: | |||
| 5213 | return err; | 5217 | return err; |
| 5214 | } | 5218 | } |
| 5215 | 5219 | ||
| 5220 | static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[]) | ||
| 5221 | { | ||
| 5222 | u32 band, mimo_bwcap; | ||
| 5223 | int err; | ||
| 5224 | |||
| 5225 | band = WLC_BAND_2G; | ||
| 5226 | err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &band); | ||
| 5227 | if (!err) { | ||
| 5228 | bw_cap[IEEE80211_BAND_2GHZ] = band; | ||
| 5229 | band = WLC_BAND_5G; | ||
| 5230 | err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &band); | ||
| 5231 | if (!err) { | ||
| 5232 | bw_cap[IEEE80211_BAND_5GHZ] = band; | ||
| 5233 | return; | ||
| 5234 | } | ||
| 5235 | WARN_ON(1); | ||
| 5236 | return; | ||
| 5237 | } | ||
| 5238 | brcmf_dbg(INFO, "fallback to mimo_bw_cap info\n"); | ||
| 5239 | mimo_bwcap = 0; | ||
| 5240 | err = brcmf_fil_iovar_int_get(ifp, "mimo_bw_cap", &mimo_bwcap); | ||
| 5241 | if (err) | ||
| 5242 | /* assume 20MHz if firmware does not give a clue */ | ||
| 5243 | mimo_bwcap = WLC_N_BW_20ALL; | ||
| 5244 | |||
| 5245 | switch (mimo_bwcap) { | ||
| 5246 | case WLC_N_BW_40ALL: | ||
| 5247 | bw_cap[IEEE80211_BAND_2GHZ] |= WLC_BW_40MHZ_BIT; | ||
| 5248 | /* fall-thru */ | ||
| 5249 | case WLC_N_BW_20IN2G_40IN5G: | ||
| 5250 | bw_cap[IEEE80211_BAND_5GHZ] |= WLC_BW_40MHZ_BIT; | ||
| 5251 | /* fall-thru */ | ||
| 5252 | case WLC_N_BW_20ALL: | ||
| 5253 | bw_cap[IEEE80211_BAND_2GHZ] |= WLC_BW_20MHZ_BIT; | ||
| 5254 | bw_cap[IEEE80211_BAND_5GHZ] |= WLC_BW_20MHZ_BIT; | ||
| 5255 | break; | ||
| 5256 | default: | ||
| 5257 | brcmf_err("invalid mimo_bw_cap value\n"); | ||
| 5258 | } | ||
| 5259 | } | ||
| 5216 | 5260 | ||
| 5217 | static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg) | 5261 | static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg) |
| 5218 | { | 5262 | { |
| @@ -5221,13 +5265,13 @@ static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg) | |||
| 5221 | s32 phy_list; | 5265 | s32 phy_list; |
| 5222 | u32 band_list[3]; | 5266 | u32 band_list[3]; |
| 5223 | u32 nmode; | 5267 | u32 nmode; |
| 5224 | u32 bw_cap = 0; | 5268 | u32 bw_cap[2] = { 0, 0 }; |
| 5225 | s8 phy; | 5269 | s8 phy; |
| 5226 | s32 err; | 5270 | s32 err; |
| 5227 | u32 nband; | 5271 | u32 nband; |
| 5228 | s32 i; | 5272 | s32 i; |
| 5229 | struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS]; | 5273 | struct ieee80211_supported_band *bands[2] = { NULL, NULL }; |
| 5230 | s32 index; | 5274 | struct ieee80211_supported_band *band; |
| 5231 | 5275 | ||
| 5232 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_PHYLIST, | 5276 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_PHYLIST, |
| 5233 | &phy_list, sizeof(phy_list)); | 5277 | &phy_list, sizeof(phy_list)); |
| @@ -5253,11 +5297,10 @@ static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg) | |||
| 5253 | if (err) { | 5297 | if (err) { |
| 5254 | brcmf_err("nmode error (%d)\n", err); | 5298 | brcmf_err("nmode error (%d)\n", err); |
| 5255 | } else { | 5299 | } else { |
| 5256 | err = brcmf_fil_iovar_int_get(ifp, "mimo_bw_cap", &bw_cap); | 5300 | brcmf_get_bwcap(ifp, bw_cap); |
| 5257 | if (err) | ||
| 5258 | brcmf_err("mimo_bw_cap error (%d)\n", err); | ||
| 5259 | } | 5301 | } |
| 5260 | brcmf_dbg(INFO, "nmode=%d, mimo_bw_cap=%d\n", nmode, bw_cap); | 5302 | brcmf_dbg(INFO, "nmode=%d, bw_cap=(%d, %d)\n", nmode, |
| 5303 | bw_cap[IEEE80211_BAND_2GHZ], bw_cap[IEEE80211_BAND_5GHZ]); | ||
| 5261 | 5304 | ||
| 5262 | err = brcmf_construct_reginfo(cfg, bw_cap); | 5305 | err = brcmf_construct_reginfo(cfg, bw_cap); |
| 5263 | if (err) { | 5306 | if (err) { |
| @@ -5266,40 +5309,33 @@ static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg) | |||
| 5266 | } | 5309 | } |
| 5267 | 5310 | ||
| 5268 | nband = band_list[0]; | 5311 | nband = band_list[0]; |
| 5269 | memset(bands, 0, sizeof(bands)); | ||
| 5270 | 5312 | ||
| 5271 | for (i = 1; i <= nband && i < ARRAY_SIZE(band_list); i++) { | 5313 | for (i = 1; i <= nband && i < ARRAY_SIZE(band_list); i++) { |
| 5272 | index = -1; | 5314 | band = NULL; |
| 5273 | if ((band_list[i] == WLC_BAND_5G) && | 5315 | if ((band_list[i] == WLC_BAND_5G) && |
| 5274 | (__wl_band_5ghz_a.n_channels > 0)) { | 5316 | (__wl_band_5ghz_a.n_channels > 0)) |
| 5275 | index = IEEE80211_BAND_5GHZ; | 5317 | band = &__wl_band_5ghz_a; |
| 5276 | bands[index] = &__wl_band_5ghz_a; | 5318 | else if ((band_list[i] == WLC_BAND_2G) && |
| 5277 | if ((bw_cap == WLC_N_BW_40ALL) || | 5319 | (__wl_band_2ghz.n_channels > 0)) |
| 5278 | (bw_cap == WLC_N_BW_20IN2G_40IN5G)) | 5320 | band = &__wl_band_2ghz; |
| 5279 | bands[index]->ht_cap.cap |= | 5321 | else |
| 5280 | IEEE80211_HT_CAP_SGI_40; | 5322 | continue; |
| 5281 | } else if ((band_list[i] == WLC_BAND_2G) && | ||
| 5282 | (__wl_band_2ghz.n_channels > 0)) { | ||
| 5283 | index = IEEE80211_BAND_2GHZ; | ||
| 5284 | bands[index] = &__wl_band_2ghz; | ||
| 5285 | if (bw_cap == WLC_N_BW_40ALL) | ||
| 5286 | bands[index]->ht_cap.cap |= | ||
| 5287 | IEEE80211_HT_CAP_SGI_40; | ||
| 5288 | } | ||
| 5289 | 5323 | ||
| 5290 | if ((index >= 0) && nmode) { | 5324 | if (bw_cap[band->band] & WLC_BW_40MHZ_BIT) { |
| 5291 | bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; | 5325 | band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; |
| 5292 | bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40; | 5326 | band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
| 5293 | bands[index]->ht_cap.ht_supported = true; | ||
| 5294 | bands[index]->ht_cap.ampdu_factor = | ||
| 5295 | IEEE80211_HT_MAX_AMPDU_64K; | ||
| 5296 | bands[index]->ht_cap.ampdu_density = | ||
| 5297 | IEEE80211_HT_MPDU_DENSITY_16; | ||
| 5298 | /* An HT shall support all EQM rates for one spatial | ||
| 5299 | * stream | ||
| 5300 | */ | ||
| 5301 | bands[index]->ht_cap.mcs.rx_mask[0] = 0xff; | ||
| 5302 | } | 5327 | } |
| 5328 | band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; | ||
| 5329 | band->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40; | ||
| 5330 | band->ht_cap.ht_supported = true; | ||
| 5331 | band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; | ||
| 5332 | band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; | ||
| 5333 | /* An HT shall support all EQM rates for one spatial | ||
| 5334 | * stream | ||
| 5335 | */ | ||
| 5336 | band->ht_cap.mcs.rx_mask[0] = 0xff; | ||
| 5337 | band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||
| 5338 | bands[band->band] = band; | ||
| 5303 | } | 5339 | } |
| 5304 | 5340 | ||
| 5305 | wiphy = cfg_to_wiphy(cfg); | 5341 | wiphy = cfg_to_wiphy(cfg); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index d9bdaf9a72d0..2dc6a074e8ed 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h | |||
| @@ -412,7 +412,6 @@ struct brcmf_cfg80211_info { | |||
| 412 | struct work_struct escan_timeout_work; | 412 | struct work_struct escan_timeout_work; |
| 413 | u8 *escan_ioctl_buf; | 413 | u8 *escan_ioctl_buf; |
| 414 | struct list_head vif_list; | 414 | struct list_head vif_list; |
| 415 | u8 vif_cnt; | ||
| 416 | struct brcmf_cfg80211_vif_event vif_event; | 415 | struct brcmf_cfg80211_vif_event vif_event; |
| 417 | struct completion vif_disabled; | 416 | struct completion vif_disabled; |
| 418 | struct brcmu_d11inf d11inf; | 417 | struct brcmu_d11inf d11inf; |
| @@ -487,8 +486,7 @@ enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp); | |||
| 487 | struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, | 486 | struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, |
| 488 | enum nl80211_iftype type, | 487 | enum nl80211_iftype type, |
| 489 | bool pm_block); | 488 | bool pm_block); |
| 490 | void brcmf_free_vif(struct brcmf_cfg80211_info *cfg, | 489 | void brcmf_free_vif(struct brcmf_cfg80211_vif *vif); |
| 491 | struct brcmf_cfg80211_vif *vif); | ||
| 492 | 490 | ||
| 493 | s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, | 491 | s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, |
| 494 | const u8 *vndr_ie_buf, u32 vndr_ie_len); | 492 | const u8 *vndr_ie_buf, u32 vndr_ie_len); |
| @@ -507,5 +505,6 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, | |||
| 507 | bool fw_abort); | 505 | bool fw_abort); |
| 508 | void brcmf_set_mpc(struct brcmf_if *ndev, int mpc); | 506 | void brcmf_set_mpc(struct brcmf_if *ndev, int mpc); |
| 509 | void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg); | 507 | void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg); |
| 508 | void brcmf_cfg80211_free_netdev(struct net_device *ndev); | ||
| 510 | 509 | ||
| 511 | #endif /* _wl_cfg80211_h_ */ | 510 | #endif /* _wl_cfg80211_h_ */ |
diff --git a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h index 84113ea16f84..6fa5d4863782 100644 --- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #define BCM4331_CHIP_ID 0x4331 | 41 | #define BCM4331_CHIP_ID 0x4331 |
| 42 | #define BCM4334_CHIP_ID 0x4334 | 42 | #define BCM4334_CHIP_ID 0x4334 |
| 43 | #define BCM4335_CHIP_ID 0x4335 | 43 | #define BCM4335_CHIP_ID 0x4335 |
| 44 | #define BCM43362_CHIP_ID 43362 | ||
| 44 | #define BCM4339_CHIP_ID 0x4339 | 45 | #define BCM4339_CHIP_ID 0x4339 |
| 45 | 46 | ||
| 46 | #endif /* _BRCM_HW_IDS_H_ */ | 47 | #endif /* _BRCM_HW_IDS_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h index 0505cc065e0d..7ca2aa1035b2 100644 --- a/drivers/net/wireless/brcm80211/include/brcmu_wifi.h +++ b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h | |||
| @@ -82,6 +82,20 @@ | |||
| 82 | #define WLC_N_BW_40ALL 1 | 82 | #define WLC_N_BW_40ALL 1 |
| 83 | #define WLC_N_BW_20IN2G_40IN5G 2 | 83 | #define WLC_N_BW_20IN2G_40IN5G 2 |
| 84 | 84 | ||
| 85 | #define WLC_BW_20MHZ_BIT BIT(0) | ||
| 86 | #define WLC_BW_40MHZ_BIT BIT(1) | ||
| 87 | #define WLC_BW_80MHZ_BIT BIT(2) | ||
| 88 | #define WLC_BW_160MHZ_BIT BIT(3) | ||
| 89 | |||
| 90 | /* Bandwidth capabilities */ | ||
| 91 | #define WLC_BW_CAP_20MHZ (WLC_BW_20MHZ_BIT) | ||
| 92 | #define WLC_BW_CAP_40MHZ (WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT) | ||
| 93 | #define WLC_BW_CAP_80MHZ (WLC_BW_80MHZ_BIT|WLC_BW_40MHZ_BIT| \ | ||
| 94 | WLC_BW_20MHZ_BIT) | ||
| 95 | #define WLC_BW_CAP_160MHZ (WLC_BW_160MHZ_BIT|WLC_BW_80MHZ_BIT| \ | ||
| 96 | WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT) | ||
| 97 | #define WLC_BW_CAP_UNRESTRICTED 0xFF | ||
| 98 | |||
| 85 | /* band types */ | 99 | /* band types */ |
| 86 | #define WLC_BAND_AUTO 0 /* auto-select */ | 100 | #define WLC_BAND_AUTO 0 /* auto-select */ |
| 87 | #define WLC_BAND_5G 1 /* 5 Ghz */ | 101 | #define WLC_BAND_5G 1 /* 5 Ghz */ |
diff --git a/drivers/net/wireless/cw1200/fwio.c b/drivers/net/wireless/cw1200/fwio.c index acdff0f7f952..5a9ffd3a6a6c 100644 --- a/drivers/net/wireless/cw1200/fwio.c +++ b/drivers/net/wireless/cw1200/fwio.c | |||
| @@ -14,7 +14,6 @@ | |||
| 14 | * published by the Free Software Foundation. | 14 | * published by the Free Software Foundation. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/vmalloc.h> | 17 | #include <linux/vmalloc.h> |
| 19 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
| 20 | #include <linux/firmware.h> | 19 | #include <linux/firmware.h> |
diff --git a/drivers/net/wireless/cw1200/main.c b/drivers/net/wireless/cw1200/main.c index 090f01577dd2..d1270da4dfea 100644 --- a/drivers/net/wireless/cw1200/main.c +++ b/drivers/net/wireless/cw1200/main.c | |||
| @@ -21,7 +21,6 @@ | |||
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 24 | #include <linux/init.h> | ||
| 25 | #include <linux/firmware.h> | 24 | #include <linux/firmware.h> |
| 26 | #include <linux/etherdevice.h> | 25 | #include <linux/etherdevice.h> |
| 27 | #include <linux/vmalloc.h> | 26 | #include <linux/vmalloc.h> |
diff --git a/drivers/net/wireless/cw1200/pm.c b/drivers/net/wireless/cw1200/pm.c index b37abb9f0453..6907c8fd4578 100644 --- a/drivers/net/wireless/cw1200/pm.c +++ b/drivers/net/wireless/cw1200/pm.c | |||
| @@ -225,7 +225,7 @@ int cw1200_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
| 225 | cw1200_set_pm(priv, &priv->powersave_mode); | 225 | cw1200_set_pm(priv, &priv->powersave_mode); |
| 226 | if (wait_event_interruptible_timeout(priv->ps_mode_switch_done, | 226 | if (wait_event_interruptible_timeout(priv->ps_mode_switch_done, |
| 227 | !priv->ps_mode_switch_in_progress, 1*HZ) <= 0) { | 227 | !priv->ps_mode_switch_in_progress, 1*HZ) <= 0) { |
| 228 | goto revert3; | 228 | goto revert4; |
| 229 | } | 229 | } |
| 230 | } | 230 | } |
| 231 | 231 | ||
| @@ -254,11 +254,11 @@ int cw1200_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
| 254 | 254 | ||
| 255 | /* Stop serving thread */ | 255 | /* Stop serving thread */ |
| 256 | if (cw1200_bh_suspend(priv)) | 256 | if (cw1200_bh_suspend(priv)) |
| 257 | goto revert4; | 257 | goto revert5; |
| 258 | 258 | ||
| 259 | ret = timer_pending(&priv->mcast_timeout); | 259 | ret = timer_pending(&priv->mcast_timeout); |
| 260 | if (ret) | 260 | if (ret) |
| 261 | goto revert5; | 261 | goto revert6; |
| 262 | 262 | ||
| 263 | /* Store suspend state */ | 263 | /* Store suspend state */ |
| 264 | pm_state->suspend_state = state; | 264 | pm_state->suspend_state = state; |
| @@ -280,9 +280,9 @@ int cw1200_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
| 280 | 280 | ||
| 281 | return 0; | 281 | return 0; |
| 282 | 282 | ||
| 283 | revert5: | 283 | revert6: |
| 284 | WARN_ON(cw1200_bh_resume(priv)); | 284 | WARN_ON(cw1200_bh_resume(priv)); |
| 285 | revert4: | 285 | revert5: |
| 286 | cw1200_resume_work(priv, &priv->bss_loss_work, | 286 | cw1200_resume_work(priv, &priv->bss_loss_work, |
| 287 | state->bss_loss_tmo); | 287 | state->bss_loss_tmo); |
| 288 | cw1200_resume_work(priv, &priv->join_timeout, | 288 | cw1200_resume_work(priv, &priv->join_timeout, |
| @@ -291,6 +291,7 @@ revert4: | |||
| 291 | state->direct_probe); | 291 | state->direct_probe); |
| 292 | cw1200_resume_work(priv, &priv->link_id_gc_work, | 292 | cw1200_resume_work(priv, &priv->link_id_gc_work, |
| 293 | state->link_id_gc); | 293 | state->link_id_gc); |
| 294 | revert4: | ||
| 294 | kfree(state); | 295 | kfree(state); |
| 295 | revert3: | 296 | revert3: |
| 296 | wsm_set_udp_port_filter(priv, &cw1200_udp_port_filter_off); | 297 | wsm_set_udp_port_filter(priv, &cw1200_udp_port_filter_off); |
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 56cd01ca8ad0..9f825f2620da 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | #define PRISM2_PCCARD | 1 | #define PRISM2_PCCARD |
| 2 | 2 | ||
| 3 | #include <linux/module.h> | 3 | #include <linux/module.h> |
| 4 | #include <linux/init.h> | ||
| 5 | #include <linux/if.h> | 4 | #include <linux/if.h> |
| 6 | #include <linux/slab.h> | 5 | #include <linux/slab.h> |
| 7 | #include <linux/wait.h> | 6 | #include <linux/wait.h> |
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index 2454a740ea50..3e5fa7872b64 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c | |||
| @@ -2567,7 +2567,7 @@ static int prism2_ioctl_priv_prism2_param(struct net_device *dev, | |||
| 2567 | local->passive_scan_interval = value; | 2567 | local->passive_scan_interval = value; |
| 2568 | if (timer_pending(&local->passive_scan_timer)) | 2568 | if (timer_pending(&local->passive_scan_timer)) |
| 2569 | del_timer(&local->passive_scan_timer); | 2569 | del_timer(&local->passive_scan_timer); |
| 2570 | if (value > 0) { | 2570 | if (value > 0 && value < INT_MAX / HZ) { |
| 2571 | local->passive_scan_timer.expires = jiffies + | 2571 | local->passive_scan_timer.expires = jiffies + |
| 2572 | local->passive_scan_interval * HZ; | 2572 | local->passive_scan_interval * HZ; |
| 2573 | add_timer(&local->passive_scan_timer); | 2573 | add_timer(&local->passive_scan_timer); |
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c index 05ca3402dca7..91158e2e961c 100644 --- a/drivers/net/wireless/hostap/hostap_pci.c +++ b/drivers/net/wireless/hostap/hostap_pci.c | |||
| @@ -5,7 +5,6 @@ | |||
| 5 | * Andy Warner <andyw@pobox.com> */ | 5 | * Andy Warner <andyw@pobox.com> */ |
| 6 | 6 | ||
| 7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
| 8 | #include <linux/init.h> | ||
| 9 | #include <linux/if.h> | 8 | #include <linux/if.h> |
| 10 | #include <linux/skbuff.h> | 9 | #include <linux/skbuff.h> |
| 11 | #include <linux/netdevice.h> | 10 | #include <linux/netdevice.h> |
diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c index c3d067ee4db9..3bf530d9a40f 100644 --- a/drivers/net/wireless/hostap/hostap_plx.c +++ b/drivers/net/wireless/hostap/hostap_plx.c | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | 8 | ||
| 9 | 9 | ||
| 10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 11 | #include <linux/init.h> | ||
| 12 | #include <linux/if.h> | 11 | #include <linux/if.h> |
| 13 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
| 14 | #include <linux/netdevice.h> | 13 | #include <linux/netdevice.h> |
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.h b/drivers/net/wireless/ipw2x00/ipw2200.h index 570d6fb88967..aa301d1eee3c 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.h +++ b/drivers/net/wireless/ipw2x00/ipw2200.h | |||
| @@ -29,7 +29,6 @@ | |||
| 29 | 29 | ||
| 30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
| 31 | #include <linux/moduleparam.h> | 31 | #include <linux/moduleparam.h> |
| 32 | #include <linux/init.h> | ||
| 33 | #include <linux/interrupt.h> | 32 | #include <linux/interrupt.h> |
| 34 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
| 35 | 34 | ||
diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c index 5c6253811c52..a586a85bfcfe 100644 --- a/drivers/net/wireless/ipw2x00/libipw_rx.c +++ b/drivers/net/wireless/ipw2x00/libipw_rx.c | |||
| @@ -1468,7 +1468,7 @@ static inline int is_same_network(struct libipw_network *src, | |||
| 1468 | * as one network */ | 1468 | * as one network */ |
| 1469 | return ((src->ssid_len == dst->ssid_len) && | 1469 | return ((src->ssid_len == dst->ssid_len) && |
| 1470 | (src->channel == dst->channel) && | 1470 | (src->channel == dst->channel) && |
| 1471 | ether_addr_equal(src->bssid, dst->bssid) && | 1471 | ether_addr_equal_64bits(src->bssid, dst->bssid) && |
| 1472 | !memcmp(src->ssid, dst->ssid, src->ssid_len)); | 1472 | !memcmp(src->ssid, dst->ssid, src->ssid_len)); |
| 1473 | } | 1473 | } |
| 1474 | 1474 | ||
diff --git a/drivers/net/wireless/iwlegacy/3945-rs.c b/drivers/net/wireless/iwlegacy/3945-rs.c index aea667b430c3..9a45f6f626f6 100644 --- a/drivers/net/wireless/iwlegacy/3945-rs.c +++ b/drivers/net/wireless/iwlegacy/3945-rs.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
| 26 | 26 | ||
| 27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
| 28 | #include <linux/init.h> | ||
| 29 | #include <linux/skbuff.h> | 28 | #include <linux/skbuff.h> |
| 30 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
| 31 | #include <net/mac80211.h> | 30 | #include <net/mac80211.h> |
diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c index f09e257759d5..d37a6fd90d40 100644 --- a/drivers/net/wireless/iwlegacy/3945.c +++ b/drivers/net/wireless/iwlegacy/3945.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | 26 | ||
| 27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
| 28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
| 29 | #include <linux/init.h> | ||
| 30 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
| 31 | #include <linux/pci.h> | 30 | #include <linux/pci.h> |
| 32 | #include <linux/dma-mapping.h> | 31 | #include <linux/dma-mapping.h> |
| @@ -466,10 +465,10 @@ il3945_is_network_packet(struct il_priv *il, struct ieee80211_hdr *header) | |||
| 466 | switch (il->iw_mode) { | 465 | switch (il->iw_mode) { |
| 467 | case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source | BSSID */ | 466 | case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source | BSSID */ |
| 468 | /* packets to our IBSS update information */ | 467 | /* packets to our IBSS update information */ |
| 469 | return ether_addr_equal(header->addr3, il->bssid); | 468 | return ether_addr_equal_64bits(header->addr3, il->bssid); |
| 470 | case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */ | 469 | case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */ |
| 471 | /* packets to our IBSS update information */ | 470 | /* packets to our IBSS update information */ |
| 472 | return ether_addr_equal(header->addr2, il->bssid); | 471 | return ether_addr_equal_64bits(header->addr2, il->bssid); |
| 473 | default: | 472 | default: |
| 474 | return 1; | 473 | return 1; |
| 475 | } | 474 | } |
diff --git a/drivers/net/wireless/iwlegacy/4965-rs.c b/drivers/net/wireless/iwlegacy/4965-rs.c index 3ccbaf791b48..4d5e33259ca8 100644 --- a/drivers/net/wireless/iwlegacy/4965-rs.c +++ b/drivers/net/wireless/iwlegacy/4965-rs.c | |||
| @@ -24,7 +24,6 @@ | |||
| 24 | * | 24 | * |
| 25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
| 26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
| 27 | #include <linux/init.h> | ||
| 28 | #include <linux/skbuff.h> | 27 | #include <linux/skbuff.h> |
| 29 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 30 | #include <net/mac80211.h> | 29 | #include <net/mac80211.h> |
diff --git a/drivers/net/wireless/iwlegacy/4965.c b/drivers/net/wireless/iwlegacy/4965.c index 777a578294bd..fe47db9c20cd 100644 --- a/drivers/net/wireless/iwlegacy/4965.c +++ b/drivers/net/wireless/iwlegacy/4965.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | 26 | ||
| 27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
| 28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
| 29 | #include <linux/init.h> | ||
| 30 | #include <linux/pci.h> | 29 | #include <linux/pci.h> |
| 31 | #include <linux/dma-mapping.h> | 30 | #include <linux/dma-mapping.h> |
| 32 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index a27b14cfeaec..02e8233ccf29 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c | |||
| @@ -33,7 +33,6 @@ | |||
| 33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
| 34 | #include <linux/types.h> | 34 | #include <linux/types.h> |
| 35 | #include <linux/lockdep.h> | 35 | #include <linux/lockdep.h> |
| 36 | #include <linux/init.h> | ||
| 37 | #include <linux/pci.h> | 36 | #include <linux/pci.h> |
| 38 | #include <linux/dma-mapping.h> | 37 | #include <linux/dma-mapping.h> |
| 39 | #include <linux/delay.h> | 38 | #include <linux/delay.h> |
| @@ -3746,10 +3745,10 @@ il_full_rxon_required(struct il_priv *il) | |||
| 3746 | 3745 | ||
| 3747 | /* These items are only settable from the full RXON command */ | 3746 | /* These items are only settable from the full RXON command */ |
| 3748 | CHK(!il_is_associated(il)); | 3747 | CHK(!il_is_associated(il)); |
| 3749 | CHK(!ether_addr_equal(staging->bssid_addr, active->bssid_addr)); | 3748 | CHK(!ether_addr_equal_64bits(staging->bssid_addr, active->bssid_addr)); |
| 3750 | CHK(!ether_addr_equal(staging->node_addr, active->node_addr)); | 3749 | CHK(!ether_addr_equal_64bits(staging->node_addr, active->node_addr)); |
| 3751 | CHK(!ether_addr_equal(staging->wlap_bssid_addr, | 3750 | CHK(!ether_addr_equal_64bits(staging->wlap_bssid_addr, |
| 3752 | active->wlap_bssid_addr)); | 3751 | active->wlap_bssid_addr)); |
| 3753 | CHK_NEQ(staging->dev_type, active->dev_type); | 3752 | CHK_NEQ(staging->dev_type, active->dev_type); |
| 3754 | CHK_NEQ(staging->channel, active->channel); | 3753 | CHK_NEQ(staging->channel, active->channel); |
| 3755 | CHK_NEQ(staging->air_propagation, active->air_propagation); | 3754 | CHK_NEQ(staging->air_propagation, active->air_propagation); |
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h index 23d5f0275ce9..562772d85102 100644 --- a/drivers/net/wireless/iwlwifi/dvm/agn.h +++ b/drivers/net/wireless/iwlwifi/dvm/agn.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/dvm/calib.c b/drivers/net/wireless/iwlwifi/dvm/calib.c index 1b0f0d502568..be1086c87157 100644 --- a/drivers/net/wireless/iwlwifi/dvm/calib.c +++ b/drivers/net/wireless/iwlwifi/dvm/calib.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/dvm/calib.h b/drivers/net/wireless/iwlwifi/dvm/calib.h index cfddde194940..aeae4e80ea40 100644 --- a/drivers/net/wireless/iwlwifi/dvm/calib.h +++ b/drivers/net/wireless/iwlwifi/dvm/calib.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/dvm/commands.h b/drivers/net/wireless/iwlwifi/dvm/commands.h index ebdac909f0cd..751ae1d10b7f 100644 --- a/drivers/net/wireless/iwlwifi/dvm/commands.h +++ b/drivers/net/wireless/iwlwifi/dvm/commands.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c index f69301e505ee..d2fe2596d54e 100644 --- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * | 2 | * |
| 3 | * GPL LICENSE SUMMARY | 3 | * GPL LICENSE SUMMARY |
| 4 | * | 4 | * |
| 5 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 5 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 6 | * | 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of version 2 of the GNU General Public License as | 8 | * it under the terms of version 2 of the GNU General Public License as |
diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h index 7434d9edf3b7..3441f70d0ff9 100644 --- a/drivers/net/wireless/iwlwifi/dvm/dev.h +++ b/drivers/net/wireless/iwlwifi/dvm/dev.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c index 352c6cb7b4f1..7b140e487deb 100644 --- a/drivers/net/wireless/iwlwifi/dvm/devices.c +++ b/drivers/net/wireless/iwlwifi/dvm/devices.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
diff --git a/drivers/net/wireless/iwlwifi/dvm/led.c b/drivers/net/wireless/iwlwifi/dvm/led.c index 33c7e15d24f5..ca4d6692cc4e 100644 --- a/drivers/net/wireless/iwlwifi/dvm/led.c +++ b/drivers/net/wireless/iwlwifi/dvm/led.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
| @@ -27,7 +27,6 @@ | |||
| 27 | 27 | ||
| 28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
| 29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
| 30 | #include <linux/init.h> | ||
| 31 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
| 32 | #include <linux/skbuff.h> | 31 | #include <linux/skbuff.h> |
| 33 | #include <linux/netdevice.h> | 32 | #include <linux/netdevice.h> |
diff --git a/drivers/net/wireless/iwlwifi/dvm/led.h b/drivers/net/wireless/iwlwifi/dvm/led.h index 8749dcfe695f..6a0817d9c4fa 100644 --- a/drivers/net/wireless/iwlwifi/dvm/led.h +++ b/drivers/net/wireless/iwlwifi/dvm/led.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c index 3d5bdc4217a8..576f7ee38ca5 100644 --- a/drivers/net/wireless/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/iwlwifi/dvm/lib.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * | 2 | * |
| 3 | * GPL LICENSE SUMMARY | 3 | * GPL LICENSE SUMMARY |
| 4 | * | 4 | * |
| 5 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 5 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 6 | * | 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of version 2 of the GNU General Public License as | 8 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -29,7 +29,6 @@ | |||
| 29 | #include <linux/etherdevice.h> | 29 | #include <linux/etherdevice.h> |
| 30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
| 31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
| 32 | #include <linux/init.h> | ||
| 33 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
| 34 | #include <net/mac80211.h> | 33 | #include <net/mac80211.h> |
| 35 | 34 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 9f4239d31c08..40eb5e691475 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Portions of this file are derived from the ipw3945 project, as well | 5 | * Portions of this file are derived from the ipw3945 project, as well |
| 6 | * as portions of the ieee80211 subsystem header files. | 6 | * as portions of the ieee80211 subsystem header files. |
| @@ -28,7 +28,6 @@ | |||
| 28 | *****************************************************************************/ | 28 | *****************************************************************************/ |
| 29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
| 30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
| 31 | #include <linux/init.h> | ||
| 32 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
| 33 | #include <linux/dma-mapping.h> | 32 | #include <linux/dma-mapping.h> |
| 34 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index fd9f6cf96cfd..ba1b1ea54252 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Portions of this file are derived from the ipw3945 project, as well | 5 | * Portions of this file are derived from the ipw3945 project, as well |
| 6 | * as portions of the ieee80211 subsystem header files. | 6 | * as portions of the ieee80211 subsystem header files. |
diff --git a/drivers/net/wireless/iwlwifi/dvm/power.c b/drivers/net/wireless/iwlwifi/dvm/power.c index 77cb59712235..b4e61417013a 100644 --- a/drivers/net/wireless/iwlwifi/dvm/power.c +++ b/drivers/net/wireless/iwlwifi/dvm/power.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Portions of this file are derived from the ipw3945 project, as well | 5 | * Portions of this file are derived from the ipw3945 project, as well |
| 6 | * as portions of the ieee80211 subsystem header files. | 6 | * as portions of the ieee80211 subsystem header files. |
| @@ -30,7 +30,6 @@ | |||
| 30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
| 31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
| 32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
| 33 | #include <linux/init.h> | ||
| 34 | #include <net/mac80211.h> | 33 | #include <net/mac80211.h> |
| 35 | #include "iwl-io.h" | 34 | #include "iwl-io.h" |
| 36 | #include "iwl-debug.h" | 35 | #include "iwl-debug.h" |
diff --git a/drivers/net/wireless/iwlwifi/dvm/power.h b/drivers/net/wireless/iwlwifi/dvm/power.h index 7b03e1342d47..570d3a5e4670 100644 --- a/drivers/net/wireless/iwlwifi/dvm/power.h +++ b/drivers/net/wireless/iwlwifi/dvm/power.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Portions of this file are derived from the ipw3945 project, as well | 5 | * Portions of this file are derived from the ipw3945 project, as well |
| 6 | * as portions of the ieee80211 subsystem header files. | 6 | * as portions of the ieee80211 subsystem header files. |
diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c index b647e506564c..0977d93b529d 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/iwlwifi/dvm/rs.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
| @@ -24,7 +24,6 @@ | |||
| 24 | * | 24 | * |
| 25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
| 26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
| 27 | #include <linux/init.h> | ||
| 28 | #include <linux/skbuff.h> | 27 | #include <linux/skbuff.h> |
| 29 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 30 | #include <net/mac80211.h> | 29 | #include <net/mac80211.h> |
diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.h b/drivers/net/wireless/iwlwifi/dvm/rs.h index 41988f4b8a5a..bdd5644a400b 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rs.h +++ b/drivers/net/wireless/iwlwifi/dvm/rs.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
diff --git a/drivers/net/wireless/iwlwifi/dvm/rx.c b/drivers/net/wireless/iwlwifi/dvm/rx.c index d71776dd1e6a..b68bb2f4d2c2 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rx.c +++ b/drivers/net/wireless/iwlwifi/dvm/rx.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Portions of this file are derived from the ipw3945 project, as well | 5 | * Portions of this file are derived from the ipw3945 project, as well |
| 6 | * as portionhelp of the ieee80211 subsystem header files. | 6 | * as portionhelp of the ieee80211 subsystem header files. |
diff --git a/drivers/net/wireless/iwlwifi/dvm/rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c index d7ce2f12a907..503a81e58185 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rxon.c +++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
diff --git a/drivers/net/wireless/iwlwifi/dvm/scan.c b/drivers/net/wireless/iwlwifi/dvm/scan.c index 928f8640a0a7..be98b913ed58 100644 --- a/drivers/net/wireless/iwlwifi/dvm/scan.c +++ b/drivers/net/wireless/iwlwifi/dvm/scan.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * | 2 | * |
| 3 | * GPL LICENSE SUMMARY | 3 | * GPL LICENSE SUMMARY |
| 4 | * | 4 | * |
| 5 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 5 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 6 | * | 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of version 2 of the GNU General Public License as | 8 | * it under the terms of version 2 of the GNU General Public License as |
diff --git a/drivers/net/wireless/iwlwifi/dvm/sta.c b/drivers/net/wireless/iwlwifi/dvm/sta.c index c3c13ce96eb0..c0d070c5df5e 100644 --- a/drivers/net/wireless/iwlwifi/dvm/sta.c +++ b/drivers/net/wireless/iwlwifi/dvm/sta.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Portions of this file are derived from the ipw3945 project, as well | 5 | * Portions of this file are derived from the ipw3945 project, as well |
| 6 | * as portions of the ieee80211 subsystem header files. | 6 | * as portions of the ieee80211 subsystem header files. |
diff --git a/drivers/net/wireless/iwlwifi/dvm/tt.c b/drivers/net/wireless/iwlwifi/dvm/tt.c index fbeee081ee2f..058c5892c427 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tt.c +++ b/drivers/net/wireless/iwlwifi/dvm/tt.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Portions of this file are derived from the ipw3945 project, as well | 5 | * Portions of this file are derived from the ipw3945 project, as well |
| 6 | * as portions of the ieee80211 subsystem header files. | 6 | * as portions of the ieee80211 subsystem header files. |
| @@ -30,7 +30,6 @@ | |||
| 30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
| 31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
| 32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
| 33 | #include <linux/init.h> | ||
| 34 | #include <net/mac80211.h> | 33 | #include <net/mac80211.h> |
| 35 | #include "iwl-io.h" | 34 | #include "iwl-io.h" |
| 36 | #include "iwl-modparams.h" | 35 | #include "iwl-modparams.h" |
diff --git a/drivers/net/wireless/iwlwifi/dvm/tt.h b/drivers/net/wireless/iwlwifi/dvm/tt.h index 9356c4b908ca..507726534b84 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tt.h +++ b/drivers/net/wireless/iwlwifi/dvm/tt.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Portions of this file are derived from the ipw3945 project, as well | 5 | * Portions of this file are derived from the ipw3945 project, as well |
| 6 | * as portions of the ieee80211 subsystem header files. | 6 | * as portions of the ieee80211 subsystem header files. |
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index e12b1a63c484..a6839dfcb82d 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * | 2 | * |
| 3 | * GPL LICENSE SUMMARY | 3 | * GPL LICENSE SUMMARY |
| 4 | * | 4 | * |
| 5 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 5 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 6 | * | 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of version 2 of the GNU General Public License as | 8 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -29,7 +29,6 @@ | |||
| 29 | 29 | ||
| 30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
| 31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
| 32 | #include <linux/init.h> | ||
| 33 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
| 34 | #include <linux/ieee80211.h> | 33 | #include <linux/ieee80211.h> |
| 35 | #include "iwl-io.h" | 34 | #include "iwl-io.h" |
diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c index 63637949a146..f59709a9b79d 100644 --- a/drivers/net/wireless/iwlwifi/dvm/ucode.c +++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * | 2 | * |
| 3 | * GPL LICENSE SUMMARY | 3 | * GPL LICENSE SUMMARY |
| 4 | * | 4 | * |
| 5 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 5 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 6 | * | 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of version 2 of the GNU General Public License as | 8 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -28,7 +28,6 @@ | |||
| 28 | *****************************************************************************/ | 28 | *****************************************************************************/ |
| 29 | 29 | ||
| 30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
| 31 | #include <linux/init.h> | ||
| 32 | 31 | ||
| 33 | #include "iwl-io.h" | 32 | #include "iwl-io.h" |
| 34 | #include "iwl-agn-hw.h" | 33 | #include "iwl-agn-hw.h" |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 0d2afe098afc..854ba84ccb73 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index c727ec7c90a6..3e63323637f3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index ecc01e1a61a1..6674f2c4541c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 8ac305be68f4..8048de90233f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 5fb37724c096..2a59da2ff87a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h index 6d73f943cefa..7f37fb86837b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index e05440ff5cd4..1ced525157dc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index da4eca8b3007..9d325516c42d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
| @@ -198,7 +198,8 @@ | |||
| 198 | CSR_INT_BIT_RF_KILL | \ | 198 | CSR_INT_BIT_RF_KILL | \ |
| 199 | CSR_INT_BIT_SW_RX | \ | 199 | CSR_INT_BIT_SW_RX | \ |
| 200 | CSR_INT_BIT_WAKEUP | \ | 200 | CSR_INT_BIT_WAKEUP | \ |
| 201 | CSR_INT_BIT_ALIVE) | 201 | CSR_INT_BIT_ALIVE | \ |
| 202 | CSR_INT_BIT_RX_PERIODIC) | ||
| 202 | 203 | ||
| 203 | /* interrupt flags in FH (flow handler) (PCI busmaster DMA) */ | 204 | /* interrupt flags in FH (flow handler) (PCI busmaster DMA) */ |
| 204 | #define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */ | 205 | #define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index b2bb32a781dd..a75aac986a23 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Portions of this file are derived from the ipw3945 project. | 5 | * Portions of this file are derived from the ipw3945 project. |
| 6 | * | 6 | * |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/iwlwifi/iwl-devtrace.c index 8f61c717f619..23e7351e02de 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.c +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2009 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 684c416d3493..78bd41bf34b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2009 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 4bebfb58fc7b..c3728163be46 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.h b/drivers/net/wireless/iwlwifi/iwl-drv.h index 429337a2b9a1..592c01e11013 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.h +++ b/drivers/net/wireless/iwlwifi/iwl-drv.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
| @@ -67,7 +67,7 @@ | |||
| 67 | /* for all modules */ | 67 | /* for all modules */ |
| 68 | #define DRV_NAME "iwlwifi" | 68 | #define DRV_NAME "iwlwifi" |
| 69 | #define IWLWIFI_VERSION "in-tree:" | 69 | #define IWLWIFI_VERSION "in-tree:" |
| 70 | #define DRV_COPYRIGHT "Copyright(c) 2003-2013 Intel Corporation" | 70 | #define DRV_COPYRIGHT "Copyright(c) 2003- 2014 Intel Corporation" |
| 71 | #define DRV_AUTHOR "<ilw@linux.intel.com>" | 71 | #define DRV_AUTHOR "<ilw@linux.intel.com>" |
| 72 | 72 | ||
| 73 | 73 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c index 4380c16580eb..c44cf1149648 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h index d73304a23ec2..e3c7deafabe6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c index e5f2e362ab0b..25d0105741db 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h index 8e941f8bd7d6..a6d3bdf82cdd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index 484d318245fb..9564ae173d06 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index 4f95734b2811..88e2d6eb569f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index 8704e3042ca1..5f1493c44097 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index ad8e19a56eca..f98175a0d35b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Portions of this file are derived from the ipw3945 project. | 5 | * Portions of this file are derived from the ipw3945 project. |
| 6 | * | 6 | * |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 63d10ec08dbc..c339c1bed080 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Portions of this file are derived from the ipw3945 project. | 5 | * Portions of this file are derived from the ipw3945 project. |
| 6 | * | 6 | * |
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h index a1f580c0c6c6..0a84ade7edac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-notif-wait.c b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c index 940b8a9d5285..b5bc959b1dfe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-notif-wait.c +++ b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-notif-wait.h b/drivers/net/wireless/iwlwifi/iwl-notif-wait.h index 2e2f1c8c99f9..95af97a6c2cf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-notif-wait.h +++ b/drivers/net/wireless/iwlwifi/iwl-notif-wait.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index a48decc6c68f..1b61cb529948 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h index 3325059c52d4..0c4399aba8c6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h index f50e6c62ebc5..b5be51f3cd3d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h +++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-phy-db.c b/drivers/net/wireless/iwlwifi/iwl-phy-db.c index 1a405ae6a9c5..fa77d63a277a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-phy-db.c +++ b/drivers/net/wireless/iwlwifi/iwl-phy-db.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-phy-db.h b/drivers/net/wireless/iwlwifi/iwl-phy-db.h index ce983af79644..9ee18d0d2d01 100644 --- a/drivers/net/wireless/iwlwifi/iwl-phy-db.h +++ b/drivers/net/wireless/iwlwifi/iwl-phy-db.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index f6412dae2659..d69b0fb0a434 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 0c3647858909..8d1b5ed3502a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
| @@ -622,6 +622,10 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans, | |||
| 622 | { | 622 | { |
| 623 | int ret; | 623 | int ret; |
| 624 | 624 | ||
| 625 | if (unlikely(!(cmd->flags & CMD_SEND_IN_RFKILL) && | ||
| 626 | test_bit(STATUS_RFKILL, &trans->status))) | ||
| 627 | return -ERFKILL; | ||
| 628 | |||
| 625 | if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status))) | 629 | if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status))) |
| 626 | return -EIO; | 630 | return -EIO; |
| 627 | 631 | ||
| @@ -684,9 +688,6 @@ static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue, | |||
| 684 | 688 | ||
| 685 | static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue) | 689 | static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue) |
| 686 | { | 690 | { |
| 687 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) | ||
| 688 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); | ||
| 689 | |||
| 690 | trans->ops->txq_disable(trans, queue); | 691 | trans->ops->txq_disable(trans, queue); |
| 691 | } | 692 | } |
| 692 | 693 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/binding.c b/drivers/net/wireless/iwlwifi/mvm/binding.c index 57d3eed86efa..a1376539d2dc 100644 --- a/drivers/net/wireless/iwlwifi/mvm/binding.c +++ b/drivers/net/wireless/iwlwifi/mvm/binding.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c index d126245c48de..76cde6ce6551 100644 --- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
| @@ -294,9 +294,9 @@ static const __le64 iwl_ci_mask[][3] = { | |||
| 294 | cpu_to_le64(0x0) | 294 | cpu_to_le64(0x0) |
| 295 | }, | 295 | }, |
| 296 | { | 296 | { |
| 297 | cpu_to_le64(0xFE00000000ULL), | 297 | cpu_to_le64(0xFFC0000000ULL), |
| 298 | cpu_to_le64(0x0ULL), | 298 | cpu_to_le64(0x0ULL), |
| 299 | cpu_to_le64(0x0) | 299 | cpu_to_le64(0x0ULL) |
| 300 | }, | 300 | }, |
| 301 | }; | 301 | }; |
| 302 | 302 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h index 4b6d670c3509..036857698565 100644 --- a/drivers/net/wireless/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/iwlwifi/mvm/constants.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 665f87e788d6..f04d2f4d80cd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c index b8667575bc10..0e29cd83a06a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index e8f62a6a1b57..76cdce9edf55 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
| @@ -123,51 +123,31 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf, | |||
| 123 | { | 123 | { |
| 124 | struct iwl_mvm *mvm = file->private_data; | 124 | struct iwl_mvm *mvm = file->private_data; |
| 125 | const struct fw_img *img; | 125 | const struct fw_img *img; |
| 126 | int ofs, len, pos = 0; | 126 | unsigned int ofs, len; |
| 127 | size_t bufsz, ret; | 127 | size_t ret; |
| 128 | char *buf; | ||
| 129 | u8 *ptr; | 128 | u8 *ptr; |
| 130 | 129 | ||
| 131 | if (!mvm->ucode_loaded) | 130 | if (!mvm->ucode_loaded) |
| 132 | return -EINVAL; | 131 | return -EINVAL; |
| 133 | 132 | ||
| 134 | /* default is to dump the entire data segment */ | 133 | /* default is to dump the entire data segment */ |
| 134 | img = &mvm->fw->img[mvm->cur_ucode]; | ||
| 135 | ofs = img->sec[IWL_UCODE_SECTION_DATA].offset; | ||
| 136 | len = img->sec[IWL_UCODE_SECTION_DATA].len; | ||
| 137 | |||
| 135 | if (!mvm->dbgfs_sram_offset && !mvm->dbgfs_sram_len) { | 138 | if (!mvm->dbgfs_sram_offset && !mvm->dbgfs_sram_len) { |
| 136 | img = &mvm->fw->img[mvm->cur_ucode]; | ||
| 137 | ofs = img->sec[IWL_UCODE_SECTION_DATA].offset; | ||
| 138 | len = img->sec[IWL_UCODE_SECTION_DATA].len; | ||
| 139 | } else { | ||
| 140 | ofs = mvm->dbgfs_sram_offset; | 139 | ofs = mvm->dbgfs_sram_offset; |
| 141 | len = mvm->dbgfs_sram_len; | 140 | len = mvm->dbgfs_sram_len; |
| 142 | } | 141 | } |
| 143 | 142 | ||
| 144 | bufsz = len * 4 + 256; | ||
| 145 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
| 146 | if (!buf) | ||
| 147 | return -ENOMEM; | ||
| 148 | |||
| 149 | ptr = kzalloc(len, GFP_KERNEL); | 143 | ptr = kzalloc(len, GFP_KERNEL); |
| 150 | if (!ptr) { | 144 | if (!ptr) |
| 151 | kfree(buf); | ||
| 152 | return -ENOMEM; | 145 | return -ENOMEM; |
| 153 | } | ||
| 154 | |||
| 155 | pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n", len); | ||
| 156 | pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n", ofs); | ||
| 157 | 146 | ||
| 158 | iwl_trans_read_mem_bytes(mvm->trans, ofs, ptr, len); | 147 | iwl_trans_read_mem_bytes(mvm->trans, ofs, ptr, len); |
| 159 | for (ofs = 0; ofs < len; ofs += 16) { | ||
| 160 | pos += scnprintf(buf + pos, bufsz - pos, "0x%.4x ", ofs); | ||
| 161 | hex_dump_to_buffer(ptr + ofs, 16, 16, 1, buf + pos, | ||
| 162 | bufsz - pos, false); | ||
| 163 | pos += strlen(buf + pos); | ||
| 164 | if (bufsz - pos > 0) | ||
| 165 | buf[pos++] = '\n'; | ||
| 166 | } | ||
| 167 | 148 | ||
| 168 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 149 | ret = simple_read_from_buffer(user_buf, count, ppos, ptr, len); |
| 169 | 150 | ||
| 170 | kfree(buf); | ||
| 171 | kfree(ptr); | 151 | kfree(ptr); |
| 172 | 152 | ||
| 173 | return ret; | 153 | return ret; |
| @@ -176,11 +156,24 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf, | |||
| 176 | static ssize_t iwl_dbgfs_sram_write(struct iwl_mvm *mvm, char *buf, | 156 | static ssize_t iwl_dbgfs_sram_write(struct iwl_mvm *mvm, char *buf, |
| 177 | size_t count, loff_t *ppos) | 157 | size_t count, loff_t *ppos) |
| 178 | { | 158 | { |
| 159 | const struct fw_img *img; | ||
| 179 | u32 offset, len; | 160 | u32 offset, len; |
| 161 | u32 img_offset, img_len; | ||
| 162 | |||
| 163 | if (!mvm->ucode_loaded) | ||
| 164 | return -EINVAL; | ||
| 165 | |||
| 166 | img = &mvm->fw->img[mvm->cur_ucode]; | ||
| 167 | img_offset = img->sec[IWL_UCODE_SECTION_DATA].offset; | ||
| 168 | img_len = img->sec[IWL_UCODE_SECTION_DATA].len; | ||
| 180 | 169 | ||
| 181 | if (sscanf(buf, "%x,%x", &offset, &len) == 2) { | 170 | if (sscanf(buf, "%x,%x", &offset, &len) == 2) { |
| 182 | if ((offset & 0x3) || (len & 0x3)) | 171 | if ((offset & 0x3) || (len & 0x3)) |
| 183 | return -EINVAL; | 172 | return -EINVAL; |
| 173 | |||
| 174 | if (offset + len > img_offset + img_len) | ||
| 175 | return -EINVAL; | ||
| 176 | |||
| 184 | mvm->dbgfs_sram_offset = offset; | 177 | mvm->dbgfs_sram_offset = offset; |
| 185 | mvm->dbgfs_sram_len = len; | 178 | mvm->dbgfs_sram_len = len; |
| 186 | } else { | 179 | } else { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.h b/drivers/net/wireless/iwlwifi/mvm/debugfs.h index 85f9f958bfd2..e3a9774af495 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.h +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h index af500996bbf1..1b4e54d416b0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h index 4e7dd8cf87dc..8415ff312d0e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h index 39c3148bdfa8..c405cda1025f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h index cb78e5539357..884c08725308 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h index 532312c7b937..85057219cc43 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h index b3ed59237cba..73cbba7424f2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h index 8c73ba74b6fd..6bbbad453a3b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h index 22864671d66c..b674c2a2b51c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 1c3079714c2b..989d7dbdca6c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index 27ba104a3540..c03d39541f9e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/led.c b/drivers/net/wireless/iwlwifi/mvm/led.c index 2269a9e5cc67..6b4ea6bf8ffe 100644 --- a/drivers/net/wireless/iwlwifi/mvm/led.c +++ b/drivers/net/wireless/iwlwifi/mvm/led.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
| @@ -103,7 +103,7 @@ int iwl_mvm_leds_init(struct iwl_mvm *mvm) | |||
| 103 | return 0; | 103 | return 0; |
| 104 | default: | 104 | default: |
| 105 | return -EINVAL; | 105 | return -EINVAL; |
| 106 | }; | 106 | } |
| 107 | 107 | ||
| 108 | mvm->led.name = kasprintf(GFP_KERNEL, "%s-led", | 108 | mvm->led.name = kasprintf(GFP_KERNEL, "%s-led", |
| 109 | wiphy_name(mvm->hw->wiphy)); | 109 | wiphy_name(mvm->hw->wiphy)); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index fb93961da750..ba723d50939a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
| @@ -69,10 +69,10 @@ | |||
| 69 | #include "mvm.h" | 69 | #include "mvm.h" |
| 70 | 70 | ||
| 71 | const u8 iwl_mvm_ac_to_tx_fifo[] = { | 71 | const u8 iwl_mvm_ac_to_tx_fifo[] = { |
| 72 | IWL_MVM_TX_FIFO_BK, | ||
| 73 | IWL_MVM_TX_FIFO_BE, | ||
| 74 | IWL_MVM_TX_FIFO_VI, | ||
| 75 | IWL_MVM_TX_FIFO_VO, | 72 | IWL_MVM_TX_FIFO_VO, |
| 73 | IWL_MVM_TX_FIFO_VI, | ||
| 74 | IWL_MVM_TX_FIFO_BE, | ||
| 75 | IWL_MVM_TX_FIFO_BK, | ||
| 76 | }; | 76 | }; |
| 77 | 77 | ||
| 78 | struct iwl_mvm_mac_iface_iterator_data { | 78 | struct iwl_mvm_mac_iface_iterator_data { |
| @@ -85,35 +85,15 @@ struct iwl_mvm_mac_iface_iterator_data { | |||
| 85 | bool found_vif; | 85 | bool found_vif; |
| 86 | }; | 86 | }; |
| 87 | 87 | ||
| 88 | static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac, | 88 | static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac, |
| 89 | struct ieee80211_vif *vif) | 89 | struct ieee80211_vif *vif) |
| 90 | { | 90 | { |
| 91 | struct iwl_mvm_mac_iface_iterator_data *data = _data; | 91 | struct iwl_mvm_mac_iface_iterator_data *data = _data; |
| 92 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 92 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
| 93 | u32 ac; | ||
| 94 | 93 | ||
| 95 | /* Iterator may already find the interface being added -- skip it */ | 94 | /* Skip the interface for which we are trying to assign a tsf_id */ |
| 96 | if (vif == data->vif) { | 95 | if (vif == data->vif) |
| 97 | data->found_vif = true; | ||
| 98 | return; | 96 | return; |
| 99 | } | ||
| 100 | |||
| 101 | /* Mark the queues used by the vif */ | ||
| 102 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | ||
| 103 | if (vif->hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE) | ||
| 104 | __set_bit(vif->hw_queue[ac], data->used_hw_queues); | ||
| 105 | |||
| 106 | if (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE) | ||
| 107 | __set_bit(vif->cab_queue, data->used_hw_queues); | ||
| 108 | |||
| 109 | /* | ||
| 110 | * Mark MAC IDs as used by clearing the available bit, and | ||
| 111 | * (below) mark TSFs as used if their existing use is not | ||
| 112 | * compatible with the new interface type. | ||
| 113 | * No locking or atomic bit operations are needed since the | ||
| 114 | * data is on the stack of the caller function. | ||
| 115 | */ | ||
| 116 | __clear_bit(mvmvif->id, data->available_mac_ids); | ||
| 117 | 97 | ||
| 118 | /* | 98 | /* |
| 119 | * The TSF is a hardware/firmware resource, there are 4 and | 99 | * The TSF is a hardware/firmware resource, there are 4 and |
| @@ -135,21 +115,26 @@ static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac, | |||
| 135 | case NL80211_IFTYPE_STATION: | 115 | case NL80211_IFTYPE_STATION: |
| 136 | /* | 116 | /* |
| 137 | * The new interface is client, so if the existing one | 117 | * The new interface is client, so if the existing one |
| 138 | * we're iterating is an AP, the TSF should be used to | 118 | * we're iterating is an AP, and both interfaces have the |
| 119 | * same beacon interval, the same TSF should be used to | ||
| 139 | * avoid drift between the new client and existing AP, | 120 | * avoid drift between the new client and existing AP, |
| 140 | * the existing AP will get drift updates from the new | 121 | * the existing AP will get drift updates from the new |
| 141 | * client context in this case | 122 | * client context in this case |
| 142 | */ | 123 | */ |
| 143 | if (vif->type == NL80211_IFTYPE_AP) { | 124 | if (vif->type == NL80211_IFTYPE_AP) { |
| 144 | if (data->preferred_tsf == NUM_TSF_IDS && | 125 | if (data->preferred_tsf == NUM_TSF_IDS && |
| 145 | test_bit(mvmvif->tsf_id, data->available_tsf_ids)) | 126 | test_bit(mvmvif->tsf_id, data->available_tsf_ids) && |
| 127 | (vif->bss_conf.beacon_int == | ||
| 128 | data->vif->bss_conf.beacon_int)) { | ||
| 146 | data->preferred_tsf = mvmvif->tsf_id; | 129 | data->preferred_tsf = mvmvif->tsf_id; |
| 147 | return; | 130 | return; |
| 131 | } | ||
| 148 | } | 132 | } |
| 149 | break; | 133 | break; |
| 150 | case NL80211_IFTYPE_AP: | 134 | case NL80211_IFTYPE_AP: |
| 151 | /* | 135 | /* |
| 152 | * The new interface is AP/GO, so should get drift | 136 | * The new interface is AP/GO, so in case both interfaces |
| 137 | * have the same beacon interval, it should get drift | ||
| 153 | * updates from an existing client or use the same | 138 | * updates from an existing client or use the same |
| 154 | * TSF as an existing GO. There's no drift between | 139 | * TSF as an existing GO. There's no drift between |
| 155 | * TSFs internally but if they used different TSFs | 140 | * TSFs internally but if they used different TSFs |
| @@ -159,9 +144,12 @@ static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac, | |||
| 159 | if (vif->type == NL80211_IFTYPE_STATION || | 144 | if (vif->type == NL80211_IFTYPE_STATION || |
| 160 | vif->type == NL80211_IFTYPE_AP) { | 145 | vif->type == NL80211_IFTYPE_AP) { |
| 161 | if (data->preferred_tsf == NUM_TSF_IDS && | 146 | if (data->preferred_tsf == NUM_TSF_IDS && |
| 162 | test_bit(mvmvif->tsf_id, data->available_tsf_ids)) | 147 | test_bit(mvmvif->tsf_id, data->available_tsf_ids) && |
| 148 | (vif->bss_conf.beacon_int == | ||
| 149 | data->vif->bss_conf.beacon_int)) { | ||
| 163 | data->preferred_tsf = mvmvif->tsf_id; | 150 | data->preferred_tsf = mvmvif->tsf_id; |
| 164 | return; | 151 | return; |
| 152 | } | ||
| 165 | } | 153 | } |
| 166 | break; | 154 | break; |
| 167 | default: | 155 | default: |
| @@ -187,6 +175,39 @@ static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac, | |||
| 187 | data->preferred_tsf = NUM_TSF_IDS; | 175 | data->preferred_tsf = NUM_TSF_IDS; |
| 188 | } | 176 | } |
| 189 | 177 | ||
| 178 | static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac, | ||
| 179 | struct ieee80211_vif *vif) | ||
| 180 | { | ||
| 181 | struct iwl_mvm_mac_iface_iterator_data *data = _data; | ||
| 182 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 183 | u32 ac; | ||
| 184 | |||
| 185 | /* Iterator may already find the interface being added -- skip it */ | ||
| 186 | if (vif == data->vif) { | ||
| 187 | data->found_vif = true; | ||
| 188 | return; | ||
| 189 | } | ||
| 190 | |||
| 191 | /* Mark the queues used by the vif */ | ||
| 192 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | ||
| 193 | if (vif->hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE) | ||
| 194 | __set_bit(vif->hw_queue[ac], data->used_hw_queues); | ||
| 195 | |||
| 196 | if (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE) | ||
| 197 | __set_bit(vif->cab_queue, data->used_hw_queues); | ||
| 198 | |||
| 199 | /* Mark MAC IDs as used by clearing the available bit, and | ||
| 200 | * (below) mark TSFs as used if their existing use is not | ||
| 201 | * compatible with the new interface type. | ||
| 202 | * No locking or atomic bit operations are needed since the | ||
| 203 | * data is on the stack of the caller function. | ||
| 204 | */ | ||
| 205 | __clear_bit(mvmvif->id, data->available_mac_ids); | ||
| 206 | |||
| 207 | /* find a suitable tsf_id */ | ||
| 208 | iwl_mvm_mac_tsf_id_iter(_data, mac, vif); | ||
| 209 | } | ||
| 210 | |||
| 190 | /* | 211 | /* |
| 191 | * Get the mask of the queus used by the vif | 212 | * Get the mask of the queus used by the vif |
| 192 | */ | 213 | */ |
| @@ -205,6 +226,29 @@ u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm, | |||
| 205 | return qmask; | 226 | return qmask; |
| 206 | } | 227 | } |
| 207 | 228 | ||
| 229 | void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm, | ||
| 230 | struct ieee80211_vif *vif) | ||
| 231 | { | ||
| 232 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 233 | struct iwl_mvm_mac_iface_iterator_data data = { | ||
| 234 | .mvm = mvm, | ||
| 235 | .vif = vif, | ||
| 236 | .available_tsf_ids = { (1 << NUM_TSF_IDS) - 1 }, | ||
| 237 | /* no preference yet */ | ||
| 238 | .preferred_tsf = NUM_TSF_IDS, | ||
| 239 | }; | ||
| 240 | |||
| 241 | ieee80211_iterate_active_interfaces_atomic( | ||
| 242 | mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL, | ||
| 243 | iwl_mvm_mac_tsf_id_iter, &data); | ||
| 244 | |||
| 245 | if (data.preferred_tsf != NUM_TSF_IDS) | ||
| 246 | mvmvif->tsf_id = data.preferred_tsf; | ||
| 247 | else if (!test_bit(mvmvif->tsf_id, data.available_tsf_ids)) | ||
| 248 | mvmvif->tsf_id = find_first_bit(data.available_tsf_ids, | ||
| 249 | NUM_TSF_IDS); | ||
| 250 | } | ||
| 251 | |||
| 208 | static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm, | 252 | static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm, |
| 209 | struct ieee80211_vif *vif) | 253 | struct ieee80211_vif *vif) |
| 210 | { | 254 | { |
| @@ -586,18 +630,23 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm, | |||
| 586 | cpu_to_le32(vif->bss_conf.use_short_slot ? | 630 | cpu_to_le32(vif->bss_conf.use_short_slot ? |
| 587 | MAC_FLG_SHORT_SLOT : 0); | 631 | MAC_FLG_SHORT_SLOT : 0); |
| 588 | 632 | ||
| 589 | for (i = 0; i < AC_NUM; i++) { | 633 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { |
| 590 | cmd->ac[i].cw_min = cpu_to_le16(mvmvif->queue_params[i].cw_min); | 634 | u8 txf = iwl_mvm_ac_to_tx_fifo[i]; |
| 591 | cmd->ac[i].cw_max = cpu_to_le16(mvmvif->queue_params[i].cw_max); | 635 | |
| 592 | cmd->ac[i].aifsn = mvmvif->queue_params[i].aifs; | 636 | cmd->ac[txf].cw_min = |
| 593 | cmd->ac[i].edca_txop = | 637 | cpu_to_le16(mvmvif->queue_params[i].cw_min); |
| 638 | cmd->ac[txf].cw_max = | ||
| 639 | cpu_to_le16(mvmvif->queue_params[i].cw_max); | ||
| 640 | cmd->ac[txf].edca_txop = | ||
| 594 | cpu_to_le16(mvmvif->queue_params[i].txop * 32); | 641 | cpu_to_le16(mvmvif->queue_params[i].txop * 32); |
| 595 | cmd->ac[i].fifos_mask = BIT(iwl_mvm_ac_to_tx_fifo[i]); | 642 | cmd->ac[txf].aifsn = mvmvif->queue_params[i].aifs; |
| 643 | cmd->ac[txf].fifos_mask = BIT(txf); | ||
| 596 | } | 644 | } |
| 597 | 645 | ||
| 598 | /* in AP mode, the MCAST FIFO takes the EDCA params from VO */ | 646 | /* in AP mode, the MCAST FIFO takes the EDCA params from VO */ |
| 599 | if (vif->type == NL80211_IFTYPE_AP) | 647 | if (vif->type == NL80211_IFTYPE_AP) |
| 600 | cmd->ac[AC_VO].fifos_mask |= BIT(IWL_MVM_TX_FIFO_MCAST); | 648 | cmd->ac[IWL_MVM_TX_FIFO_VO].fifos_mask |= |
| 649 | BIT(IWL_MVM_TX_FIFO_MCAST); | ||
| 601 | 650 | ||
| 602 | if (vif->bss_conf.qos) | 651 | if (vif->bss_conf.qos) |
| 603 | cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA); | 652 | cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA); |
| @@ -1007,7 +1056,7 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm, | |||
| 1007 | iwl_mvm_mac_ap_iterator, &data); | 1056 | iwl_mvm_mac_ap_iterator, &data); |
| 1008 | 1057 | ||
| 1009 | if (data.beacon_device_ts) { | 1058 | if (data.beacon_device_ts) { |
| 1010 | u32 rand = (prandom_u32() % (80 - 20)) + 20; | 1059 | u32 rand = (prandom_u32() % (64 - 36)) + 36; |
| 1011 | mvmvif->ap_beacon_time = data.beacon_device_ts + | 1060 | mvmvif->ap_beacon_time = data.beacon_device_ts + |
| 1012 | ieee80211_tu_to_usec(data.beacon_int * rand / | 1061 | ieee80211_tu_to_usec(data.beacon_int * rand / |
| 1013 | 100); | 1062 | 100); |
| @@ -1186,10 +1235,18 @@ int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, | |||
| 1186 | static void iwl_mvm_beacon_loss_iterator(void *_data, u8 *mac, | 1235 | static void iwl_mvm_beacon_loss_iterator(void *_data, u8 *mac, |
| 1187 | struct ieee80211_vif *vif) | 1236 | struct ieee80211_vif *vif) |
| 1188 | { | 1237 | { |
| 1189 | u16 *id = _data; | 1238 | struct iwl_missed_beacons_notif *missed_beacons = _data; |
| 1190 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 1239 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
| 1191 | 1240 | ||
| 1192 | if (mvmvif->id == *id) | 1241 | if (mvmvif->id != (u16)le32_to_cpu(missed_beacons->mac_id)) |
| 1242 | return; | ||
| 1243 | |||
| 1244 | /* | ||
| 1245 | * TODO: the threshold should be adjusted based on latency conditions, | ||
| 1246 | * and/or in case of a CS flow on one of the other AP vifs. | ||
| 1247 | */ | ||
| 1248 | if (le32_to_cpu(missed_beacons->consec_missed_beacons_since_last_rx) > | ||
| 1249 | IWL_MVM_MISSED_BEACONS_THRESHOLD) | ||
| 1193 | ieee80211_beacon_loss(vif); | 1250 | ieee80211_beacon_loss(vif); |
| 1194 | } | 1251 | } |
| 1195 | 1252 | ||
| @@ -1198,12 +1255,19 @@ int iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, | |||
| 1198 | struct iwl_device_cmd *cmd) | 1255 | struct iwl_device_cmd *cmd) |
| 1199 | { | 1256 | { |
| 1200 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 1257 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
| 1201 | struct iwl_missed_beacons_notif *missed_beacons = (void *)pkt->data; | 1258 | struct iwl_missed_beacons_notif *mb = (void *)pkt->data; |
| 1202 | u16 id = (u16)le32_to_cpu(missed_beacons->mac_id); | 1259 | |
| 1260 | IWL_DEBUG_INFO(mvm, | ||
| 1261 | "missed bcn mac_id=%u, consecutive=%u (%u, %u, %u)\n", | ||
| 1262 | le32_to_cpu(mb->mac_id), | ||
| 1263 | le32_to_cpu(mb->consec_missed_beacons), | ||
| 1264 | le32_to_cpu(mb->consec_missed_beacons_since_last_rx), | ||
| 1265 | le32_to_cpu(mb->num_recvd_beacons), | ||
| 1266 | le32_to_cpu(mb->num_expected_beacons)); | ||
| 1203 | 1267 | ||
| 1204 | ieee80211_iterate_active_interfaces_atomic(mvm->hw, | 1268 | ieee80211_iterate_active_interfaces_atomic(mvm->hw, |
| 1205 | IEEE80211_IFACE_ITER_NORMAL, | 1269 | IEEE80211_IFACE_ITER_NORMAL, |
| 1206 | iwl_mvm_beacon_loss_iterator, | 1270 | iwl_mvm_beacon_loss_iterator, |
| 1207 | &id); | 1271 | mb); |
| 1208 | return 0; | 1272 | return 0; |
| 1209 | } | 1273 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 2f5269359dce..b41177eb4888 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
| @@ -262,7 +262,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 262 | mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; | 262 | mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; |
| 263 | 263 | ||
| 264 | /* currently FW API supports only one optional cipher scheme */ | 264 | /* currently FW API supports only one optional cipher scheme */ |
| 265 | if (mvm->fw->cs && mvm->fw->cs->cipher) { | 265 | if (mvm->fw->cs->cipher) { |
| 266 | mvm->hw->n_cipher_schemes = 1; | 266 | mvm->hw->n_cipher_schemes = 1; |
| 267 | mvm->hw->cipher_schemes = mvm->fw->cs; | 267 | mvm->hw->cipher_schemes = mvm->fw->cs; |
| 268 | } | 268 | } |
| @@ -866,6 +866,14 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
| 866 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 866 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
| 867 | int ret; | 867 | int ret; |
| 868 | 868 | ||
| 869 | /* | ||
| 870 | * Re-calculate the tsf id, as the master-slave relations depend on the | ||
| 871 | * beacon interval, which was not known when the station interface was | ||
| 872 | * added. | ||
| 873 | */ | ||
| 874 | if (changes & BSS_CHANGED_ASSOC && bss_conf->assoc) | ||
| 875 | iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif); | ||
| 876 | |||
| 869 | ret = iwl_mvm_mac_ctxt_changed(mvm, vif); | 877 | ret = iwl_mvm_mac_ctxt_changed(mvm, vif); |
| 870 | if (ret) | 878 | if (ret) |
| 871 | IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr); | 879 | IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr); |
| @@ -979,6 +987,13 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, | |||
| 979 | if (ret) | 987 | if (ret) |
| 980 | goto out_unlock; | 988 | goto out_unlock; |
| 981 | 989 | ||
| 990 | /* | ||
| 991 | * Re-calculate the tsf id, as the master-slave relations depend on the | ||
| 992 | * beacon interval, which was not known when the AP interface was added. | ||
| 993 | */ | ||
| 994 | if (vif->type == NL80211_IFTYPE_AP) | ||
| 995 | iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif); | ||
| 996 | |||
| 982 | /* Add the mac context */ | 997 | /* Add the mac context */ |
| 983 | ret = iwl_mvm_mac_ctxt_add(mvm, vif); | 998 | ret = iwl_mvm_mac_ctxt_add(mvm, vif); |
| 984 | if (ret) | 999 | if (ret) |
| @@ -1671,7 +1686,8 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw, | |||
| 1671 | if (WARN_ONCE((phy_ctxt->ref > 1) && | 1686 | if (WARN_ONCE((phy_ctxt->ref > 1) && |
| 1672 | (changed & ~(IEEE80211_CHANCTX_CHANGE_WIDTH | | 1687 | (changed & ~(IEEE80211_CHANCTX_CHANGE_WIDTH | |
| 1673 | IEEE80211_CHANCTX_CHANGE_RX_CHAINS | | 1688 | IEEE80211_CHANCTX_CHANGE_RX_CHAINS | |
| 1674 | IEEE80211_CHANCTX_CHANGE_RADAR)), | 1689 | IEEE80211_CHANCTX_CHANGE_RADAR | |
| 1690 | IEEE80211_CHANCTX_CHANGE_MIN_WIDTH)), | ||
| 1675 | "Cannot change PHY. Ref=%d, changed=0x%X\n", | 1691 | "Cannot change PHY. Ref=%d, changed=0x%X\n", |
| 1676 | phy_ctxt->ref, changed)) | 1692 | phy_ctxt->ref, changed)) |
| 1677 | return; | 1693 | return; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 84edf3649ad2..e4ead86f06d6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
| @@ -81,6 +81,7 @@ | |||
| 81 | #define IWL_MVM_MAX_ADDRESSES 5 | 81 | #define IWL_MVM_MAX_ADDRESSES 5 |
| 82 | /* RSSI offset for WkP */ | 82 | /* RSSI offset for WkP */ |
| 83 | #define IWL_RSSI_OFFSET 50 | 83 | #define IWL_RSSI_OFFSET 50 |
| 84 | #define IWL_MVM_MISSED_BEACONS_THRESHOLD 8 | ||
| 84 | 85 | ||
| 85 | enum iwl_mvm_tx_fifo { | 86 | enum iwl_mvm_tx_fifo { |
| 86 | IWL_MVM_TX_FIFO_BK = 0, | 87 | IWL_MVM_TX_FIFO_BK = 0, |
| @@ -711,6 +712,8 @@ int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, | |||
| 711 | int iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, | 712 | int iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, |
| 712 | struct iwl_rx_cmd_buffer *rxb, | 713 | struct iwl_rx_cmd_buffer *rxb, |
| 713 | struct iwl_device_cmd *cmd); | 714 | struct iwl_device_cmd *cmd); |
| 715 | void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm, | ||
| 716 | struct ieee80211_vif *vif); | ||
| 714 | 717 | ||
| 715 | /* Bindings */ | 718 | /* Bindings */ |
| 716 | int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 719 | int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index 48089b1625ff..c6beb0f842d5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
| @@ -367,16 +367,17 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) | |||
| 367 | break; | 367 | break; |
| 368 | } | 368 | } |
| 369 | 369 | ||
| 370 | if (WARN(section_id >= NVM_NUM_OF_SECTIONS, | ||
| 371 | "Invalid NVM section ID %d\n", section_id)) { | ||
| 372 | ret = -EINVAL; | ||
| 373 | break; | ||
| 374 | } | ||
| 375 | |||
| 370 | temp = kmemdup(file_sec->data, section_size, GFP_KERNEL); | 376 | temp = kmemdup(file_sec->data, section_size, GFP_KERNEL); |
| 371 | if (!temp) { | 377 | if (!temp) { |
| 372 | ret = -ENOMEM; | 378 | ret = -ENOMEM; |
| 373 | break; | 379 | break; |
| 374 | } | 380 | } |
| 375 | if (WARN_ON(section_id >= NVM_NUM_OF_SECTIONS)) { | ||
| 376 | IWL_ERR(mvm, "Invalid NVM section ID\n"); | ||
| 377 | ret = -EINVAL; | ||
| 378 | break; | ||
| 379 | } | ||
| 380 | mvm->nvm_sections[section_id].data = temp; | 381 | mvm->nvm_sections[section_id].data = temp; |
| 381 | mvm->nvm_sections[section_id].length = section_size; | 382 | mvm->nvm_sections[section_id].length = section_size; |
| 382 | 383 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index a362430477a0..552c76a926ed 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
| @@ -665,6 +665,8 @@ static void iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) | |||
| 665 | else | 665 | else |
| 666 | clear_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status); | 666 | clear_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status); |
| 667 | 667 | ||
| 668 | if (state && mvm->cur_ucode != IWL_UCODE_INIT) | ||
| 669 | iwl_trans_stop_device(mvm->trans); | ||
| 668 | wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm)); | 670 | wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm)); |
| 669 | } | 671 | } |
| 670 | 672 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c index a8652ddd6bed..b7268c0b3333 100644 --- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 483ecc67501f..d9eab3b7bb9f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
| @@ -64,7 +64,6 @@ | |||
| 64 | #include <linux/kernel.h> | 64 | #include <linux/kernel.h> |
| 65 | #include <linux/module.h> | 65 | #include <linux/module.h> |
| 66 | #include <linux/slab.h> | 66 | #include <linux/slab.h> |
| 67 | #include <linux/init.h> | ||
| 68 | 67 | ||
| 69 | #include <net/mac80211.h> | 68 | #include <net/mac80211.h> |
| 70 | 69 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/power_legacy.c b/drivers/net/wireless/iwlwifi/mvm/power_legacy.c index 2ce79bad5845..ef712ae5bc62 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power_legacy.c +++ b/drivers/net/wireless/iwlwifi/mvm/power_legacy.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c index 38165eba2a17..ce5db6c4ef7e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/quota.c +++ b/drivers/net/wireless/iwlwifi/mvm/quota.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index d6d28d7b442b..ba078a3322b8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
| @@ -24,7 +24,6 @@ | |||
| 24 | * | 24 | * |
| 25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
| 26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
| 27 | #include <linux/init.h> | ||
| 28 | #include <linux/skbuff.h> | 27 | #include <linux/skbuff.h> |
| 29 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 30 | #include <net/mac80211.h> | 29 | #include <net/mac80211.h> |
| @@ -700,7 +699,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate, | |||
| 700 | u8 num_of_ant = get_num_of_ant_from_rate(ucode_rate); | 699 | u8 num_of_ant = get_num_of_ant_from_rate(ucode_rate); |
| 701 | u8 nss; | 700 | u8 nss; |
| 702 | 701 | ||
| 703 | memset(rate, 0, sizeof(struct rs_rate)); | 702 | memset(rate, 0, sizeof(*rate)); |
| 704 | rate->index = iwl_hwrate_to_plcp_idx(ucode_rate); | 703 | rate->index = iwl_hwrate_to_plcp_idx(ucode_rate); |
| 705 | 704 | ||
| 706 | if (rate->index == IWL_RATE_INVALID) { | 705 | if (rate->index == IWL_RATE_INVALID) { |
| @@ -2121,7 +2120,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm, | |||
| 2121 | tbl->column = RS_COLUMN_LEGACY_ANT_B; | 2120 | tbl->column = RS_COLUMN_LEGACY_ANT_B; |
| 2122 | 2121 | ||
| 2123 | rs_set_expected_tpt_table(lq_sta, tbl); | 2122 | rs_set_expected_tpt_table(lq_sta, tbl); |
| 2124 | rs_fill_lq_cmd(NULL, NULL, lq_sta, rate); | 2123 | rs_fill_lq_cmd(mvm, sta, lq_sta, rate); |
| 2125 | /* TODO restore station should remember the lq cmd */ | 2124 | /* TODO restore station should remember the lq cmd */ |
| 2126 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, init); | 2125 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, init); |
| 2127 | } | 2126 | } |
| @@ -2446,10 +2445,9 @@ static void rs_build_rates_table(struct iwl_mvm *mvm, | |||
| 2446 | struct iwl_lq_cmd *lq_cmd = &lq_sta->lq; | 2445 | struct iwl_lq_cmd *lq_cmd = &lq_sta->lq; |
| 2447 | bool toggle_ant = false; | 2446 | bool toggle_ant = false; |
| 2448 | 2447 | ||
| 2449 | memcpy(&rate, initial_rate, sizeof(struct rs_rate)); | 2448 | memcpy(&rate, initial_rate, sizeof(rate)); |
| 2450 | 2449 | ||
| 2451 | if (mvm) | 2450 | valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); |
| 2452 | valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); | ||
| 2453 | 2451 | ||
| 2454 | if (is_siso(&rate)) { | 2452 | if (is_siso(&rate)) { |
| 2455 | num_rates = RS_INITIAL_SISO_NUM_RATES; | 2453 | num_rates = RS_INITIAL_SISO_NUM_RATES; |
| @@ -2623,7 +2621,7 @@ static void rs_program_fix_rate(struct iwl_mvm *mvm, | |||
| 2623 | struct rs_rate rate; | 2621 | struct rs_rate rate; |
| 2624 | rs_rate_from_ucode_rate(lq_sta->dbg_fixed_rate, | 2622 | rs_rate_from_ucode_rate(lq_sta->dbg_fixed_rate, |
| 2625 | lq_sta->band, &rate); | 2623 | lq_sta->band, &rate); |
| 2626 | rs_fill_lq_cmd(NULL, NULL, lq_sta, &rate); | 2624 | rs_fill_lq_cmd(mvm, NULL, lq_sta, &rate); |
| 2627 | iwl_mvm_send_lq_cmd(lq_sta->drv, &lq_sta->lq, false); | 2625 | iwl_mvm_send_lq_cmd(lq_sta->drv, &lq_sta->lq, false); |
| 2628 | } | 2626 | } |
| 2629 | } | 2627 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index c31aa59728ea..7bc6404f6986 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index 454341cc3b27..a85b60f7e67e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 4ce9bb581144..0e0007960612 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
| @@ -473,13 +473,18 @@ void iwl_mvm_cancel_scan(struct iwl_mvm *mvm) | |||
| 473 | if (mvm->scan_status == IWL_MVM_SCAN_NONE) | 473 | if (mvm->scan_status == IWL_MVM_SCAN_NONE) |
| 474 | return; | 474 | return; |
| 475 | 475 | ||
| 476 | if (iwl_mvm_is_radio_killed(mvm)) { | ||
| 477 | ieee80211_scan_completed(mvm->hw, true); | ||
| 478 | mvm->scan_status = IWL_MVM_SCAN_NONE; | ||
| 479 | return; | ||
| 480 | } | ||
| 481 | |||
| 476 | iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_abort, | 482 | iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_abort, |
| 477 | scan_abort_notif, | 483 | scan_abort_notif, |
| 478 | ARRAY_SIZE(scan_abort_notif), | 484 | ARRAY_SIZE(scan_abort_notif), |
| 479 | iwl_mvm_scan_abort_notif, NULL); | 485 | iwl_mvm_scan_abort_notif, NULL); |
| 480 | 486 | ||
| 481 | ret = iwl_mvm_send_cmd_pdu(mvm, SCAN_ABORT_CMD, | 487 | ret = iwl_mvm_send_cmd_pdu(mvm, SCAN_ABORT_CMD, CMD_SYNC, 0, NULL); |
| 482 | CMD_SYNC | CMD_SEND_IN_RFKILL, 0, NULL); | ||
| 483 | if (ret) { | 488 | if (ret) { |
| 484 | IWL_ERR(mvm, "Couldn't send SCAN_ABORT_CMD: %d\n", ret); | 489 | IWL_ERR(mvm, "Couldn't send SCAN_ABORT_CMD: %d\n", ret); |
| 485 | /* mac80211's state will be cleaned in the fw_restart flow */ | 490 | /* mac80211's state will be cleaned in the fw_restart flow */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sf.c b/drivers/net/wireless/iwlwifi/mvm/sf.c index 97bb3c3e75ce..8401627c0030 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sf.c +++ b/drivers/net/wireless/iwlwifi/mvm/sf.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 0a8af2083ddc..ec1812133235 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h index b34941148a98..4968d0237dc5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/sta.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/testmode.h b/drivers/net/wireless/iwlwifi/mvm/testmode.h index eb74391d91ca..0241665925f7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/testmode.h +++ b/drivers/net/wireless/iwlwifi/mvm/testmode.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index 95ce4b601fef..50f3d7f560bc 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.h b/drivers/net/wireless/iwlwifi/mvm/time-event.h index d9c8d6cfa2db..4a61c8c02372 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.h +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c index a0ec7b3473bd..3afa6b6bf835 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/iwlwifi/mvm/tt.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 735f86da7985..3c575a39987b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index f4aff56a36da..487d61b25359 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 2e97a3995333..e58b8af56c04 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index 674c75b0d002..e851f26fd44c 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Portions of this file are derived from the ipw3945 project, as well | 5 | * Portions of this file are derived from the ipw3945 project, as well |
| 6 | * as portions of the ieee80211 subsystem header files. | 6 | * as portions of the ieee80211 subsystem header files. |
| @@ -262,6 +262,7 @@ iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx) | |||
| 262 | * @rx_page_order: page order for receive buffer size | 262 | * @rx_page_order: page order for receive buffer size |
| 263 | * @wd_timeout: queue watchdog timeout (jiffies) | 263 | * @wd_timeout: queue watchdog timeout (jiffies) |
| 264 | * @reg_lock: protect hw register access | 264 | * @reg_lock: protect hw register access |
| 265 | * @cmd_in_flight: true when we have a host command in flight | ||
| 265 | */ | 266 | */ |
| 266 | struct iwl_trans_pcie { | 267 | struct iwl_trans_pcie { |
| 267 | struct iwl_rxq rxq; | 268 | struct iwl_rxq rxq; |
| @@ -273,7 +274,6 @@ struct iwl_trans_pcie { | |||
| 273 | __le32 *ict_tbl; | 274 | __le32 *ict_tbl; |
| 274 | dma_addr_t ict_tbl_dma; | 275 | dma_addr_t ict_tbl_dma; |
| 275 | int ict_index; | 276 | int ict_index; |
| 276 | u32 inta; | ||
| 277 | bool use_ict; | 277 | bool use_ict; |
| 278 | struct isr_statistics isr_stats; | 278 | struct isr_statistics isr_stats; |
| 279 | 279 | ||
| @@ -311,6 +311,7 @@ struct iwl_trans_pcie { | |||
| 311 | 311 | ||
| 312 | /*protect hw register */ | 312 | /*protect hw register */ |
| 313 | spinlock_t reg_lock; | 313 | spinlock_t reg_lock; |
| 314 | bool cmd_in_flight; | ||
| 314 | }; | 315 | }; |
| 315 | 316 | ||
| 316 | #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ | 317 | #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ |
| @@ -343,7 +344,7 @@ void iwl_pcie_rx_free(struct iwl_trans *trans); | |||
| 343 | /***************************************************** | 344 | /***************************************************** |
| 344 | * ICT - interrupt handling | 345 | * ICT - interrupt handling |
| 345 | ******************************************************/ | 346 | ******************************************************/ |
| 346 | irqreturn_t iwl_pcie_isr_ict(int irq, void *data); | 347 | irqreturn_t iwl_pcie_isr(int irq, void *data); |
| 347 | int iwl_pcie_alloc_ict(struct iwl_trans *trans); | 348 | int iwl_pcie_alloc_ict(struct iwl_trans *trans); |
| 348 | void iwl_pcie_free_ict(struct iwl_trans *trans); | 349 | void iwl_pcie_free_ict(struct iwl_trans *trans); |
| 349 | void iwl_pcie_reset_ict(struct iwl_trans *trans); | 350 | void iwl_pcie_reset_ict(struct iwl_trans *trans); |
| @@ -397,13 +398,17 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans) | |||
| 397 | 398 | ||
| 398 | IWL_DEBUG_ISR(trans, "Enabling interrupts\n"); | 399 | IWL_DEBUG_ISR(trans, "Enabling interrupts\n"); |
| 399 | set_bit(STATUS_INT_ENABLED, &trans->status); | 400 | set_bit(STATUS_INT_ENABLED, &trans->status); |
| 401 | trans_pcie->inta_mask = CSR_INI_SET_MASK; | ||
| 400 | iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); | 402 | iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); |
| 401 | } | 403 | } |
| 402 | 404 | ||
| 403 | static inline void iwl_enable_rfkill_int(struct iwl_trans *trans) | 405 | static inline void iwl_enable_rfkill_int(struct iwl_trans *trans) |
| 404 | { | 406 | { |
| 407 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
| 408 | |||
| 405 | IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n"); | 409 | IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n"); |
| 406 | iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); | 410 | trans_pcie->inta_mask = CSR_INT_BIT_RF_KILL; |
| 411 | iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); | ||
| 407 | } | 412 | } |
| 408 | 413 | ||
| 409 | static inline void iwl_wake_queue(struct iwl_trans *trans, | 414 | static inline void iwl_wake_queue(struct iwl_trans *trans, |
| @@ -456,4 +461,31 @@ static inline bool iwl_is_rfkill_set(struct iwl_trans *trans) | |||
| 456 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); | 461 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); |
| 457 | } | 462 | } |
| 458 | 463 | ||
| 464 | static inline void __iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, | ||
| 465 | u32 reg, u32 mask, u32 value) | ||
| 466 | { | ||
| 467 | u32 v; | ||
| 468 | |||
| 469 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
| 470 | WARN_ON_ONCE(value & ~mask); | ||
| 471 | #endif | ||
| 472 | |||
| 473 | v = iwl_read32(trans, reg); | ||
| 474 | v &= ~mask; | ||
| 475 | v |= value; | ||
| 476 | iwl_write32(trans, reg, v); | ||
| 477 | } | ||
| 478 | |||
| 479 | static inline void __iwl_trans_pcie_clear_bit(struct iwl_trans *trans, | ||
| 480 | u32 reg, u32 mask) | ||
| 481 | { | ||
| 482 | __iwl_trans_pcie_set_bits_mask(trans, reg, mask, 0); | ||
| 483 | } | ||
| 484 | |||
| 485 | static inline void __iwl_trans_pcie_set_bit(struct iwl_trans *trans, | ||
| 486 | u32 reg, u32 mask) | ||
| 487 | { | ||
| 488 | __iwl_trans_pcie_set_bits_mask(trans, reg, mask, mask); | ||
| 489 | } | ||
| 490 | |||
| 459 | #endif /* __iwl_trans_int_pcie_h__ */ | 491 | #endif /* __iwl_trans_int_pcie_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 7aeec5ccefa5..1890ea29c264 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Portions of this file are derived from the ipw3945 project, as well | 5 | * Portions of this file are derived from the ipw3945 project, as well |
| 6 | * as portions of the ieee80211 subsystem header files. | 6 | * as portions of the ieee80211 subsystem header files. |
| @@ -148,10 +148,9 @@ int iwl_pcie_rx_stop(struct iwl_trans *trans) | |||
| 148 | static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, | 148 | static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, |
| 149 | struct iwl_rxq *rxq) | 149 | struct iwl_rxq *rxq) |
| 150 | { | 150 | { |
| 151 | unsigned long flags; | ||
| 152 | u32 reg; | 151 | u32 reg; |
| 153 | 152 | ||
| 154 | spin_lock_irqsave(&rxq->lock, flags); | 153 | spin_lock(&rxq->lock); |
| 155 | 154 | ||
| 156 | if (rxq->need_update == 0) | 155 | if (rxq->need_update == 0) |
| 157 | goto exit_unlock; | 156 | goto exit_unlock; |
| @@ -190,7 +189,7 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, | |||
| 190 | rxq->need_update = 0; | 189 | rxq->need_update = 0; |
| 191 | 190 | ||
| 192 | exit_unlock: | 191 | exit_unlock: |
| 193 | spin_unlock_irqrestore(&rxq->lock, flags); | 192 | spin_unlock(&rxq->lock); |
| 194 | } | 193 | } |
| 195 | 194 | ||
| 196 | /* | 195 | /* |
| @@ -209,7 +208,6 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans) | |||
| 209 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 208 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 210 | struct iwl_rxq *rxq = &trans_pcie->rxq; | 209 | struct iwl_rxq *rxq = &trans_pcie->rxq; |
| 211 | struct iwl_rx_mem_buffer *rxb; | 210 | struct iwl_rx_mem_buffer *rxb; |
| 212 | unsigned long flags; | ||
| 213 | 211 | ||
| 214 | /* | 212 | /* |
| 215 | * If the device isn't enabled - not need to try to add buffers... | 213 | * If the device isn't enabled - not need to try to add buffers... |
| @@ -222,7 +220,7 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans) | |||
| 222 | if (!test_bit(STATUS_DEVICE_ENABLED, &trans->status)) | 220 | if (!test_bit(STATUS_DEVICE_ENABLED, &trans->status)) |
| 223 | return; | 221 | return; |
| 224 | 222 | ||
| 225 | spin_lock_irqsave(&rxq->lock, flags); | 223 | spin_lock(&rxq->lock); |
| 226 | while ((iwl_rxq_space(rxq) > 0) && (rxq->free_count)) { | 224 | while ((iwl_rxq_space(rxq) > 0) && (rxq->free_count)) { |
| 227 | /* The overwritten rxb must be a used one */ | 225 | /* The overwritten rxb must be a used one */ |
| 228 | rxb = rxq->queue[rxq->write]; | 226 | rxb = rxq->queue[rxq->write]; |
| @@ -239,7 +237,7 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans) | |||
| 239 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; | 237 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; |
| 240 | rxq->free_count--; | 238 | rxq->free_count--; |
| 241 | } | 239 | } |
| 242 | spin_unlock_irqrestore(&rxq->lock, flags); | 240 | spin_unlock(&rxq->lock); |
| 243 | /* If the pre-allocated buffer pool is dropping low, schedule to | 241 | /* If the pre-allocated buffer pool is dropping low, schedule to |
| 244 | * refill it */ | 242 | * refill it */ |
| 245 | if (rxq->free_count <= RX_LOW_WATERMARK) | 243 | if (rxq->free_count <= RX_LOW_WATERMARK) |
| @@ -248,9 +246,9 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans) | |||
| 248 | /* If we've added more space for the firmware to place data, tell it. | 246 | /* If we've added more space for the firmware to place data, tell it. |
| 249 | * Increment device's write pointer in multiples of 8. */ | 247 | * Increment device's write pointer in multiples of 8. */ |
| 250 | if (rxq->write_actual != (rxq->write & ~0x7)) { | 248 | if (rxq->write_actual != (rxq->write & ~0x7)) { |
| 251 | spin_lock_irqsave(&rxq->lock, flags); | 249 | spin_lock(&rxq->lock); |
| 252 | rxq->need_update = 1; | 250 | rxq->need_update = 1; |
| 253 | spin_unlock_irqrestore(&rxq->lock, flags); | 251 | spin_unlock(&rxq->lock); |
| 254 | iwl_pcie_rxq_inc_wr_ptr(trans, rxq); | 252 | iwl_pcie_rxq_inc_wr_ptr(trans, rxq); |
| 255 | } | 253 | } |
| 256 | } | 254 | } |
| @@ -270,16 +268,15 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority) | |||
| 270 | struct iwl_rxq *rxq = &trans_pcie->rxq; | 268 | struct iwl_rxq *rxq = &trans_pcie->rxq; |
| 271 | struct iwl_rx_mem_buffer *rxb; | 269 | struct iwl_rx_mem_buffer *rxb; |
| 272 | struct page *page; | 270 | struct page *page; |
| 273 | unsigned long flags; | ||
| 274 | gfp_t gfp_mask = priority; | 271 | gfp_t gfp_mask = priority; |
| 275 | 272 | ||
| 276 | while (1) { | 273 | while (1) { |
| 277 | spin_lock_irqsave(&rxq->lock, flags); | 274 | spin_lock(&rxq->lock); |
| 278 | if (list_empty(&rxq->rx_used)) { | 275 | if (list_empty(&rxq->rx_used)) { |
| 279 | spin_unlock_irqrestore(&rxq->lock, flags); | 276 | spin_unlock(&rxq->lock); |
| 280 | return; | 277 | return; |
| 281 | } | 278 | } |
| 282 | spin_unlock_irqrestore(&rxq->lock, flags); | 279 | spin_unlock(&rxq->lock); |
| 283 | 280 | ||
| 284 | if (rxq->free_count > RX_LOW_WATERMARK) | 281 | if (rxq->free_count > RX_LOW_WATERMARK) |
| 285 | gfp_mask |= __GFP_NOWARN; | 282 | gfp_mask |= __GFP_NOWARN; |
| @@ -308,17 +305,17 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority) | |||
| 308 | return; | 305 | return; |
| 309 | } | 306 | } |
| 310 | 307 | ||
| 311 | spin_lock_irqsave(&rxq->lock, flags); | 308 | spin_lock(&rxq->lock); |
| 312 | 309 | ||
| 313 | if (list_empty(&rxq->rx_used)) { | 310 | if (list_empty(&rxq->rx_used)) { |
| 314 | spin_unlock_irqrestore(&rxq->lock, flags); | 311 | spin_unlock(&rxq->lock); |
| 315 | __free_pages(page, trans_pcie->rx_page_order); | 312 | __free_pages(page, trans_pcie->rx_page_order); |
| 316 | return; | 313 | return; |
| 317 | } | 314 | } |
| 318 | rxb = list_first_entry(&rxq->rx_used, struct iwl_rx_mem_buffer, | 315 | rxb = list_first_entry(&rxq->rx_used, struct iwl_rx_mem_buffer, |
| 319 | list); | 316 | list); |
| 320 | list_del(&rxb->list); | 317 | list_del(&rxb->list); |
| 321 | spin_unlock_irqrestore(&rxq->lock, flags); | 318 | spin_unlock(&rxq->lock); |
| 322 | 319 | ||
| 323 | BUG_ON(rxb->page); | 320 | BUG_ON(rxb->page); |
| 324 | rxb->page = page; | 321 | rxb->page = page; |
| @@ -329,9 +326,9 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority) | |||
| 329 | DMA_FROM_DEVICE); | 326 | DMA_FROM_DEVICE); |
| 330 | if (dma_mapping_error(trans->dev, rxb->page_dma)) { | 327 | if (dma_mapping_error(trans->dev, rxb->page_dma)) { |
| 331 | rxb->page = NULL; | 328 | rxb->page = NULL; |
| 332 | spin_lock_irqsave(&rxq->lock, flags); | 329 | spin_lock(&rxq->lock); |
| 333 | list_add(&rxb->list, &rxq->rx_used); | 330 | list_add(&rxb->list, &rxq->rx_used); |
| 334 | spin_unlock_irqrestore(&rxq->lock, flags); | 331 | spin_unlock(&rxq->lock); |
| 335 | __free_pages(page, trans_pcie->rx_page_order); | 332 | __free_pages(page, trans_pcie->rx_page_order); |
| 336 | return; | 333 | return; |
| 337 | } | 334 | } |
| @@ -340,12 +337,12 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority) | |||
| 340 | /* and also 256 byte aligned! */ | 337 | /* and also 256 byte aligned! */ |
| 341 | BUG_ON(rxb->page_dma & DMA_BIT_MASK(8)); | 338 | BUG_ON(rxb->page_dma & DMA_BIT_MASK(8)); |
| 342 | 339 | ||
| 343 | spin_lock_irqsave(&rxq->lock, flags); | 340 | spin_lock(&rxq->lock); |
| 344 | 341 | ||
| 345 | list_add_tail(&rxb->list, &rxq->rx_free); | 342 | list_add_tail(&rxb->list, &rxq->rx_free); |
| 346 | rxq->free_count++; | 343 | rxq->free_count++; |
| 347 | 344 | ||
| 348 | spin_unlock_irqrestore(&rxq->lock, flags); | 345 | spin_unlock(&rxq->lock); |
| 349 | } | 346 | } |
| 350 | } | 347 | } |
| 351 | 348 | ||
| @@ -379,13 +376,12 @@ static void iwl_pcie_rxq_free_rbs(struct iwl_trans *trans) | |||
| 379 | static void iwl_pcie_rx_replenish(struct iwl_trans *trans) | 376 | static void iwl_pcie_rx_replenish(struct iwl_trans *trans) |
| 380 | { | 377 | { |
| 381 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 378 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 382 | unsigned long flags; | ||
| 383 | 379 | ||
| 384 | iwl_pcie_rxq_alloc_rbs(trans, GFP_KERNEL); | 380 | iwl_pcie_rxq_alloc_rbs(trans, GFP_KERNEL); |
| 385 | 381 | ||
| 386 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 382 | spin_lock(&trans_pcie->irq_lock); |
| 387 | iwl_pcie_rxq_restock(trans); | 383 | iwl_pcie_rxq_restock(trans); |
| 388 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 384 | spin_unlock(&trans_pcie->irq_lock); |
| 389 | } | 385 | } |
| 390 | 386 | ||
| 391 | static void iwl_pcie_rx_replenish_now(struct iwl_trans *trans) | 387 | static void iwl_pcie_rx_replenish_now(struct iwl_trans *trans) |
| @@ -511,7 +507,6 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) | |||
| 511 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 507 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 512 | struct iwl_rxq *rxq = &trans_pcie->rxq; | 508 | struct iwl_rxq *rxq = &trans_pcie->rxq; |
| 513 | int i, err; | 509 | int i, err; |
| 514 | unsigned long flags; | ||
| 515 | 510 | ||
| 516 | if (!rxq->bd) { | 511 | if (!rxq->bd) { |
| 517 | err = iwl_pcie_rx_alloc(trans); | 512 | err = iwl_pcie_rx_alloc(trans); |
| @@ -519,7 +514,7 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) | |||
| 519 | return err; | 514 | return err; |
| 520 | } | 515 | } |
| 521 | 516 | ||
| 522 | spin_lock_irqsave(&rxq->lock, flags); | 517 | spin_lock(&rxq->lock); |
| 523 | 518 | ||
| 524 | INIT_WORK(&trans_pcie->rx_replenish, iwl_pcie_rx_replenish_work); | 519 | INIT_WORK(&trans_pcie->rx_replenish, iwl_pcie_rx_replenish_work); |
| 525 | 520 | ||
| @@ -535,16 +530,16 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) | |||
| 535 | rxq->read = rxq->write = 0; | 530 | rxq->read = rxq->write = 0; |
| 536 | rxq->write_actual = 0; | 531 | rxq->write_actual = 0; |
| 537 | memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts)); | 532 | memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts)); |
| 538 | spin_unlock_irqrestore(&rxq->lock, flags); | 533 | spin_unlock(&rxq->lock); |
| 539 | 534 | ||
| 540 | iwl_pcie_rx_replenish(trans); | 535 | iwl_pcie_rx_replenish(trans); |
| 541 | 536 | ||
| 542 | iwl_pcie_rx_hw_init(trans, rxq); | 537 | iwl_pcie_rx_hw_init(trans, rxq); |
| 543 | 538 | ||
| 544 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 539 | spin_lock(&trans_pcie->irq_lock); |
| 545 | rxq->need_update = 1; | 540 | rxq->need_update = 1; |
| 546 | iwl_pcie_rxq_inc_wr_ptr(trans, rxq); | 541 | iwl_pcie_rxq_inc_wr_ptr(trans, rxq); |
| 547 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 542 | spin_unlock(&trans_pcie->irq_lock); |
| 548 | 543 | ||
| 549 | return 0; | 544 | return 0; |
| 550 | } | 545 | } |
| @@ -553,7 +548,6 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) | |||
| 553 | { | 548 | { |
| 554 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 549 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 555 | struct iwl_rxq *rxq = &trans_pcie->rxq; | 550 | struct iwl_rxq *rxq = &trans_pcie->rxq; |
| 556 | unsigned long flags; | ||
| 557 | 551 | ||
| 558 | /*if rxq->bd is NULL, it means that nothing has been allocated, | 552 | /*if rxq->bd is NULL, it means that nothing has been allocated, |
| 559 | * exit now */ | 553 | * exit now */ |
| @@ -564,9 +558,9 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) | |||
| 564 | 558 | ||
| 565 | cancel_work_sync(&trans_pcie->rx_replenish); | 559 | cancel_work_sync(&trans_pcie->rx_replenish); |
| 566 | 560 | ||
| 567 | spin_lock_irqsave(&rxq->lock, flags); | 561 | spin_lock(&rxq->lock); |
| 568 | iwl_pcie_rxq_free_rbs(trans); | 562 | iwl_pcie_rxq_free_rbs(trans); |
| 569 | spin_unlock_irqrestore(&rxq->lock, flags); | 563 | spin_unlock(&rxq->lock); |
| 570 | 564 | ||
| 571 | dma_free_coherent(trans->dev, sizeof(__le32) * RX_QUEUE_SIZE, | 565 | dma_free_coherent(trans->dev, sizeof(__le32) * RX_QUEUE_SIZE, |
| 572 | rxq->bd, rxq->bd_dma); | 566 | rxq->bd, rxq->bd_dma); |
| @@ -589,7 +583,6 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, | |||
| 589 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 583 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 590 | struct iwl_rxq *rxq = &trans_pcie->rxq; | 584 | struct iwl_rxq *rxq = &trans_pcie->rxq; |
| 591 | struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; | 585 | struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; |
| 592 | unsigned long flags; | ||
| 593 | bool page_stolen = false; | 586 | bool page_stolen = false; |
| 594 | int max_len = PAGE_SIZE << trans_pcie->rx_page_order; | 587 | int max_len = PAGE_SIZE << trans_pcie->rx_page_order; |
| 595 | u32 offset = 0; | 588 | u32 offset = 0; |
| @@ -691,7 +684,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, | |||
| 691 | /* Reuse the page if possible. For notification packets and | 684 | /* Reuse the page if possible. For notification packets and |
| 692 | * SKBs that fail to Rx correctly, add them back into the | 685 | * SKBs that fail to Rx correctly, add them back into the |
| 693 | * rx_free list for reuse later. */ | 686 | * rx_free list for reuse later. */ |
| 694 | spin_lock_irqsave(&rxq->lock, flags); | 687 | spin_lock(&rxq->lock); |
| 695 | if (rxb->page != NULL) { | 688 | if (rxb->page != NULL) { |
| 696 | rxb->page_dma = | 689 | rxb->page_dma = |
| 697 | dma_map_page(trans->dev, rxb->page, 0, | 690 | dma_map_page(trans->dev, rxb->page, 0, |
| @@ -712,7 +705,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, | |||
| 712 | } | 705 | } |
| 713 | } else | 706 | } else |
| 714 | list_add_tail(&rxb->list, &rxq->rx_used); | 707 | list_add_tail(&rxb->list, &rxq->rx_used); |
| 715 | spin_unlock_irqrestore(&rxq->lock, flags); | 708 | spin_unlock(&rxq->lock); |
| 716 | } | 709 | } |
| 717 | 710 | ||
| 718 | /* | 711 | /* |
| @@ -807,6 +800,87 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans) | |||
| 807 | wake_up(&trans_pcie->wait_command_queue); | 800 | wake_up(&trans_pcie->wait_command_queue); |
| 808 | } | 801 | } |
| 809 | 802 | ||
| 803 | static u32 iwl_pcie_int_cause_non_ict(struct iwl_trans *trans) | ||
| 804 | { | ||
| 805 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
| 806 | u32 inta; | ||
| 807 | |||
| 808 | lockdep_assert_held(&trans_pcie->irq_lock); | ||
| 809 | |||
| 810 | trace_iwlwifi_dev_irq(trans->dev); | ||
| 811 | |||
| 812 | /* Discover which interrupts are active/pending */ | ||
| 813 | inta = iwl_read32(trans, CSR_INT); | ||
| 814 | |||
| 815 | /* the thread will service interrupts and re-enable them */ | ||
| 816 | return inta; | ||
| 817 | } | ||
| 818 | |||
| 819 | /* a device (PCI-E) page is 4096 bytes long */ | ||
| 820 | #define ICT_SHIFT 12 | ||
| 821 | #define ICT_SIZE (1 << ICT_SHIFT) | ||
| 822 | #define ICT_COUNT (ICT_SIZE / sizeof(u32)) | ||
| 823 | |||
| 824 | /* interrupt handler using ict table, with this interrupt driver will | ||
| 825 | * stop using INTA register to get device's interrupt, reading this register | ||
| 826 | * is expensive, device will write interrupts in ICT dram table, increment | ||
| 827 | * index then will fire interrupt to driver, driver will OR all ICT table | ||
| 828 | * entries from current index up to table entry with 0 value. the result is | ||
| 829 | * the interrupt we need to service, driver will set the entries back to 0 and | ||
| 830 | * set index. | ||
| 831 | */ | ||
| 832 | static u32 iwl_pcie_int_cause_ict(struct iwl_trans *trans) | ||
| 833 | { | ||
| 834 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
| 835 | u32 inta; | ||
| 836 | u32 val = 0; | ||
| 837 | u32 read; | ||
| 838 | |||
| 839 | trace_iwlwifi_dev_irq(trans->dev); | ||
| 840 | |||
| 841 | /* Ignore interrupt if there's nothing in NIC to service. | ||
| 842 | * This may be due to IRQ shared with another device, | ||
| 843 | * or due to sporadic interrupts thrown from our NIC. */ | ||
| 844 | read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]); | ||
| 845 | trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index, read); | ||
| 846 | if (!read) | ||
| 847 | return 0; | ||
| 848 | |||
| 849 | /* | ||
| 850 | * Collect all entries up to the first 0, starting from ict_index; | ||
| 851 | * note we already read at ict_index. | ||
| 852 | */ | ||
| 853 | do { | ||
| 854 | val |= read; | ||
| 855 | IWL_DEBUG_ISR(trans, "ICT index %d value 0x%08X\n", | ||
| 856 | trans_pcie->ict_index, read); | ||
| 857 | trans_pcie->ict_tbl[trans_pcie->ict_index] = 0; | ||
| 858 | trans_pcie->ict_index = | ||
| 859 | iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT); | ||
| 860 | |||
| 861 | read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]); | ||
| 862 | trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index, | ||
| 863 | read); | ||
| 864 | } while (read); | ||
| 865 | |||
| 866 | /* We should not get this value, just ignore it. */ | ||
| 867 | if (val == 0xffffffff) | ||
| 868 | val = 0; | ||
| 869 | |||
| 870 | /* | ||
| 871 | * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit | ||
| 872 | * (bit 15 before shifting it to 31) to clear when using interrupt | ||
| 873 | * coalescing. fortunately, bits 18 and 19 stay set when this happens | ||
| 874 | * so we use them to decide on the real state of the Rx bit. | ||
| 875 | * In order words, bit 15 is set if bit 18 or bit 19 are set. | ||
| 876 | */ | ||
| 877 | if (val & 0xC0000) | ||
| 878 | val |= 0x8000; | ||
| 879 | |||
| 880 | inta = (0xff & val) | ((0xff00 & val) << 16); | ||
| 881 | return inta; | ||
| 882 | } | ||
| 883 | |||
| 810 | irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) | 884 | irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) |
| 811 | { | 885 | { |
| 812 | struct iwl_trans *trans = dev_id; | 886 | struct iwl_trans *trans = dev_id; |
| @@ -814,12 +888,61 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) | |||
| 814 | struct isr_statistics *isr_stats = &trans_pcie->isr_stats; | 888 | struct isr_statistics *isr_stats = &trans_pcie->isr_stats; |
| 815 | u32 inta = 0; | 889 | u32 inta = 0; |
| 816 | u32 handled = 0; | 890 | u32 handled = 0; |
| 817 | unsigned long flags; | ||
| 818 | u32 i; | 891 | u32 i; |
| 819 | 892 | ||
| 820 | lock_map_acquire(&trans->sync_cmd_lockdep_map); | 893 | lock_map_acquire(&trans->sync_cmd_lockdep_map); |
| 821 | 894 | ||
| 822 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 895 | spin_lock(&trans_pcie->irq_lock); |
| 896 | |||
| 897 | /* dram interrupt table not set yet, | ||
| 898 | * use legacy interrupt. | ||
| 899 | */ | ||
| 900 | if (likely(trans_pcie->use_ict)) | ||
| 901 | inta = iwl_pcie_int_cause_ict(trans); | ||
| 902 | else | ||
| 903 | inta = iwl_pcie_int_cause_non_ict(trans); | ||
| 904 | |||
| 905 | if (iwl_have_debug_level(IWL_DL_ISR)) { | ||
| 906 | IWL_DEBUG_ISR(trans, | ||
| 907 | "ISR inta 0x%08x, enabled 0x%08x(sw), enabled(hw) 0x%08x, fh 0x%08x\n", | ||
| 908 | inta, trans_pcie->inta_mask, | ||
| 909 | iwl_read32(trans, CSR_INT_MASK), | ||
| 910 | iwl_read32(trans, CSR_FH_INT_STATUS)); | ||
| 911 | if (inta & (~trans_pcie->inta_mask)) | ||
| 912 | IWL_DEBUG_ISR(trans, | ||
| 913 | "We got a masked interrupt (0x%08x)\n", | ||
| 914 | inta & (~trans_pcie->inta_mask)); | ||
| 915 | } | ||
| 916 | |||
| 917 | inta &= trans_pcie->inta_mask; | ||
| 918 | |||
| 919 | /* | ||
| 920 | * Ignore interrupt if there's nothing in NIC to service. | ||
| 921 | * This may be due to IRQ shared with another device, | ||
| 922 | * or due to sporadic interrupts thrown from our NIC. | ||
| 923 | */ | ||
| 924 | if (unlikely(!inta)) { | ||
| 925 | IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n"); | ||
| 926 | /* | ||
| 927 | * Re-enable interrupts here since we don't | ||
| 928 | * have anything to service | ||
| 929 | */ | ||
| 930 | if (test_bit(STATUS_INT_ENABLED, &trans->status)) | ||
| 931 | iwl_enable_interrupts(trans); | ||
| 932 | spin_unlock(&trans_pcie->irq_lock); | ||
| 933 | lock_map_release(&trans->sync_cmd_lockdep_map); | ||
| 934 | return IRQ_NONE; | ||
| 935 | } | ||
| 936 | |||
| 937 | if (unlikely(inta == 0xFFFFFFFF || (inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { | ||
| 938 | /* | ||
| 939 | * Hardware disappeared. It might have | ||
| 940 | * already raised an interrupt. | ||
| 941 | */ | ||
| 942 | IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta); | ||
| 943 | spin_unlock(&trans_pcie->irq_lock); | ||
| 944 | goto out; | ||
| 945 | } | ||
| 823 | 946 | ||
| 824 | /* Ack/clear/reset pending uCode interrupts. | 947 | /* Ack/clear/reset pending uCode interrupts. |
| 825 | * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, | 948 | * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, |
| @@ -832,19 +955,13 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) | |||
| 832 | * hardware bugs here by ACKing all the possible interrupts so that | 955 | * hardware bugs here by ACKing all the possible interrupts so that |
| 833 | * interrupt coalescing can still be achieved. | 956 | * interrupt coalescing can still be achieved. |
| 834 | */ | 957 | */ |
| 835 | iwl_write32(trans, CSR_INT, | 958 | iwl_write32(trans, CSR_INT, inta | ~trans_pcie->inta_mask); |
| 836 | trans_pcie->inta | ~trans_pcie->inta_mask); | ||
| 837 | |||
| 838 | inta = trans_pcie->inta; | ||
| 839 | 959 | ||
| 840 | if (iwl_have_debug_level(IWL_DL_ISR)) | 960 | if (iwl_have_debug_level(IWL_DL_ISR)) |
| 841 | IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n", | 961 | IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n", |
| 842 | inta, iwl_read32(trans, CSR_INT_MASK)); | 962 | inta, iwl_read32(trans, CSR_INT_MASK)); |
| 843 | 963 | ||
| 844 | /* saved interrupt in inta variable now we can reset trans_pcie->inta */ | 964 | spin_unlock(&trans_pcie->irq_lock); |
| 845 | trans_pcie->inta = 0; | ||
| 846 | |||
| 847 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | ||
| 848 | 965 | ||
| 849 | /* Now service all interrupt bits discovered above. */ | 966 | /* Now service all interrupt bits discovered above. */ |
| 850 | if (inta & CSR_INT_BIT_HW_ERR) { | 967 | if (inta & CSR_INT_BIT_HW_ERR) { |
| @@ -1019,11 +1136,6 @@ out: | |||
| 1019 | * | 1136 | * |
| 1020 | ******************************************************************************/ | 1137 | ******************************************************************************/ |
| 1021 | 1138 | ||
| 1022 | /* a device (PCI-E) page is 4096 bytes long */ | ||
| 1023 | #define ICT_SHIFT 12 | ||
| 1024 | #define ICT_SIZE (1 << ICT_SHIFT) | ||
| 1025 | #define ICT_COUNT (ICT_SIZE / sizeof(u32)) | ||
| 1026 | |||
| 1027 | /* Free dram table */ | 1139 | /* Free dram table */ |
| 1028 | void iwl_pcie_free_ict(struct iwl_trans *trans) | 1140 | void iwl_pcie_free_ict(struct iwl_trans *trans) |
| 1029 | { | 1141 | { |
| @@ -1048,7 +1160,7 @@ int iwl_pcie_alloc_ict(struct iwl_trans *trans) | |||
| 1048 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1160 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 1049 | 1161 | ||
| 1050 | trans_pcie->ict_tbl = | 1162 | trans_pcie->ict_tbl = |
| 1051 | dma_alloc_coherent(trans->dev, ICT_SIZE, | 1163 | dma_zalloc_coherent(trans->dev, ICT_SIZE, |
| 1052 | &trans_pcie->ict_tbl_dma, | 1164 | &trans_pcie->ict_tbl_dma, |
| 1053 | GFP_KERNEL); | 1165 | GFP_KERNEL); |
| 1054 | if (!trans_pcie->ict_tbl) | 1166 | if (!trans_pcie->ict_tbl) |
| @@ -1060,17 +1172,10 @@ int iwl_pcie_alloc_ict(struct iwl_trans *trans) | |||
| 1060 | return -EINVAL; | 1172 | return -EINVAL; |
| 1061 | } | 1173 | } |
| 1062 | 1174 | ||
| 1063 | IWL_DEBUG_ISR(trans, "ict dma addr %Lx\n", | 1175 | IWL_DEBUG_ISR(trans, "ict dma addr %Lx ict vir addr %p\n", |
| 1064 | (unsigned long long)trans_pcie->ict_tbl_dma); | 1176 | (unsigned long long)trans_pcie->ict_tbl_dma, |
| 1065 | 1177 | trans_pcie->ict_tbl); | |
| 1066 | IWL_DEBUG_ISR(trans, "ict vir addr %p\n", trans_pcie->ict_tbl); | ||
| 1067 | 1178 | ||
| 1068 | /* reset table and index to all 0 */ | ||
| 1069 | memset(trans_pcie->ict_tbl, 0, ICT_SIZE); | ||
| 1070 | trans_pcie->ict_index = 0; | ||
| 1071 | |||
| 1072 | /* add periodic RX interrupt */ | ||
| 1073 | trans_pcie->inta_mask |= CSR_INT_BIT_RX_PERIODIC; | ||
| 1074 | return 0; | 1179 | return 0; |
| 1075 | } | 1180 | } |
| 1076 | 1181 | ||
| @@ -1081,12 +1186,11 @@ void iwl_pcie_reset_ict(struct iwl_trans *trans) | |||
| 1081 | { | 1186 | { |
| 1082 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1187 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 1083 | u32 val; | 1188 | u32 val; |
| 1084 | unsigned long flags; | ||
| 1085 | 1189 | ||
| 1086 | if (!trans_pcie->ict_tbl) | 1190 | if (!trans_pcie->ict_tbl) |
| 1087 | return; | 1191 | return; |
| 1088 | 1192 | ||
| 1089 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 1193 | spin_lock(&trans_pcie->irq_lock); |
| 1090 | iwl_disable_interrupts(trans); | 1194 | iwl_disable_interrupts(trans); |
| 1091 | 1195 | ||
| 1092 | memset(trans_pcie->ict_tbl, 0, ICT_SIZE); | 1196 | memset(trans_pcie->ict_tbl, 0, ICT_SIZE); |
| @@ -1103,120 +1207,26 @@ void iwl_pcie_reset_ict(struct iwl_trans *trans) | |||
| 1103 | trans_pcie->ict_index = 0; | 1207 | trans_pcie->ict_index = 0; |
| 1104 | iwl_write32(trans, CSR_INT, trans_pcie->inta_mask); | 1208 | iwl_write32(trans, CSR_INT, trans_pcie->inta_mask); |
| 1105 | iwl_enable_interrupts(trans); | 1209 | iwl_enable_interrupts(trans); |
| 1106 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 1210 | spin_unlock(&trans_pcie->irq_lock); |
| 1107 | } | 1211 | } |
| 1108 | 1212 | ||
| 1109 | /* Device is going down disable ict interrupt usage */ | 1213 | /* Device is going down disable ict interrupt usage */ |
| 1110 | void iwl_pcie_disable_ict(struct iwl_trans *trans) | 1214 | void iwl_pcie_disable_ict(struct iwl_trans *trans) |
| 1111 | { | 1215 | { |
| 1112 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1216 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 1113 | unsigned long flags; | ||
| 1114 | 1217 | ||
| 1115 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 1218 | spin_lock(&trans_pcie->irq_lock); |
| 1116 | trans_pcie->use_ict = false; | 1219 | trans_pcie->use_ict = false; |
| 1117 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 1220 | spin_unlock(&trans_pcie->irq_lock); |
| 1118 | } | ||
| 1119 | |||
| 1120 | /* legacy (non-ICT) ISR. Assumes that trans_pcie->irq_lock is held */ | ||
| 1121 | static irqreturn_t iwl_pcie_isr(int irq, void *data) | ||
| 1122 | { | ||
| 1123 | struct iwl_trans *trans = data; | ||
| 1124 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
| 1125 | u32 inta, inta_mask; | ||
| 1126 | |||
| 1127 | lockdep_assert_held(&trans_pcie->irq_lock); | ||
| 1128 | |||
| 1129 | trace_iwlwifi_dev_irq(trans->dev); | ||
| 1130 | |||
| 1131 | /* Disable (but don't clear!) interrupts here to avoid | ||
| 1132 | * back-to-back ISRs and sporadic interrupts from our NIC. | ||
| 1133 | * If we have something to service, the irq thread will re-enable ints. | ||
| 1134 | * If we *don't* have something, we'll re-enable before leaving here. */ | ||
| 1135 | inta_mask = iwl_read32(trans, CSR_INT_MASK); | ||
| 1136 | iwl_write32(trans, CSR_INT_MASK, 0x00000000); | ||
| 1137 | |||
| 1138 | /* Discover which interrupts are active/pending */ | ||
| 1139 | inta = iwl_read32(trans, CSR_INT); | ||
| 1140 | |||
| 1141 | if (inta & (~inta_mask)) { | ||
| 1142 | IWL_DEBUG_ISR(trans, | ||
| 1143 | "We got a masked interrupt (0x%08x)...Ack and ignore\n", | ||
| 1144 | inta & (~inta_mask)); | ||
| 1145 | iwl_write32(trans, CSR_INT, inta & (~inta_mask)); | ||
| 1146 | inta &= inta_mask; | ||
| 1147 | } | ||
| 1148 | |||
| 1149 | /* Ignore interrupt if there's nothing in NIC to service. | ||
| 1150 | * This may be due to IRQ shared with another device, | ||
| 1151 | * or due to sporadic interrupts thrown from our NIC. */ | ||
| 1152 | if (!inta) { | ||
| 1153 | IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n"); | ||
| 1154 | /* | ||
| 1155 | * Re-enable interrupts here since we don't have anything to | ||
| 1156 | * service, but only in case the handler won't run. Note that | ||
| 1157 | * the handler can be scheduled because of a previous | ||
| 1158 | * interrupt. | ||
| 1159 | */ | ||
| 1160 | if (test_bit(STATUS_INT_ENABLED, &trans->status) && | ||
| 1161 | !trans_pcie->inta) | ||
| 1162 | iwl_enable_interrupts(trans); | ||
| 1163 | return IRQ_NONE; | ||
| 1164 | } | ||
| 1165 | |||
| 1166 | if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { | ||
| 1167 | /* Hardware disappeared. It might have already raised | ||
| 1168 | * an interrupt */ | ||
| 1169 | IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta); | ||
| 1170 | return IRQ_HANDLED; | ||
| 1171 | } | ||
| 1172 | |||
| 1173 | if (iwl_have_debug_level(IWL_DL_ISR)) | ||
| 1174 | IWL_DEBUG_ISR(trans, | ||
| 1175 | "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", | ||
| 1176 | inta, inta_mask, | ||
| 1177 | iwl_read32(trans, CSR_FH_INT_STATUS)); | ||
| 1178 | |||
| 1179 | trans_pcie->inta |= inta; | ||
| 1180 | /* the thread will service interrupts and re-enable them */ | ||
| 1181 | return IRQ_WAKE_THREAD; | ||
| 1182 | } | 1221 | } |
| 1183 | 1222 | ||
| 1184 | /* interrupt handler using ict table, with this interrupt driver will | 1223 | irqreturn_t iwl_pcie_isr(int irq, void *data) |
| 1185 | * stop using INTA register to get device's interrupt, reading this register | ||
| 1186 | * is expensive, device will write interrupts in ICT dram table, increment | ||
| 1187 | * index then will fire interrupt to driver, driver will OR all ICT table | ||
| 1188 | * entries from current index up to table entry with 0 value. the result is | ||
| 1189 | * the interrupt we need to service, driver will set the entries back to 0 and | ||
| 1190 | * set index. | ||
| 1191 | */ | ||
| 1192 | irqreturn_t iwl_pcie_isr_ict(int irq, void *data) | ||
| 1193 | { | 1224 | { |
| 1194 | struct iwl_trans *trans = data; | 1225 | struct iwl_trans *trans = data; |
| 1195 | struct iwl_trans_pcie *trans_pcie; | ||
| 1196 | u32 inta; | ||
| 1197 | u32 val = 0; | ||
| 1198 | u32 read; | ||
| 1199 | unsigned long flags; | ||
| 1200 | irqreturn_t ret = IRQ_NONE; | ||
| 1201 | 1226 | ||
| 1202 | if (!trans) | 1227 | if (!trans) |
| 1203 | return IRQ_NONE; | 1228 | return IRQ_NONE; |
| 1204 | 1229 | ||
| 1205 | trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
| 1206 | |||
| 1207 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | ||
| 1208 | |||
| 1209 | /* dram interrupt table not set yet, | ||
| 1210 | * use legacy interrupt. | ||
| 1211 | */ | ||
| 1212 | if (unlikely(!trans_pcie->use_ict)) { | ||
| 1213 | ret = iwl_pcie_isr(irq, data); | ||
| 1214 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | ||
| 1215 | return ret; | ||
| 1216 | } | ||
| 1217 | |||
| 1218 | trace_iwlwifi_dev_irq(trans->dev); | ||
| 1219 | |||
| 1220 | /* Disable (but don't clear!) interrupts here to avoid | 1230 | /* Disable (but don't clear!) interrupts here to avoid |
| 1221 | * back-to-back ISRs and sporadic interrupts from our NIC. | 1231 | * back-to-back ISRs and sporadic interrupts from our NIC. |
| 1222 | * If we have something to service, the tasklet will re-enable ints. | 1232 | * If we have something to service, the tasklet will re-enable ints. |
| @@ -1224,73 +1234,5 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data) | |||
| 1224 | */ | 1234 | */ |
| 1225 | iwl_write32(trans, CSR_INT_MASK, 0x00000000); | 1235 | iwl_write32(trans, CSR_INT_MASK, 0x00000000); |
| 1226 | 1236 | ||
| 1227 | /* Ignore interrupt if there's nothing in NIC to service. | 1237 | return IRQ_WAKE_THREAD; |
| 1228 | * This may be due to IRQ shared with another device, | ||
| 1229 | * or due to sporadic interrupts thrown from our NIC. */ | ||
| 1230 | read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]); | ||
| 1231 | trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index, read); | ||
| 1232 | if (!read) { | ||
| 1233 | IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n"); | ||
| 1234 | goto none; | ||
| 1235 | } | ||
| 1236 | |||
| 1237 | /* | ||
| 1238 | * Collect all entries up to the first 0, starting from ict_index; | ||
| 1239 | * note we already read at ict_index. | ||
| 1240 | */ | ||
| 1241 | do { | ||
| 1242 | val |= read; | ||
| 1243 | IWL_DEBUG_ISR(trans, "ICT index %d value 0x%08X\n", | ||
| 1244 | trans_pcie->ict_index, read); | ||
| 1245 | trans_pcie->ict_tbl[trans_pcie->ict_index] = 0; | ||
| 1246 | trans_pcie->ict_index = | ||
| 1247 | iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT); | ||
| 1248 | |||
| 1249 | read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]); | ||
| 1250 | trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index, | ||
| 1251 | read); | ||
| 1252 | } while (read); | ||
| 1253 | |||
| 1254 | /* We should not get this value, just ignore it. */ | ||
| 1255 | if (val == 0xffffffff) | ||
| 1256 | val = 0; | ||
| 1257 | |||
| 1258 | /* | ||
| 1259 | * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit | ||
| 1260 | * (bit 15 before shifting it to 31) to clear when using interrupt | ||
| 1261 | * coalescing. fortunately, bits 18 and 19 stay set when this happens | ||
| 1262 | * so we use them to decide on the real state of the Rx bit. | ||
| 1263 | * In order words, bit 15 is set if bit 18 or bit 19 are set. | ||
| 1264 | */ | ||
| 1265 | if (val & 0xC0000) | ||
| 1266 | val |= 0x8000; | ||
| 1267 | |||
| 1268 | inta = (0xff & val) | ((0xff00 & val) << 16); | ||
| 1269 | IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled(sw) 0x%08x ict 0x%08x\n", | ||
| 1270 | inta, trans_pcie->inta_mask, val); | ||
| 1271 | if (iwl_have_debug_level(IWL_DL_ISR)) | ||
| 1272 | IWL_DEBUG_ISR(trans, "enabled(hw) 0x%08x\n", | ||
| 1273 | iwl_read32(trans, CSR_INT_MASK)); | ||
| 1274 | |||
| 1275 | inta &= trans_pcie->inta_mask; | ||
| 1276 | trans_pcie->inta |= inta; | ||
| 1277 | |||
| 1278 | /* iwl_pcie_tasklet() will service interrupts and re-enable them */ | ||
| 1279 | if (likely(inta)) { | ||
| 1280 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | ||
| 1281 | return IRQ_WAKE_THREAD; | ||
| 1282 | } | ||
| 1283 | |||
| 1284 | ret = IRQ_HANDLED; | ||
| 1285 | |||
| 1286 | none: | ||
| 1287 | /* re-enable interrupts here since we don't have anything to service. | ||
| 1288 | * only Re-enable if disabled by irq. | ||
| 1289 | */ | ||
| 1290 | if (test_bit(STATUS_INT_ENABLED, &trans->status) && | ||
| 1291 | !trans_pcie->inta) | ||
| 1292 | iwl_enable_interrupts(trans); | ||
| 1293 | |||
| 1294 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | ||
| 1295 | return ret; | ||
| 1296 | } | 1238 | } |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index eecd38e3f15f..16f66c1a23de 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | * BSD LICENSE | 31 | * BSD LICENSE |
| 32 | * | 32 | * |
| 33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 34 | * All rights reserved. | 34 | * All rights reserved. |
| 35 | * | 35 | * |
| 36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
| @@ -75,33 +75,6 @@ | |||
| 75 | #include "iwl-agn-hw.h" | 75 | #include "iwl-agn-hw.h" |
| 76 | #include "internal.h" | 76 | #include "internal.h" |
| 77 | 77 | ||
| 78 | static void __iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, | ||
| 79 | u32 reg, u32 mask, u32 value) | ||
| 80 | { | ||
| 81 | u32 v; | ||
| 82 | |||
| 83 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
| 84 | WARN_ON_ONCE(value & ~mask); | ||
| 85 | #endif | ||
| 86 | |||
| 87 | v = iwl_read32(trans, reg); | ||
| 88 | v &= ~mask; | ||
| 89 | v |= value; | ||
| 90 | iwl_write32(trans, reg, v); | ||
| 91 | } | ||
| 92 | |||
| 93 | static inline void __iwl_trans_pcie_clear_bit(struct iwl_trans *trans, | ||
| 94 | u32 reg, u32 mask) | ||
| 95 | { | ||
| 96 | __iwl_trans_pcie_set_bits_mask(trans, reg, mask, 0); | ||
| 97 | } | ||
| 98 | |||
| 99 | static inline void __iwl_trans_pcie_set_bit(struct iwl_trans *trans, | ||
| 100 | u32 reg, u32 mask) | ||
| 101 | { | ||
| 102 | __iwl_trans_pcie_set_bits_mask(trans, reg, mask, mask); | ||
| 103 | } | ||
| 104 | |||
| 105 | static void iwl_pcie_set_pwr(struct iwl_trans *trans, bool vaux) | 78 | static void iwl_pcie_set_pwr(struct iwl_trans *trans, bool vaux) |
| 106 | { | 79 | { |
| 107 | if (vaux && pci_pme_capable(to_pci_dev(trans->dev), PCI_D3cold)) | 80 | if (vaux && pci_pme_capable(to_pci_dev(trans->dev), PCI_D3cold)) |
| @@ -271,13 +244,12 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans) | |||
| 271 | static int iwl_pcie_nic_init(struct iwl_trans *trans) | 244 | static int iwl_pcie_nic_init(struct iwl_trans *trans) |
| 272 | { | 245 | { |
| 273 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 246 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 274 | unsigned long flags; | ||
| 275 | 247 | ||
| 276 | /* nic_init */ | 248 | /* nic_init */ |
| 277 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 249 | spin_lock(&trans_pcie->irq_lock); |
| 278 | iwl_pcie_apm_init(trans); | 250 | iwl_pcie_apm_init(trans); |
| 279 | 251 | ||
| 280 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 252 | spin_unlock(&trans_pcie->irq_lock); |
| 281 | 253 | ||
| 282 | iwl_pcie_set_pwr(trans, false); | 254 | iwl_pcie_set_pwr(trans, false); |
| 283 | 255 | ||
| @@ -635,13 +607,14 @@ static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr) | |||
| 635 | static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | 607 | static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) |
| 636 | { | 608 | { |
| 637 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 609 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 638 | unsigned long flags; | 610 | bool hw_rfkill, was_hw_rfkill; |
| 639 | bool hw_rfkill; | 611 | |
| 612 | was_hw_rfkill = iwl_is_rfkill_set(trans); | ||
| 640 | 613 | ||
| 641 | /* tell the device to stop sending interrupts */ | 614 | /* tell the device to stop sending interrupts */ |
| 642 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 615 | spin_lock(&trans_pcie->irq_lock); |
| 643 | iwl_disable_interrupts(trans); | 616 | iwl_disable_interrupts(trans); |
| 644 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 617 | spin_unlock(&trans_pcie->irq_lock); |
| 645 | 618 | ||
| 646 | /* device going down, Stop using ICT table */ | 619 | /* device going down, Stop using ICT table */ |
| 647 | iwl_pcie_disable_ict(trans); | 620 | iwl_pcie_disable_ict(trans); |
| @@ -673,9 +646,9 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | |||
| 673 | /* Upon stop, the APM issues an interrupt if HW RF kill is set. | 646 | /* Upon stop, the APM issues an interrupt if HW RF kill is set. |
| 674 | * Clean again the interrupt here | 647 | * Clean again the interrupt here |
| 675 | */ | 648 | */ |
| 676 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 649 | spin_lock(&trans_pcie->irq_lock); |
| 677 | iwl_disable_interrupts(trans); | 650 | iwl_disable_interrupts(trans); |
| 678 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 651 | spin_unlock(&trans_pcie->irq_lock); |
| 679 | 652 | ||
| 680 | /* stop and reset the on-board processor */ | 653 | /* stop and reset the on-board processor */ |
| 681 | iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); | 654 | iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); |
| @@ -698,13 +671,20 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | |||
| 698 | * all the interrupts were disabled, in this case we couldn't | 671 | * all the interrupts were disabled, in this case we couldn't |
| 699 | * receive the RF kill interrupt and update the state in the | 672 | * receive the RF kill interrupt and update the state in the |
| 700 | * op_mode. | 673 | * op_mode. |
| 674 | * Don't call the op_mode if the rkfill state hasn't changed. | ||
| 675 | * This allows the op_mode to call stop_device from the rfkill | ||
| 676 | * notification without endless recursion. Under very rare | ||
| 677 | * circumstances, we might have a small recursion if the rfkill | ||
| 678 | * state changed exactly now while we were called from stop_device. | ||
| 679 | * This is very unlikely but can happen and is supported. | ||
| 701 | */ | 680 | */ |
| 702 | hw_rfkill = iwl_is_rfkill_set(trans); | 681 | hw_rfkill = iwl_is_rfkill_set(trans); |
| 703 | if (hw_rfkill) | 682 | if (hw_rfkill) |
| 704 | set_bit(STATUS_RFKILL, &trans->status); | 683 | set_bit(STATUS_RFKILL, &trans->status); |
| 705 | else | 684 | else |
| 706 | clear_bit(STATUS_RFKILL, &trans->status); | 685 | clear_bit(STATUS_RFKILL, &trans->status); |
| 707 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | 686 | if (hw_rfkill != was_hw_rfkill) |
| 687 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | ||
| 708 | } | 688 | } |
| 709 | 689 | ||
| 710 | static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test) | 690 | static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test) |
| @@ -799,7 +779,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) | |||
| 799 | } | 779 | } |
| 800 | 780 | ||
| 801 | /* Reset the entire device */ | 781 | /* Reset the entire device */ |
| 802 | iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | 782 | iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); |
| 803 | 783 | ||
| 804 | usleep_range(10, 15); | 784 | usleep_range(10, 15); |
| 805 | 785 | ||
| @@ -821,18 +801,17 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) | |||
| 821 | static void iwl_trans_pcie_op_mode_leave(struct iwl_trans *trans) | 801 | static void iwl_trans_pcie_op_mode_leave(struct iwl_trans *trans) |
| 822 | { | 802 | { |
| 823 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 803 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 824 | unsigned long flags; | ||
| 825 | 804 | ||
| 826 | /* disable interrupts - don't enable HW RF kill interrupt */ | 805 | /* disable interrupts - don't enable HW RF kill interrupt */ |
| 827 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 806 | spin_lock(&trans_pcie->irq_lock); |
| 828 | iwl_disable_interrupts(trans); | 807 | iwl_disable_interrupts(trans); |
| 829 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 808 | spin_unlock(&trans_pcie->irq_lock); |
| 830 | 809 | ||
| 831 | iwl_pcie_apm_stop(trans); | 810 | iwl_pcie_apm_stop(trans); |
| 832 | 811 | ||
| 833 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 812 | spin_lock(&trans_pcie->irq_lock); |
| 834 | iwl_disable_interrupts(trans); | 813 | iwl_disable_interrupts(trans); |
| 835 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 814 | spin_unlock(&trans_pcie->irq_lock); |
| 836 | 815 | ||
| 837 | iwl_pcie_disable_ict(trans); | 816 | iwl_pcie_disable_ict(trans); |
| 838 | } | 817 | } |
| @@ -932,6 +911,9 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent, | |||
| 932 | 911 | ||
| 933 | spin_lock_irqsave(&trans_pcie->reg_lock, *flags); | 912 | spin_lock_irqsave(&trans_pcie->reg_lock, *flags); |
| 934 | 913 | ||
| 914 | if (trans_pcie->cmd_in_flight) | ||
| 915 | goto out; | ||
| 916 | |||
| 935 | /* this bit wakes up the NIC */ | 917 | /* this bit wakes up the NIC */ |
| 936 | __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, | 918 | __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, |
| 937 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 919 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
| @@ -971,6 +953,7 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent, | |||
| 971 | } | 953 | } |
| 972 | } | 954 | } |
| 973 | 955 | ||
| 956 | out: | ||
| 974 | /* | 957 | /* |
| 975 | * Fool sparse by faking we release the lock - sparse will | 958 | * Fool sparse by faking we release the lock - sparse will |
| 976 | * track nic_access anyway. | 959 | * track nic_access anyway. |
| @@ -992,6 +975,9 @@ static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans, | |||
| 992 | */ | 975 | */ |
| 993 | __acquire(&trans_pcie->reg_lock); | 976 | __acquire(&trans_pcie->reg_lock); |
| 994 | 977 | ||
| 978 | if (trans_pcie->cmd_in_flight) | ||
| 979 | goto out; | ||
| 980 | |||
| 995 | __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, | 981 | __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, |
| 996 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 982 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
| 997 | /* | 983 | /* |
| @@ -1001,6 +987,7 @@ static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans, | |||
| 1001 | * scheduled on different CPUs (after we drop reg_lock). | 987 | * scheduled on different CPUs (after we drop reg_lock). |
| 1002 | */ | 988 | */ |
| 1003 | mmiowb(); | 989 | mmiowb(); |
| 990 | out: | ||
| 1004 | spin_unlock_irqrestore(&trans_pcie->reg_lock, *flags); | 991 | spin_unlock_irqrestore(&trans_pcie->reg_lock, *flags); |
| 1005 | } | 992 | } |
| 1006 | 993 | ||
| @@ -1597,7 +1584,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
| 1597 | if (iwl_pcie_alloc_ict(trans)) | 1584 | if (iwl_pcie_alloc_ict(trans)) |
| 1598 | goto out_free_cmd_pool; | 1585 | goto out_free_cmd_pool; |
| 1599 | 1586 | ||
| 1600 | err = request_threaded_irq(pdev->irq, iwl_pcie_isr_ict, | 1587 | err = request_threaded_irq(pdev->irq, iwl_pcie_isr, |
| 1601 | iwl_pcie_irq_handler, | 1588 | iwl_pcie_irq_handler, |
| 1602 | IRQF_SHARED, DRV_NAME, trans); | 1589 | IRQF_SHARED, DRV_NAME, trans); |
| 1603 | if (err) { | 1590 | if (err) { |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 8df24787c141..3b14fa8abfc7 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Portions of this file are derived from the ipw3945 project, as well | 5 | * Portions of this file are derived from the ipw3945 project, as well |
| 6 | * as portions of the ieee80211 subsystem header files. | 6 | * as portions of the ieee80211 subsystem header files. |
| @@ -737,10 +737,9 @@ int iwl_pcie_tx_stop(struct iwl_trans *trans) | |||
| 737 | { | 737 | { |
| 738 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 738 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 739 | int ch, txq_id, ret; | 739 | int ch, txq_id, ret; |
| 740 | unsigned long flags; | ||
| 741 | 740 | ||
| 742 | /* Turn off all Tx DMA fifos */ | 741 | /* Turn off all Tx DMA fifos */ |
| 743 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 742 | spin_lock(&trans_pcie->irq_lock); |
| 744 | 743 | ||
| 745 | iwl_pcie_txq_set_sched(trans, 0); | 744 | iwl_pcie_txq_set_sched(trans, 0); |
| 746 | 745 | ||
| @@ -757,13 +756,19 @@ int iwl_pcie_tx_stop(struct iwl_trans *trans) | |||
| 757 | iwl_read_direct32(trans, | 756 | iwl_read_direct32(trans, |
| 758 | FH_TSSR_TX_STATUS_REG)); | 757 | FH_TSSR_TX_STATUS_REG)); |
| 759 | } | 758 | } |
| 760 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 759 | spin_unlock(&trans_pcie->irq_lock); |
| 761 | 760 | ||
| 762 | if (!trans_pcie->txq) { | 761 | /* |
| 763 | IWL_WARN(trans, | 762 | * This function can be called before the op_mode disabled the |
| 764 | "Stopping tx queues that aren't allocated...\n"); | 763 | * queues. This happens when we have an rfkill interrupt. |
| 764 | * Since we stop Tx altogether - mark the queues as stopped. | ||
| 765 | */ | ||
| 766 | memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped)); | ||
| 767 | memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used)); | ||
| 768 | |||
| 769 | /* This can happen: start_hw, stop_device */ | ||
| 770 | if (!trans_pcie->txq) | ||
| 765 | return 0; | 771 | return 0; |
| 766 | } | ||
| 767 | 772 | ||
| 768 | /* Unmap DMA from host system and free skb's */ | 773 | /* Unmap DMA from host system and free skb's */ |
| 769 | for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues; | 774 | for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues; |
| @@ -865,7 +870,6 @@ int iwl_pcie_tx_init(struct iwl_trans *trans) | |||
| 865 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 870 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 866 | int ret; | 871 | int ret; |
| 867 | int txq_id, slots_num; | 872 | int txq_id, slots_num; |
| 868 | unsigned long flags; | ||
| 869 | bool alloc = false; | 873 | bool alloc = false; |
| 870 | 874 | ||
| 871 | if (!trans_pcie->txq) { | 875 | if (!trans_pcie->txq) { |
| @@ -875,7 +879,7 @@ int iwl_pcie_tx_init(struct iwl_trans *trans) | |||
| 875 | alloc = true; | 879 | alloc = true; |
| 876 | } | 880 | } |
| 877 | 881 | ||
| 878 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 882 | spin_lock(&trans_pcie->irq_lock); |
| 879 | 883 | ||
| 880 | /* Turn off all Tx DMA fifos */ | 884 | /* Turn off all Tx DMA fifos */ |
| 881 | iwl_write_prph(trans, SCD_TXFACT, 0); | 885 | iwl_write_prph(trans, SCD_TXFACT, 0); |
| @@ -884,7 +888,7 @@ int iwl_pcie_tx_init(struct iwl_trans *trans) | |||
| 884 | iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG, | 888 | iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG, |
| 885 | trans_pcie->kw.dma >> 4); | 889 | trans_pcie->kw.dma >> 4); |
| 886 | 890 | ||
| 887 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 891 | spin_unlock(&trans_pcie->irq_lock); |
| 888 | 892 | ||
| 889 | /* Alloc and init all Tx queues, including the command queue (#4/#9) */ | 893 | /* Alloc and init all Tx queues, including the command queue (#4/#9) */ |
| 890 | for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues; | 894 | for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues; |
| @@ -1003,6 +1007,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx) | |||
| 1003 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1007 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 1004 | struct iwl_txq *txq = &trans_pcie->txq[txq_id]; | 1008 | struct iwl_txq *txq = &trans_pcie->txq[txq_id]; |
| 1005 | struct iwl_queue *q = &txq->q; | 1009 | struct iwl_queue *q = &txq->q; |
| 1010 | unsigned long flags; | ||
| 1006 | int nfreed = 0; | 1011 | int nfreed = 0; |
| 1007 | 1012 | ||
| 1008 | lockdep_assert_held(&txq->lock); | 1013 | lockdep_assert_held(&txq->lock); |
| @@ -1025,6 +1030,16 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx) | |||
| 1025 | } | 1030 | } |
| 1026 | } | 1031 | } |
| 1027 | 1032 | ||
| 1033 | if (q->read_ptr == q->write_ptr) { | ||
| 1034 | spin_lock_irqsave(&trans_pcie->reg_lock, flags); | ||
| 1035 | WARN_ON(!trans_pcie->cmd_in_flight); | ||
| 1036 | trans_pcie->cmd_in_flight = false; | ||
| 1037 | __iwl_trans_pcie_clear_bit(trans, | ||
| 1038 | CSR_GP_CNTRL, | ||
| 1039 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
| 1040 | spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); | ||
| 1041 | } | ||
| 1042 | |||
| 1028 | iwl_pcie_txq_progress(trans_pcie, txq); | 1043 | iwl_pcie_txq_progress(trans_pcie, txq); |
| 1029 | } | 1044 | } |
| 1030 | 1045 | ||
| @@ -1141,8 +1156,15 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) | |||
| 1141 | SCD_TX_STTS_QUEUE_OFFSET(txq_id); | 1156 | SCD_TX_STTS_QUEUE_OFFSET(txq_id); |
| 1142 | static const u32 zero_val[4] = {}; | 1157 | static const u32 zero_val[4] = {}; |
| 1143 | 1158 | ||
| 1159 | /* | ||
| 1160 | * Upon HW Rfkill - we stop the device, and then stop the queues | ||
| 1161 | * in the op_mode. Just for the sake of the simplicity of the op_mode, | ||
| 1162 | * allow the op_mode to call txq_disable after it already called | ||
| 1163 | * stop_device. | ||
| 1164 | */ | ||
| 1144 | if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) { | 1165 | if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) { |
| 1145 | WARN_ONCE(1, "queue %d not used", txq_id); | 1166 | WARN_ONCE(test_bit(STATUS_DEVICE_ENABLED, &trans->status), |
| 1167 | "queue %d not used", txq_id); | ||
| 1146 | return; | 1168 | return; |
| 1147 | } | 1169 | } |
| 1148 | 1170 | ||
| @@ -1176,12 +1198,13 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
| 1176 | struct iwl_queue *q = &txq->q; | 1198 | struct iwl_queue *q = &txq->q; |
| 1177 | struct iwl_device_cmd *out_cmd; | 1199 | struct iwl_device_cmd *out_cmd; |
| 1178 | struct iwl_cmd_meta *out_meta; | 1200 | struct iwl_cmd_meta *out_meta; |
| 1201 | unsigned long flags; | ||
| 1179 | void *dup_buf = NULL; | 1202 | void *dup_buf = NULL; |
| 1180 | dma_addr_t phys_addr; | 1203 | dma_addr_t phys_addr; |
| 1181 | int idx; | 1204 | int idx; |
| 1182 | u16 copy_size, cmd_size, scratch_size; | 1205 | u16 copy_size, cmd_size, scratch_size; |
| 1183 | bool had_nocopy = false; | 1206 | bool had_nocopy = false; |
| 1184 | int i; | 1207 | int i, ret; |
| 1185 | u32 cmd_pos; | 1208 | u32 cmd_pos; |
| 1186 | const u8 *cmddata[IWL_MAX_CMD_TBS_PER_TFD]; | 1209 | const u8 *cmddata[IWL_MAX_CMD_TBS_PER_TFD]; |
| 1187 | u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD]; | 1210 | u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD]; |
| @@ -1379,10 +1402,38 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
| 1379 | if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout) | 1402 | if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout) |
| 1380 | mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout); | 1403 | mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout); |
| 1381 | 1404 | ||
| 1405 | spin_lock_irqsave(&trans_pcie->reg_lock, flags); | ||
| 1406 | |||
| 1407 | /* | ||
| 1408 | * wake up the NIC to make sure that the firmware will see the host | ||
| 1409 | * command - we will let the NIC sleep once all the host commands | ||
| 1410 | * returned. | ||
| 1411 | */ | ||
| 1412 | if (!trans_pcie->cmd_in_flight) { | ||
| 1413 | trans_pcie->cmd_in_flight = true; | ||
| 1414 | __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, | ||
| 1415 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
| 1416 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, | ||
| 1417 | CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, | ||
| 1418 | (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | | ||
| 1419 | CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), | ||
| 1420 | 15000); | ||
| 1421 | if (ret < 0) { | ||
| 1422 | __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, | ||
| 1423 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
| 1424 | spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); | ||
| 1425 | trans_pcie->cmd_in_flight = false; | ||
| 1426 | idx = -EIO; | ||
| 1427 | goto out; | ||
| 1428 | } | ||
| 1429 | } | ||
| 1430 | |||
| 1382 | /* Increment and update queue's write index */ | 1431 | /* Increment and update queue's write index */ |
| 1383 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 1432 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
| 1384 | iwl_pcie_txq_inc_wr_ptr(trans, txq); | 1433 | iwl_pcie_txq_inc_wr_ptr(trans, txq); |
| 1385 | 1434 | ||
| 1435 | spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); | ||
| 1436 | |||
| 1386 | out: | 1437 | out: |
| 1387 | spin_unlock_bh(&txq->lock); | 1438 | spin_unlock_bh(&txq->lock); |
| 1388 | free_dup_buf: | 1439 | free_dup_buf: |
| @@ -1464,7 +1515,6 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans, | |||
| 1464 | } | 1515 | } |
| 1465 | 1516 | ||
| 1466 | #define HOST_COMPLETE_TIMEOUT (2 * HZ) | 1517 | #define HOST_COMPLETE_TIMEOUT (2 * HZ) |
| 1467 | #define COMMAND_POKE_TIMEOUT (HZ / 10) | ||
| 1468 | 1518 | ||
| 1469 | static int iwl_pcie_send_hcmd_async(struct iwl_trans *trans, | 1519 | static int iwl_pcie_send_hcmd_async(struct iwl_trans *trans, |
| 1470 | struct iwl_host_cmd *cmd) | 1520 | struct iwl_host_cmd *cmd) |
| @@ -1492,7 +1542,6 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, | |||
| 1492 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1542 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 1493 | int cmd_idx; | 1543 | int cmd_idx; |
| 1494 | int ret; | 1544 | int ret; |
| 1495 | int timeout = HOST_COMPLETE_TIMEOUT; | ||
| 1496 | 1545 | ||
| 1497 | IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", | 1546 | IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", |
| 1498 | get_cmd_string(trans_pcie, cmd->id)); | 1547 | get_cmd_string(trans_pcie, cmd->id)); |
| @@ -1516,29 +1565,10 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, | |||
| 1516 | return ret; | 1565 | return ret; |
| 1517 | } | 1566 | } |
| 1518 | 1567 | ||
| 1519 | while (timeout > 0) { | 1568 | ret = wait_event_timeout(trans_pcie->wait_command_queue, |
| 1520 | unsigned long flags; | 1569 | !test_bit(STATUS_SYNC_HCMD_ACTIVE, |
| 1521 | 1570 | &trans->status), | |
| 1522 | timeout -= COMMAND_POKE_TIMEOUT; | 1571 | HOST_COMPLETE_TIMEOUT); |
| 1523 | ret = wait_event_timeout(trans_pcie->wait_command_queue, | ||
| 1524 | !test_bit(STATUS_SYNC_HCMD_ACTIVE, | ||
| 1525 | &trans->status), | ||
| 1526 | COMMAND_POKE_TIMEOUT); | ||
| 1527 | if (ret) | ||
| 1528 | break; | ||
| 1529 | /* poke the device - it may have lost the command */ | ||
| 1530 | if (iwl_trans_grab_nic_access(trans, true, &flags)) { | ||
| 1531 | iwl_trans_release_nic_access(trans, &flags); | ||
| 1532 | IWL_DEBUG_INFO(trans, | ||
| 1533 | "Tried to wake NIC for command %s\n", | ||
| 1534 | get_cmd_string(trans_pcie, cmd->id)); | ||
| 1535 | } else { | ||
| 1536 | IWL_ERR(trans, "Failed to poke NIC for command %s\n", | ||
| 1537 | get_cmd_string(trans_pcie, cmd->id)); | ||
| 1538 | break; | ||
| 1539 | } | ||
| 1540 | } | ||
| 1541 | |||
| 1542 | if (!ret) { | 1572 | if (!ret) { |
| 1543 | struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; | 1573 | struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; |
| 1544 | struct iwl_queue *q = &txq->q; | 1574 | struct iwl_queue *q = &txq->q; |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index b994679abce0..e7c81abf108e 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
| @@ -563,14 +563,7 @@ static void mwifiex_reg_notifier(struct wiphy *wiphy, | |||
| 563 | memcpy(adapter->country_code, request->alpha2, | 563 | memcpy(adapter->country_code, request->alpha2, |
| 564 | sizeof(request->alpha2)); | 564 | sizeof(request->alpha2)); |
| 565 | mwifiex_send_domain_info_cmd_fw(wiphy); | 565 | mwifiex_send_domain_info_cmd_fw(wiphy); |
| 566 | 566 | mwifiex_dnld_txpwr_table(priv); | |
| 567 | if (adapter->dt_node) { | ||
| 568 | char txpwr[] = {"marvell,00_txpwrlimit"}; | ||
| 569 | |||
| 570 | memcpy(&txpwr[8], adapter->country_code, 2); | ||
| 571 | mwifiex_dnld_dt_cfgdata(priv, adapter->dt_node, | ||
| 572 | txpwr); | ||
| 573 | } | ||
| 574 | } | 567 | } |
| 575 | } | 568 | } |
| 576 | 569 | ||
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 6bf58aba51d2..2d6f5e1721cf 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
| @@ -749,7 +749,7 @@ static struct net_device_stats *mwifiex_get_stats(struct net_device *dev) | |||
| 749 | static u16 | 749 | static u16 |
| 750 | mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb) | 750 | mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb) |
| 751 | { | 751 | { |
| 752 | skb->priority = cfg80211_classify8021d(skb); | 752 | skb->priority = cfg80211_classify8021d(skb, NULL); |
| 753 | return mwifiex_1d_to_wmm_queue[skb->priority]; | 753 | return mwifiex_1d_to_wmm_queue[skb->priority]; |
| 754 | } | 754 | } |
| 755 | 755 | ||
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index ab3416449bfd..d8ad554ce39f 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
| @@ -1155,6 +1155,7 @@ void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer, | |||
| 1155 | int mwifiex_11h_handle_event_chanswann(struct mwifiex_private *priv); | 1155 | int mwifiex_11h_handle_event_chanswann(struct mwifiex_private *priv); |
| 1156 | int mwifiex_dnld_dt_cfgdata(struct mwifiex_private *priv, | 1156 | int mwifiex_dnld_dt_cfgdata(struct mwifiex_private *priv, |
| 1157 | struct device_node *node, const char *prefix); | 1157 | struct device_node *node, const char *prefix); |
| 1158 | void mwifiex_dnld_txpwr_table(struct mwifiex_private *priv); | ||
| 1158 | 1159 | ||
| 1159 | extern const struct ethtool_ops mwifiex_ethtool_ops; | 1160 | extern const struct ethtool_ops mwifiex_ethtool_ops; |
| 1160 | 1161 | ||
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 9c2404cd755f..9208a8816b80 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
| @@ -1170,8 +1170,9 @@ int mwifiex_dnld_dt_cfgdata(struct mwifiex_private *priv, | |||
| 1170 | strncmp(prop->name, prefix, len)) | 1170 | strncmp(prop->name, prefix, len)) |
| 1171 | continue; | 1171 | continue; |
| 1172 | 1172 | ||
| 1173 | /* property header is 6 bytes */ | 1173 | /* property header is 6 bytes, data must fit in cmd buffer */ |
| 1174 | if (prop && prop->value && prop->length > 6) { | 1174 | if (prop && prop->value && prop->length > 6 && |
| 1175 | prop->length <= MWIFIEX_SIZE_OF_CMD_BUFFER - S_DS_GEN) { | ||
| 1175 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_CFG_DATA, | 1176 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_CFG_DATA, |
| 1176 | HostCmd_ACT_GEN_SET, 0, | 1177 | HostCmd_ACT_GEN_SET, 0, |
| 1177 | prop); | 1178 | prop); |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 3edc92fad319..c5cb2ed19ec2 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
| @@ -184,6 +184,16 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, | |||
| 184 | return mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc); | 184 | return mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc); |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | void mwifiex_dnld_txpwr_table(struct mwifiex_private *priv) | ||
| 188 | { | ||
| 189 | if (priv->adapter->dt_node) { | ||
| 190 | char txpwr[] = {"marvell,00_txpwrlimit"}; | ||
| 191 | |||
| 192 | memcpy(&txpwr[8], priv->adapter->country_code, 2); | ||
| 193 | mwifiex_dnld_dt_cfgdata(priv, priv->adapter->dt_node, txpwr); | ||
| 194 | } | ||
| 195 | } | ||
| 196 | |||
| 187 | static int mwifiex_process_country_ie(struct mwifiex_private *priv, | 197 | static int mwifiex_process_country_ie(struct mwifiex_private *priv, |
| 188 | struct cfg80211_bss *bss) | 198 | struct cfg80211_bss *bss) |
| 189 | { | 199 | { |
| @@ -234,12 +244,7 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv, | |||
| 234 | return -1; | 244 | return -1; |
| 235 | } | 245 | } |
| 236 | 246 | ||
| 237 | if (priv->adapter->dt_node) { | 247 | mwifiex_dnld_txpwr_table(priv); |
| 238 | char txpwr[] = {"marvell,00_txpwrlimit"}; | ||
| 239 | |||
| 240 | memcpy(&txpwr[8], priv->adapter->country_code, 2); | ||
| 241 | mwifiex_dnld_dt_cfgdata(priv, priv->adapter->dt_node, txpwr); | ||
| 242 | } | ||
| 243 | 248 | ||
| 244 | return 0; | 249 | return 0; |
| 245 | } | 250 | } |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index b953ad621e0b..63dbde5c3713 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | * warranty of any kind, whether express or implied. | 9 | * warranty of any kind, whether express or implied. |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/init.h> | ||
| 13 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
| 14 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 15 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| @@ -1258,7 +1257,7 @@ mwl8k_capture_bssid(struct mwl8k_priv *priv, struct ieee80211_hdr *wh) | |||
| 1258 | { | 1257 | { |
| 1259 | return priv->capture_beacon && | 1258 | return priv->capture_beacon && |
| 1260 | ieee80211_is_beacon(wh->frame_control) && | 1259 | ieee80211_is_beacon(wh->frame_control) && |
| 1261 | ether_addr_equal(wh->addr3, priv->capture_bssid); | 1260 | ether_addr_equal_64bits(wh->addr3, priv->capture_bssid); |
| 1262 | } | 1261 | } |
| 1263 | 1262 | ||
| 1264 | static inline void mwl8k_save_beacon(struct ieee80211_hw *hw, | 1263 | static inline void mwl8k_save_beacon(struct ieee80211_hw *hw, |
diff --git a/drivers/net/wireless/orinoco/hermes.c b/drivers/net/wireless/orinoco/hermes.c index 75c15bc7b34c..43790fbea0e0 100644 --- a/drivers/net/wireless/orinoco/hermes.c +++ b/drivers/net/wireless/orinoco/hermes.c | |||
| @@ -40,7 +40,6 @@ | |||
| 40 | 40 | ||
| 41 | #include <linux/module.h> | 41 | #include <linux/module.h> |
| 42 | #include <linux/kernel.h> | 42 | #include <linux/kernel.h> |
| 43 | #include <linux/init.h> | ||
| 44 | #include <linux/delay.h> | 43 | #include <linux/delay.h> |
| 45 | 44 | ||
| 46 | #include "hermes.h" | 45 | #include "hermes.h" |
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c index d21d95939316..c0a27377d9e2 100644 --- a/drivers/net/wireless/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/orinoco/orinoco_cs.c | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | 15 | ||
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
| 20 | #include <pcmcia/cistpl.h> | 19 | #include <pcmcia/cistpl.h> |
| 21 | #include <pcmcia/cisreg.h> | 20 | #include <pcmcia/cisreg.h> |
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c index bdfe637953f4..f9805c9353d2 100644 --- a/drivers/net/wireless/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/orinoco/orinoco_usb.c | |||
| @@ -52,7 +52,6 @@ | |||
| 52 | #include <linux/signal.h> | 52 | #include <linux/signal.h> |
| 53 | #include <linux/errno.h> | 53 | #include <linux/errno.h> |
| 54 | #include <linux/poll.h> | 54 | #include <linux/poll.h> |
| 55 | #include <linux/init.h> | ||
| 56 | #include <linux/slab.h> | 55 | #include <linux/slab.h> |
| 57 | #include <linux/fcntl.h> | 56 | #include <linux/fcntl.h> |
| 58 | #include <linux/spinlock.h> | 57 | #include <linux/spinlock.h> |
diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c index e2264bc12ebf..b60048c95e0a 100644 --- a/drivers/net/wireless/orinoco/spectrum_cs.c +++ b/drivers/net/wireless/orinoco/spectrum_cs.c | |||
| @@ -23,7 +23,6 @@ | |||
| 23 | 23 | ||
| 24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
| 25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
| 26 | #include <linux/init.h> | ||
| 27 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
| 28 | #include <pcmcia/cistpl.h> | 27 | #include <pcmcia/cistpl.h> |
| 29 | #include <pcmcia/cisreg.h> | 28 | #include <pcmcia/cisreg.h> |
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index d43e3740e45d..0fe67d2da208 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | * published by the Free Software Foundation. | 16 | * published by the Free Software Foundation. |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/firmware.h> | 19 | #include <linux/firmware.h> |
| 21 | #include <linux/etherdevice.h> | 20 | #include <linux/etherdevice.h> |
| 22 | #include <linux/sort.h> | 21 | #include <linux/sort.h> |
diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c index b3879fbf5368..bc065e8e348b 100644 --- a/drivers/net/wireless/p54/fwio.c +++ b/drivers/net/wireless/p54/fwio.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | * published by the Free Software Foundation. | 16 | * published by the Free Software Foundation. |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
| 21 | #include <linux/firmware.h> | 20 | #include <linux/firmware.h> |
| 22 | #include <linux/etherdevice.h> | 21 | #include <linux/etherdevice.h> |
diff --git a/drivers/net/wireless/p54/led.c b/drivers/net/wireless/p54/led.c index 3837e1eec5f4..1f6fd5ff5531 100644 --- a/drivers/net/wireless/p54/led.c +++ b/drivers/net/wireless/p54/led.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | * published by the Free Software Foundation. | 16 | * published by the Free Software Foundation. |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/firmware.h> | 19 | #include <linux/firmware.h> |
| 21 | #include <linux/etherdevice.h> | 20 | #include <linux/etherdevice.h> |
| 22 | 21 | ||
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 067e6f2fd050..80d93cba5150 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | * published by the Free Software Foundation. | 16 | * published by the Free Software Foundation. |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
| 21 | #include <linux/firmware.h> | 20 | #include <linux/firmware.h> |
| 22 | #include <linux/etherdevice.h> | 21 | #include <linux/etherdevice.h> |
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index f9a07b0d83ac..d411de409050 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | * published by the Free Software Foundation. | 13 | * published by the Free Software Foundation. |
| 14 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | #include <linux/init.h> | ||
| 17 | #include <linux/pci.h> | 16 | #include <linux/pci.h> |
| 18 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 19 | #include <linux/firmware.h> | 18 | #include <linux/firmware.h> |
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index e328d3058c41..6e635cfa24c8 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
| 13 | */ | 13 | */ |
| 14 | 14 | ||
| 15 | #include <linux/init.h> | ||
| 16 | #include <linux/usb.h> | 15 | #include <linux/usb.h> |
| 17 | #include <linux/pci.h> | 16 | #include <linux/pci.h> |
| 18 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index f95de0d16216..9c96831c0b5c 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c | |||
| @@ -17,7 +17,6 @@ | |||
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <linux/export.h> | 19 | #include <linux/export.h> |
| 20 | #include <linux/init.h> | ||
| 21 | #include <linux/firmware.h> | 20 | #include <linux/firmware.h> |
| 22 | #include <linux/etherdevice.h> | 21 | #include <linux/etherdevice.h> |
| 23 | #include <asm/div64.h> | 22 | #include <asm/div64.h> |
| @@ -308,7 +307,7 @@ static void p54_pspoll_workaround(struct p54_common *priv, struct sk_buff *skb) | |||
| 308 | return; | 307 | return; |
| 309 | 308 | ||
| 310 | /* only consider beacons from the associated BSSID */ | 309 | /* only consider beacons from the associated BSSID */ |
| 311 | if (!ether_addr_equal(hdr->addr3, priv->bssid)) | 310 | if (!ether_addr_equal_64bits(hdr->addr3, priv->bssid)) |
| 312 | return; | 311 | return; |
| 313 | 312 | ||
| 314 | tim = p54_find_ie(skb, WLAN_EID_TIM); | 313 | tim = p54_find_ie(skb, WLAN_EID_TIM); |
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index c3cdda1252de..5028557aa18a 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | // #define VERBOSE // more; success messages | 26 | // #define VERBOSE // more; success messages |
| 27 | 27 | ||
| 28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
| 29 | #include <linux/init.h> | ||
| 30 | #include <linux/netdevice.h> | 29 | #include <linux/netdevice.h> |
| 31 | #include <linux/etherdevice.h> | 30 | #include <linux/etherdevice.h> |
| 32 | #include <linux/ethtool.h> | 31 | #include <linux/ethtool.h> |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 4ad0de9d1d08..4ccfef5094e0 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
| @@ -24,7 +24,6 @@ | |||
| 24 | 24 | ||
| 25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
| 26 | #include <linux/etherdevice.h> | 26 | #include <linux/etherdevice.h> |
| 27 | #include <linux/init.h> | ||
| 28 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
| 29 | #include <linux/module.h> | 28 | #include <linux/module.h> |
| 30 | #include <linux/pci.h> | 29 | #include <linux/pci.h> |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 4f61ffbcd2f1..abc5f56f29fe 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
| @@ -24,7 +24,6 @@ | |||
| 24 | 24 | ||
| 25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
| 26 | #include <linux/etherdevice.h> | 26 | #include <linux/etherdevice.h> |
| 27 | #include <linux/init.h> | ||
| 28 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
| 29 | #include <linux/module.h> | 28 | #include <linux/module.h> |
| 30 | #include <linux/pci.h> | 29 | #include <linux/pci.h> |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 1bb76935da71..9f16824cd1bc 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
| @@ -24,7 +24,6 @@ | |||
| 24 | 24 | ||
| 25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
| 26 | #include <linux/etherdevice.h> | 26 | #include <linux/etherdevice.h> |
| 27 | #include <linux/init.h> | ||
| 28 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
| 29 | #include <linux/module.h> | 28 | #include <linux/module.h> |
| 30 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 49ff178a0b46..5c5c4906c6b6 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
| @@ -29,7 +29,6 @@ | |||
| 29 | 29 | ||
| 30 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
| 31 | #include <linux/etherdevice.h> | 31 | #include <linux/etherdevice.h> |
| 32 | #include <linux/init.h> | ||
| 33 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
| 34 | #include <linux/module.h> | 33 | #include <linux/module.h> |
| 35 | #include <linux/usb.h> | 34 | #include <linux/usb.h> |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 00c3fae6fa3c..2bde6729f5e6 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
| @@ -565,10 +565,10 @@ static void rt2x00lib_rxdone_check_ba(struct rt2x00_dev *rt2x00dev, | |||
| 565 | 565 | ||
| 566 | #undef TID_CHECK | 566 | #undef TID_CHECK |
| 567 | 567 | ||
| 568 | if (!ether_addr_equal(ba->ra, entry->ta)) | 568 | if (!ether_addr_equal_64bits(ba->ra, entry->ta)) |
| 569 | continue; | 569 | continue; |
| 570 | 570 | ||
| 571 | if (!ether_addr_equal(ba->ta, entry->ra)) | 571 | if (!ether_addr_equal_64bits(ba->ta, entry->ra)) |
| 572 | continue; | 572 | continue; |
| 573 | 573 | ||
| 574 | /* Mark BAR since we received the according BA */ | 574 | /* Mark BAR since we received the according BA */ |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index b76f6049ad9a..24402984ee57 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | #include <linux/crc-itu-t.h> | 25 | #include <linux/crc-itu-t.h> |
| 26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
| 27 | #include <linux/etherdevice.h> | 27 | #include <linux/etherdevice.h> |
| 28 | #include <linux/init.h> | ||
| 29 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
| 30 | #include <linux/module.h> | 29 | #include <linux/module.h> |
| 31 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ade88d7e089c..a140170b1eb3 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | #include <linux/crc-itu-t.h> | 25 | #include <linux/crc-itu-t.h> |
| 26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
| 27 | #include <linux/etherdevice.h> | 27 | #include <linux/etherdevice.h> |
| 28 | #include <linux/init.h> | ||
| 29 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
| 30 | #include <linux/module.h> | 29 | #include <linux/module.h> |
| 31 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c index a91506b12a62..8ec17aad0e52 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | * published by the Free Software Foundation. | 15 | * published by the Free Software Foundation. |
| 16 | */ | 16 | */ |
| 17 | 17 | ||
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
| 20 | #include <linux/pci.h> | 19 | #include <linux/pci.h> |
| 21 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
diff --git a/drivers/net/wireless/rtl818x/rtl8180/grf5101.c b/drivers/net/wireless/rtl818x/rtl8180/grf5101.c index dc845693f321..b1bfee738937 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/grf5101.c +++ b/drivers/net/wireless/rtl818x/rtl8180/grf5101.c | |||
| @@ -19,7 +19,6 @@ | |||
| 19 | * published by the Free Software Foundation. | 19 | * published by the Free Software Foundation. |
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/pci.h> | 22 | #include <linux/pci.h> |
| 24 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
| 25 | #include <net/mac80211.h> | 24 | #include <net/mac80211.h> |
diff --git a/drivers/net/wireless/rtl818x/rtl8180/max2820.c b/drivers/net/wireless/rtl818x/rtl8180/max2820.c index a63c443c3c6f..eebf23976524 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/max2820.c +++ b/drivers/net/wireless/rtl818x/rtl8180/max2820.c | |||
| @@ -18,7 +18,6 @@ | |||
| 18 | * published by the Free Software Foundation. | 18 | * published by the Free Software Foundation. |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | #include <linux/init.h> | ||
| 22 | #include <linux/pci.h> | 21 | #include <linux/pci.h> |
| 23 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
| 24 | #include <net/mac80211.h> | 23 | #include <net/mac80211.h> |
diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c b/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c index ee638d0749d6..d60a5f399022 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c +++ b/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | * published by the Free Software Foundation. | 15 | * published by the Free Software Foundation. |
| 16 | */ | 16 | */ |
| 17 | 17 | ||
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/pci.h> | 18 | #include <linux/pci.h> |
| 20 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
| 21 | #include <net/mac80211.h> | 20 | #include <net/mac80211.h> |
diff --git a/drivers/net/wireless/rtl818x/rtl8180/sa2400.c b/drivers/net/wireless/rtl818x/rtl8180/sa2400.c index 7614d9ccc729..959b049827de 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/sa2400.c +++ b/drivers/net/wireless/rtl818x/rtl8180/sa2400.c | |||
| @@ -19,7 +19,6 @@ | |||
| 19 | * published by the Free Software Foundation. | 19 | * published by the Free Software Foundation. |
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/pci.h> | 22 | #include <linux/pci.h> |
| 24 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
| 25 | #include <net/mac80211.h> | 24 | #include <net/mac80211.h> |
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c index ec9aa5b67381..fd78df813a85 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c | |||
| @@ -20,7 +20,6 @@ | |||
| 20 | * published by the Free Software Foundation. | 20 | * published by the Free Software Foundation. |
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | #include <linux/init.h> | ||
| 24 | #include <linux/usb.h> | 23 | #include <linux/usb.h> |
| 25 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
| 26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
diff --git a/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c b/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c index a26193a04447..5ecf18ed67b8 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c +++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | * published by the Free Software Foundation. | 16 | * published by the Free Software Foundation. |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/usb.h> | 19 | #include <linux/usb.h> |
| 21 | #include <net/mac80211.h> | 20 | #include <net/mac80211.h> |
| 22 | 21 | ||
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index fcf9b621918c..d63a12cc5de8 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c | |||
| @@ -1293,7 +1293,7 @@ void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
| 1293 | return; | 1293 | return; |
| 1294 | 1294 | ||
| 1295 | /* and only beacons from the associated BSSID, please */ | 1295 | /* and only beacons from the associated BSSID, please */ |
| 1296 | if (!ether_addr_equal(hdr->addr3, rtlpriv->mac80211.bssid)) | 1296 | if (!ether_addr_equal_64bits(hdr->addr3, rtlpriv->mac80211.bssid)) |
| 1297 | return; | 1297 | return; |
| 1298 | 1298 | ||
| 1299 | rtlpriv->link_info.bcn_rx_inperiod++; | 1299 | rtlpriv->link_info.bcn_rx_inperiod++; |
| @@ -1781,7 +1781,7 @@ void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len) | |||
| 1781 | return; | 1781 | return; |
| 1782 | 1782 | ||
| 1783 | /* and only beacons from the associated BSSID, please */ | 1783 | /* and only beacons from the associated BSSID, please */ |
| 1784 | if (!ether_addr_equal(hdr->addr3, rtlpriv->mac80211.bssid)) | 1784 | if (!ether_addr_equal_64bits(hdr->addr3, rtlpriv->mac80211.bssid)) |
| 1785 | return; | 1785 | return; |
| 1786 | 1786 | ||
| 1787 | if (rtl_find_221_ie(hw, data, len)) | 1787 | if (rtl_find_221_ie(hw, data, len)) |
diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index 0d81f766fd0f..deedae3c5449 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c | |||
| @@ -478,7 +478,7 @@ void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len) | |||
| 478 | return; | 478 | return; |
| 479 | 479 | ||
| 480 | /* and only beacons from the associated BSSID, please */ | 480 | /* and only beacons from the associated BSSID, please */ |
| 481 | if (!ether_addr_equal(hdr->addr3, rtlpriv->mac80211.bssid)) | 481 | if (!ether_addr_equal_64bits(hdr->addr3, rtlpriv->mac80211.bssid)) |
| 482 | return; | 482 | return; |
| 483 | 483 | ||
| 484 | rtlpriv->psc.last_beacon = jiffies; | 484 | rtlpriv->psc.last_beacon = jiffies; |
| @@ -923,7 +923,7 @@ void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len) | |||
| 923 | return; | 923 | return; |
| 924 | 924 | ||
| 925 | /* and only beacons from the associated BSSID, please */ | 925 | /* and only beacons from the associated BSSID, please */ |
| 926 | if (!ether_addr_equal(hdr->addr3, rtlpriv->mac80211.bssid)) | 926 | if (!ether_addr_equal_64bits(hdr->addr3, rtlpriv->mac80211.bssid)) |
| 927 | return; | 927 | return; |
| 928 | 928 | ||
| 929 | /* check if this really is a beacon */ | 929 | /* check if this really is a beacon */ |
diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c index 374268d5ac6a..5a4ec56c83d0 100644 --- a/drivers/net/wireless/ti/wl1251/acx.c +++ b/drivers/net/wireless/ti/wl1251/acx.c | |||
| @@ -194,7 +194,7 @@ out: | |||
| 194 | return ret; | 194 | return ret; |
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | int wl1251_acx_feature_cfg(struct wl1251 *wl) | 197 | int wl1251_acx_feature_cfg(struct wl1251 *wl, u32 data_flow_options) |
| 198 | { | 198 | { |
| 199 | struct acx_feature_config *feature; | 199 | struct acx_feature_config *feature; |
| 200 | int ret; | 200 | int ret; |
| @@ -205,8 +205,8 @@ int wl1251_acx_feature_cfg(struct wl1251 *wl) | |||
| 205 | if (!feature) | 205 | if (!feature) |
| 206 | return -ENOMEM; | 206 | return -ENOMEM; |
| 207 | 207 | ||
| 208 | /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */ | 208 | /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE can be set */ |
| 209 | feature->data_flow_options = 0; | 209 | feature->data_flow_options = data_flow_options; |
| 210 | feature->options = 0; | 210 | feature->options = 0; |
| 211 | 211 | ||
| 212 | ret = wl1251_cmd_configure(wl, ACX_FEATURE_CFG, | 212 | ret = wl1251_cmd_configure(wl, ACX_FEATURE_CFG, |
| @@ -381,7 +381,8 @@ out: | |||
| 381 | return ret; | 381 | return ret; |
| 382 | } | 382 | } |
| 383 | 383 | ||
| 384 | int wl1251_acx_group_address_tbl(struct wl1251 *wl) | 384 | int wl1251_acx_group_address_tbl(struct wl1251 *wl, bool enable, |
| 385 | void *mc_list, u32 mc_list_len) | ||
| 385 | { | 386 | { |
| 386 | struct acx_dot11_grp_addr_tbl *acx; | 387 | struct acx_dot11_grp_addr_tbl *acx; |
| 387 | int ret; | 388 | int ret; |
| @@ -393,9 +394,9 @@ int wl1251_acx_group_address_tbl(struct wl1251 *wl) | |||
| 393 | return -ENOMEM; | 394 | return -ENOMEM; |
| 394 | 395 | ||
| 395 | /* MAC filtering */ | 396 | /* MAC filtering */ |
| 396 | acx->enabled = 0; | 397 | acx->enabled = enable; |
| 397 | acx->num_groups = 0; | 398 | acx->num_groups = mc_list_len; |
| 398 | memset(acx->mac_table, 0, ADDRESS_GROUP_MAX_LEN); | 399 | memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN); |
| 399 | 400 | ||
| 400 | ret = wl1251_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL, | 401 | ret = wl1251_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL, |
| 401 | acx, sizeof(*acx)); | 402 | acx, sizeof(*acx)); |
| @@ -846,12 +847,18 @@ int wl1251_acx_rate_policies(struct wl1251 *wl) | |||
| 846 | return -ENOMEM; | 847 | return -ENOMEM; |
| 847 | 848 | ||
| 848 | /* configure one default (one-size-fits-all) rate class */ | 849 | /* configure one default (one-size-fits-all) rate class */ |
| 849 | acx->rate_class_cnt = 1; | 850 | acx->rate_class_cnt = 2; |
| 850 | acx->rate_class[0].enabled_rates = ACX_RATE_MASK_UNSPECIFIED; | 851 | acx->rate_class[0].enabled_rates = ACX_RATE_MASK_UNSPECIFIED; |
| 851 | acx->rate_class[0].short_retry_limit = ACX_RATE_RETRY_LIMIT; | 852 | acx->rate_class[0].short_retry_limit = ACX_RATE_RETRY_LIMIT; |
| 852 | acx->rate_class[0].long_retry_limit = ACX_RATE_RETRY_LIMIT; | 853 | acx->rate_class[0].long_retry_limit = ACX_RATE_RETRY_LIMIT; |
| 853 | acx->rate_class[0].aflags = 0; | 854 | acx->rate_class[0].aflags = 0; |
| 854 | 855 | ||
| 856 | /* no-retry rate class */ | ||
| 857 | acx->rate_class[1].enabled_rates = ACX_RATE_MASK_UNSPECIFIED; | ||
| 858 | acx->rate_class[1].short_retry_limit = 0; | ||
| 859 | acx->rate_class[1].long_retry_limit = 0; | ||
| 860 | acx->rate_class[1].aflags = 0; | ||
| 861 | |||
| 855 | ret = wl1251_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); | 862 | ret = wl1251_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); |
| 856 | if (ret < 0) { | 863 | if (ret < 0) { |
| 857 | wl1251_warning("Setting of rate policies failed: %d", ret); | 864 | wl1251_warning("Setting of rate policies failed: %d", ret); |
| @@ -960,6 +967,32 @@ out: | |||
| 960 | return ret; | 967 | return ret; |
| 961 | } | 968 | } |
| 962 | 969 | ||
| 970 | int wl1251_acx_arp_ip_filter(struct wl1251 *wl, bool enable, __be32 address) | ||
| 971 | { | ||
| 972 | struct wl1251_acx_arp_filter *acx; | ||
| 973 | int ret; | ||
| 974 | |||
| 975 | wl1251_debug(DEBUG_ACX, "acx arp ip filter, enable: %d", enable); | ||
| 976 | |||
| 977 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
| 978 | if (!acx) | ||
| 979 | return -ENOMEM; | ||
| 980 | |||
| 981 | acx->version = ACX_IPV4_VERSION; | ||
| 982 | acx->enable = enable; | ||
| 983 | |||
| 984 | if (enable) | ||
| 985 | memcpy(acx->address, &address, ACX_IPV4_ADDR_SIZE); | ||
| 986 | |||
| 987 | ret = wl1251_cmd_configure(wl, ACX_ARP_IP_FILTER, | ||
| 988 | acx, sizeof(*acx)); | ||
| 989 | if (ret < 0) | ||
| 990 | wl1251_warning("failed to set arp ip filter: %d", ret); | ||
| 991 | |||
| 992 | kfree(acx); | ||
| 993 | return ret; | ||
| 994 | } | ||
| 995 | |||
| 963 | int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max, | 996 | int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max, |
| 964 | u8 aifs, u16 txop) | 997 | u8 aifs, u16 txop) |
| 965 | { | 998 | { |
diff --git a/drivers/net/wireless/ti/wl1251/acx.h b/drivers/net/wireless/ti/wl1251/acx.h index c2ba100f9b1a..2bdec38699f4 100644 --- a/drivers/net/wireless/ti/wl1251/acx.h +++ b/drivers/net/wireless/ti/wl1251/acx.h | |||
| @@ -350,8 +350,8 @@ struct acx_slot { | |||
| 350 | } __packed; | 350 | } __packed; |
| 351 | 351 | ||
| 352 | 352 | ||
| 353 | #define ADDRESS_GROUP_MAX (8) | 353 | #define ACX_MC_ADDRESS_GROUP_MAX (8) |
| 354 | #define ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ADDRESS_GROUP_MAX) | 354 | #define ACX_MC_ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ACX_MC_ADDRESS_GROUP_MAX) |
| 355 | 355 | ||
| 356 | struct acx_dot11_grp_addr_tbl { | 356 | struct acx_dot11_grp_addr_tbl { |
| 357 | struct acx_header header; | 357 | struct acx_header header; |
| @@ -359,7 +359,7 @@ struct acx_dot11_grp_addr_tbl { | |||
| 359 | u8 enabled; | 359 | u8 enabled; |
| 360 | u8 num_groups; | 360 | u8 num_groups; |
| 361 | u8 pad[2]; | 361 | u8 pad[2]; |
| 362 | u8 mac_table[ADDRESS_GROUP_MAX_LEN]; | 362 | u8 mac_table[ACX_MC_ADDRESS_GROUP_MAX_LEN]; |
| 363 | } __packed; | 363 | } __packed; |
| 364 | 364 | ||
| 365 | 365 | ||
| @@ -1232,6 +1232,20 @@ struct wl1251_acx_bet_enable { | |||
| 1232 | u8 padding[2]; | 1232 | u8 padding[2]; |
| 1233 | } __packed; | 1233 | } __packed; |
| 1234 | 1234 | ||
| 1235 | #define ACX_IPV4_VERSION 4 | ||
| 1236 | #define ACX_IPV6_VERSION 6 | ||
| 1237 | #define ACX_IPV4_ADDR_SIZE 4 | ||
| 1238 | struct wl1251_acx_arp_filter { | ||
| 1239 | struct acx_header header; | ||
| 1240 | u8 version; /* The IP version: 4 - IPv4, 6 - IPv6.*/ | ||
| 1241 | u8 enable; /* 1 - ARP filtering is enabled, 0 - disabled */ | ||
| 1242 | u8 padding[2]; | ||
| 1243 | u8 address[16]; /* The IP address used to filter ARP packets. | ||
| 1244 | ARP packets that do not match this address are | ||
| 1245 | dropped. When the IP Version is 4, the last 12 | ||
| 1246 | bytes of the the address are ignored. */ | ||
| 1247 | } __attribute__((packed)); | ||
| 1248 | |||
| 1235 | struct wl1251_acx_ac_cfg { | 1249 | struct wl1251_acx_ac_cfg { |
| 1236 | struct acx_header header; | 1250 | struct acx_header header; |
| 1237 | 1251 | ||
| @@ -1440,7 +1454,7 @@ int wl1251_acx_wake_up_conditions(struct wl1251 *wl, u8 wake_up_event, | |||
| 1440 | int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth); | 1454 | int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth); |
| 1441 | int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len); | 1455 | int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len); |
| 1442 | int wl1251_acx_tx_power(struct wl1251 *wl, int power); | 1456 | int wl1251_acx_tx_power(struct wl1251 *wl, int power); |
| 1443 | int wl1251_acx_feature_cfg(struct wl1251 *wl); | 1457 | int wl1251_acx_feature_cfg(struct wl1251 *wl, u32 data_flow_options); |
| 1444 | int wl1251_acx_mem_map(struct wl1251 *wl, | 1458 | int wl1251_acx_mem_map(struct wl1251 *wl, |
| 1445 | struct acx_header *mem_map, size_t len); | 1459 | struct acx_header *mem_map, size_t len); |
| 1446 | int wl1251_acx_data_path_params(struct wl1251 *wl, | 1460 | int wl1251_acx_data_path_params(struct wl1251 *wl, |
| @@ -1449,7 +1463,8 @@ int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time); | |||
| 1449 | int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter); | 1463 | int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter); |
| 1450 | int wl1251_acx_pd_threshold(struct wl1251 *wl); | 1464 | int wl1251_acx_pd_threshold(struct wl1251 *wl); |
| 1451 | int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time); | 1465 | int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time); |
| 1452 | int wl1251_acx_group_address_tbl(struct wl1251 *wl); | 1466 | int wl1251_acx_group_address_tbl(struct wl1251 *wl, bool enable, |
| 1467 | void *mc_list, u32 mc_list_len); | ||
| 1453 | int wl1251_acx_service_period_timeout(struct wl1251 *wl); | 1468 | int wl1251_acx_service_period_timeout(struct wl1251 *wl); |
| 1454 | int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold); | 1469 | int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold); |
| 1455 | int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter); | 1470 | int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter); |
| @@ -1473,6 +1488,7 @@ int wl1251_acx_mem_cfg(struct wl1251 *wl); | |||
| 1473 | int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim); | 1488 | int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim); |
| 1474 | int wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode, | 1489 | int wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode, |
| 1475 | u8 max_consecutive); | 1490 | u8 max_consecutive); |
| 1491 | int wl1251_acx_arp_ip_filter(struct wl1251 *wl, bool enable, __be32 address); | ||
| 1476 | int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max, | 1492 | int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max, |
| 1477 | u8 aifs, u16 txop); | 1493 | u8 aifs, u16 txop); |
| 1478 | int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue, | 1494 | int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue, |
diff --git a/drivers/net/wireless/ti/wl1251/boot.c b/drivers/net/wireless/ti/wl1251/boot.c index a2e5241382da..2000cd536077 100644 --- a/drivers/net/wireless/ti/wl1251/boot.c +++ b/drivers/net/wireless/ti/wl1251/boot.c | |||
| @@ -299,7 +299,8 @@ int wl1251_boot_run_firmware(struct wl1251 *wl) | |||
| 299 | ROAMING_TRIGGER_LOW_RSSI_EVENT_ID | | 299 | ROAMING_TRIGGER_LOW_RSSI_EVENT_ID | |
| 300 | ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID | | 300 | ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID | |
| 301 | REGAINED_BSS_EVENT_ID | BT_PTA_SENSE_EVENT_ID | | 301 | REGAINED_BSS_EVENT_ID | BT_PTA_SENSE_EVENT_ID | |
| 302 | BT_PTA_PREDICTION_EVENT_ID | JOIN_EVENT_COMPLETE_ID; | 302 | BT_PTA_PREDICTION_EVENT_ID | JOIN_EVENT_COMPLETE_ID | |
| 303 | PS_REPORT_EVENT_ID; | ||
| 303 | 304 | ||
| 304 | ret = wl1251_event_unmask(wl); | 305 | ret = wl1251_event_unmask(wl); |
| 305 | if (ret < 0) { | 306 | if (ret < 0) { |
diff --git a/drivers/net/wireless/ti/wl1251/cmd.c b/drivers/net/wireless/ti/wl1251/cmd.c index 6822b845efc1..223649bcaa5a 100644 --- a/drivers/net/wireless/ti/wl1251/cmd.c +++ b/drivers/net/wireless/ti/wl1251/cmd.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | #include <linux/module.h> | 3 | #include <linux/module.h> |
| 4 | #include <linux/slab.h> | 4 | #include <linux/slab.h> |
| 5 | #include <linux/crc7.h> | 5 | #include <linux/crc7.h> |
| 6 | #include <linux/etherdevice.h> | ||
| 6 | 7 | ||
| 7 | #include "wl1251.h" | 8 | #include "wl1251.h" |
| 8 | #include "reg.h" | 9 | #include "reg.h" |
| @@ -203,11 +204,11 @@ out: | |||
| 203 | return ret; | 204 | return ret; |
| 204 | } | 205 | } |
| 205 | 206 | ||
| 206 | int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable) | 207 | int wl1251_cmd_data_path_rx(struct wl1251 *wl, u8 channel, bool enable) |
| 207 | { | 208 | { |
| 208 | struct cmd_enabledisable_path *cmd; | 209 | struct cmd_enabledisable_path *cmd; |
| 209 | int ret; | 210 | int ret; |
| 210 | u16 cmd_rx, cmd_tx; | 211 | u16 cmd_rx; |
| 211 | 212 | ||
| 212 | wl1251_debug(DEBUG_CMD, "cmd data path"); | 213 | wl1251_debug(DEBUG_CMD, "cmd data path"); |
| 213 | 214 | ||
| @@ -219,13 +220,10 @@ int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable) | |||
| 219 | 220 | ||
| 220 | cmd->channel = channel; | 221 | cmd->channel = channel; |
| 221 | 222 | ||
| 222 | if (enable) { | 223 | if (enable) |
| 223 | cmd_rx = CMD_ENABLE_RX; | 224 | cmd_rx = CMD_ENABLE_RX; |
| 224 | cmd_tx = CMD_ENABLE_TX; | 225 | else |
| 225 | } else { | ||
| 226 | cmd_rx = CMD_DISABLE_RX; | 226 | cmd_rx = CMD_DISABLE_RX; |
| 227 | cmd_tx = CMD_DISABLE_TX; | ||
| 228 | } | ||
| 229 | 227 | ||
| 230 | ret = wl1251_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd)); | 228 | ret = wl1251_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd)); |
| 231 | if (ret < 0) { | 229 | if (ret < 0) { |
| @@ -237,17 +235,38 @@ int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable) | |||
| 237 | wl1251_debug(DEBUG_BOOT, "rx %s cmd channel %d", | 235 | wl1251_debug(DEBUG_BOOT, "rx %s cmd channel %d", |
| 238 | enable ? "start" : "stop", channel); | 236 | enable ? "start" : "stop", channel); |
| 239 | 237 | ||
| 238 | out: | ||
| 239 | kfree(cmd); | ||
| 240 | return ret; | ||
| 241 | } | ||
| 242 | |||
| 243 | int wl1251_cmd_data_path_tx(struct wl1251 *wl, u8 channel, bool enable) | ||
| 244 | { | ||
| 245 | struct cmd_enabledisable_path *cmd; | ||
| 246 | int ret; | ||
| 247 | u16 cmd_tx; | ||
| 248 | |||
| 249 | wl1251_debug(DEBUG_CMD, "cmd data path"); | ||
| 250 | |||
| 251 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
| 252 | if (!cmd) | ||
| 253 | return -ENOMEM; | ||
| 254 | |||
| 255 | cmd->channel = channel; | ||
| 256 | |||
| 257 | if (enable) | ||
| 258 | cmd_tx = CMD_ENABLE_TX; | ||
| 259 | else | ||
| 260 | cmd_tx = CMD_DISABLE_TX; | ||
| 261 | |||
| 240 | ret = wl1251_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd)); | 262 | ret = wl1251_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd)); |
| 241 | if (ret < 0) { | 263 | if (ret < 0) |
| 242 | wl1251_error("tx %s cmd for channel %d failed", | 264 | wl1251_error("tx %s cmd for channel %d failed", |
| 243 | enable ? "start" : "stop", channel); | 265 | enable ? "start" : "stop", channel); |
| 244 | goto out; | 266 | else |
| 245 | } | 267 | wl1251_debug(DEBUG_BOOT, "tx %s cmd channel %d", |
| 246 | 268 | enable ? "start" : "stop", channel); | |
| 247 | wl1251_debug(DEBUG_BOOT, "tx %s cmd channel %d", | ||
| 248 | enable ? "start" : "stop", channel); | ||
| 249 | 269 | ||
| 250 | out: | ||
| 251 | kfree(cmd); | 270 | kfree(cmd); |
| 252 | return ret; | 271 | return ret; |
| 253 | } | 272 | } |
| @@ -410,7 +429,9 @@ int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len, | |||
| 410 | struct wl1251_cmd_scan *cmd; | 429 | struct wl1251_cmd_scan *cmd; |
| 411 | int i, ret = 0; | 430 | int i, ret = 0; |
| 412 | 431 | ||
| 413 | wl1251_debug(DEBUG_CMD, "cmd scan"); | 432 | wl1251_debug(DEBUG_CMD, "cmd scan channels %d", n_channels); |
| 433 | |||
| 434 | WARN_ON(n_channels > SCAN_MAX_NUM_OF_CHANNELS); | ||
| 414 | 435 | ||
| 415 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 436 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
| 416 | if (!cmd) | 437 | if (!cmd) |
| @@ -421,6 +442,13 @@ int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len, | |||
| 421 | CFG_RX_MGMT_EN | | 442 | CFG_RX_MGMT_EN | |
| 422 | CFG_RX_BCN_EN); | 443 | CFG_RX_BCN_EN); |
| 423 | cmd->params.scan_options = 0; | 444 | cmd->params.scan_options = 0; |
| 445 | /* | ||
| 446 | * Use high priority scan when not associated to prevent fw issue | ||
| 447 | * causing never-ending scans (sometimes 20+ minutes). | ||
| 448 | * Note: This bug may be caused by the fw's DTIM handling. | ||
| 449 | */ | ||
| 450 | if (is_zero_ether_addr(wl->bssid)) | ||
| 451 | cmd->params.scan_options |= WL1251_SCAN_OPT_PRIORITY_HIGH; | ||
| 424 | cmd->params.num_channels = n_channels; | 452 | cmd->params.num_channels = n_channels; |
| 425 | cmd->params.num_probe_requests = n_probes; | 453 | cmd->params.num_probe_requests = n_probes; |
| 426 | cmd->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */ | 454 | cmd->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */ |
diff --git a/drivers/net/wireless/ti/wl1251/cmd.h b/drivers/net/wireless/ti/wl1251/cmd.h index ee4f2b391822..d824ff978311 100644 --- a/drivers/net/wireless/ti/wl1251/cmd.h +++ b/drivers/net/wireless/ti/wl1251/cmd.h | |||
| @@ -35,7 +35,8 @@ int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len); | |||
| 35 | int wl1251_cmd_configure(struct wl1251 *wl, u16 id, void *buf, size_t len); | 35 | int wl1251_cmd_configure(struct wl1251 *wl, u16 id, void *buf, size_t len); |
| 36 | int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity, | 36 | int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity, |
| 37 | void *bitmap, u16 bitmap_len, u8 bitmap_control); | 37 | void *bitmap, u16 bitmap_len, u8 bitmap_control); |
| 38 | int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable); | 38 | int wl1251_cmd_data_path_rx(struct wl1251 *wl, u8 channel, bool enable); |
| 39 | int wl1251_cmd_data_path_tx(struct wl1251 *wl, u8 channel, bool enable); | ||
| 39 | int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel, | 40 | int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel, |
| 40 | u16 beacon_interval, u8 dtim_interval); | 41 | u16 beacon_interval, u8 dtim_interval); |
| 41 | int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode); | 42 | int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode); |
| @@ -167,6 +168,11 @@ struct cmd_read_write_memory { | |||
| 167 | #define CMDMBOX_HEADER_LEN 4 | 168 | #define CMDMBOX_HEADER_LEN 4 |
| 168 | #define CMDMBOX_INFO_ELEM_HEADER_LEN 4 | 169 | #define CMDMBOX_INFO_ELEM_HEADER_LEN 4 |
| 169 | 170 | ||
| 171 | #define WL1251_SCAN_OPT_PASSIVE 1 | ||
| 172 | #define WL1251_SCAN_OPT_5GHZ_BAND 2 | ||
| 173 | #define WL1251_SCAN_OPT_TRIGGERD_SCAN 4 | ||
| 174 | #define WL1251_SCAN_OPT_PRIORITY_HIGH 8 | ||
| 175 | |||
| 170 | #define WL1251_SCAN_MIN_DURATION 30000 | 176 | #define WL1251_SCAN_MIN_DURATION 30000 |
| 171 | #define WL1251_SCAN_MAX_DURATION 60000 | 177 | #define WL1251_SCAN_MAX_DURATION 60000 |
| 172 | 178 | ||
diff --git a/drivers/net/wireless/ti/wl1251/event.c b/drivers/net/wireless/ti/wl1251/event.c index 74ae8e1c2e33..db0105313745 100644 --- a/drivers/net/wireless/ti/wl1251/event.c +++ b/drivers/net/wireless/ti/wl1251/event.c | |||
| @@ -46,6 +46,43 @@ static int wl1251_event_scan_complete(struct wl1251 *wl, | |||
| 46 | return ret; | 46 | return ret; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | #define WL1251_PSM_ENTRY_RETRIES 3 | ||
| 50 | static int wl1251_event_ps_report(struct wl1251 *wl, | ||
| 51 | struct event_mailbox *mbox) | ||
| 52 | { | ||
| 53 | int ret = 0; | ||
| 54 | |||
| 55 | wl1251_debug(DEBUG_EVENT, "ps status: %x", mbox->ps_status); | ||
| 56 | |||
| 57 | switch (mbox->ps_status) { | ||
| 58 | case EVENT_ENTER_POWER_SAVE_FAIL: | ||
| 59 | wl1251_debug(DEBUG_PSM, "PSM entry failed"); | ||
| 60 | |||
| 61 | if (wl->station_mode != STATION_POWER_SAVE_MODE) { | ||
| 62 | /* remain in active mode */ | ||
| 63 | wl->psm_entry_retry = 0; | ||
| 64 | break; | ||
| 65 | } | ||
| 66 | |||
| 67 | if (wl->psm_entry_retry < WL1251_PSM_ENTRY_RETRIES) { | ||
| 68 | wl->psm_entry_retry++; | ||
| 69 | ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); | ||
| 70 | } else { | ||
| 71 | wl1251_error("Power save entry failed, giving up"); | ||
| 72 | wl->psm_entry_retry = 0; | ||
| 73 | } | ||
| 74 | break; | ||
| 75 | case EVENT_ENTER_POWER_SAVE_SUCCESS: | ||
| 76 | case EVENT_EXIT_POWER_SAVE_FAIL: | ||
| 77 | case EVENT_EXIT_POWER_SAVE_SUCCESS: | ||
| 78 | default: | ||
| 79 | wl->psm_entry_retry = 0; | ||
| 80 | break; | ||
| 81 | } | ||
| 82 | |||
| 83 | return 0; | ||
| 84 | } | ||
| 85 | |||
| 49 | static void wl1251_event_mbox_dump(struct event_mailbox *mbox) | 86 | static void wl1251_event_mbox_dump(struct event_mailbox *mbox) |
| 50 | { | 87 | { |
| 51 | wl1251_debug(DEBUG_EVENT, "MBOX DUMP:"); | 88 | wl1251_debug(DEBUG_EVENT, "MBOX DUMP:"); |
| @@ -80,7 +117,14 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox) | |||
| 80 | } | 117 | } |
| 81 | } | 118 | } |
| 82 | 119 | ||
| 83 | if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) { | 120 | if (vector & PS_REPORT_EVENT_ID) { |
| 121 | wl1251_debug(DEBUG_EVENT, "PS_REPORT_EVENT"); | ||
| 122 | ret = wl1251_event_ps_report(wl, mbox); | ||
| 123 | if (ret < 0) | ||
| 124 | return ret; | ||
| 125 | } | ||
| 126 | |||
| 127 | if (wl->vif && vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) { | ||
| 84 | wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT"); | 128 | wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT"); |
| 85 | 129 | ||
| 86 | /* indicate to the stack, that beacons have been lost */ | 130 | /* indicate to the stack, that beacons have been lost */ |
diff --git a/drivers/net/wireless/ti/wl1251/event.h b/drivers/net/wireless/ti/wl1251/event.h index 30eb5d150bf7..88570a5cd042 100644 --- a/drivers/net/wireless/ti/wl1251/event.h +++ b/drivers/net/wireless/ti/wl1251/event.h | |||
| @@ -112,6 +112,13 @@ struct event_mailbox { | |||
| 112 | u8 padding[19]; | 112 | u8 padding[19]; |
| 113 | } __packed; | 113 | } __packed; |
| 114 | 114 | ||
| 115 | enum { | ||
| 116 | EVENT_ENTER_POWER_SAVE_FAIL = 0, | ||
| 117 | EVENT_ENTER_POWER_SAVE_SUCCESS, | ||
| 118 | EVENT_EXIT_POWER_SAVE_FAIL, | ||
| 119 | EVENT_EXIT_POWER_SAVE_SUCCESS, | ||
| 120 | }; | ||
| 121 | |||
| 115 | int wl1251_event_unmask(struct wl1251 *wl); | 122 | int wl1251_event_unmask(struct wl1251 *wl); |
| 116 | void wl1251_event_mbox_config(struct wl1251 *wl); | 123 | void wl1251_event_mbox_config(struct wl1251 *wl); |
| 117 | int wl1251_event_handle(struct wl1251 *wl, u8 mbox); | 124 | int wl1251_event_handle(struct wl1251 *wl, u8 mbox); |
diff --git a/drivers/net/wireless/ti/wl1251/init.c b/drivers/net/wireless/ti/wl1251/init.c index 89b43d35473c..1d799bffaa9f 100644 --- a/drivers/net/wireless/ti/wl1251/init.c +++ b/drivers/net/wireless/ti/wl1251/init.c | |||
| @@ -33,7 +33,7 @@ int wl1251_hw_init_hwenc_config(struct wl1251 *wl) | |||
| 33 | { | 33 | { |
| 34 | int ret; | 34 | int ret; |
| 35 | 35 | ||
| 36 | ret = wl1251_acx_feature_cfg(wl); | 36 | ret = wl1251_acx_feature_cfg(wl, 0); |
| 37 | if (ret < 0) { | 37 | if (ret < 0) { |
| 38 | wl1251_warning("couldn't set feature config"); | 38 | wl1251_warning("couldn't set feature config"); |
| 39 | return ret; | 39 | return ret; |
| @@ -127,7 +127,7 @@ int wl1251_hw_init_phy_config(struct wl1251 *wl) | |||
| 127 | if (ret < 0) | 127 | if (ret < 0) |
| 128 | return ret; | 128 | return ret; |
| 129 | 129 | ||
| 130 | ret = wl1251_acx_group_address_tbl(wl); | 130 | ret = wl1251_acx_group_address_tbl(wl, true, NULL, 0); |
| 131 | if (ret < 0) | 131 | if (ret < 0) |
| 132 | return ret; | 132 | return ret; |
| 133 | 133 | ||
| @@ -394,8 +394,13 @@ int wl1251_hw_init(struct wl1251 *wl) | |||
| 394 | if (ret < 0) | 394 | if (ret < 0) |
| 395 | goto out_free_data_path; | 395 | goto out_free_data_path; |
| 396 | 396 | ||
| 397 | /* Enable data path */ | 397 | /* Enable rx data path */ |
| 398 | ret = wl1251_cmd_data_path(wl, wl->channel, 1); | 398 | ret = wl1251_cmd_data_path_rx(wl, wl->channel, 1); |
| 399 | if (ret < 0) | ||
| 400 | goto out_free_data_path; | ||
| 401 | |||
| 402 | /* Enable tx data path */ | ||
| 403 | ret = wl1251_cmd_data_path_tx(wl, wl->channel, 1); | ||
| 399 | if (ret < 0) | 404 | if (ret < 0) |
| 400 | goto out_free_data_path; | 405 | goto out_free_data_path; |
| 401 | 406 | ||
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c index b8a360b43e76..119c148f7740 100644 --- a/drivers/net/wireless/ti/wl1251/main.c +++ b/drivers/net/wireless/ti/wl1251/main.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/etherdevice.h> | 28 | #include <linux/etherdevice.h> |
| 29 | #include <linux/vmalloc.h> | 29 | #include <linux/vmalloc.h> |
| 30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
| 31 | #include <linux/netdevice.h> | ||
| 31 | 32 | ||
| 32 | #include "wl1251.h" | 33 | #include "wl1251.h" |
| 33 | #include "wl12xx_80211.h" | 34 | #include "wl12xx_80211.h" |
| @@ -479,10 +480,13 @@ static void wl1251_op_stop(struct ieee80211_hw *hw) | |||
| 479 | wl->next_tx_complete = 0; | 480 | wl->next_tx_complete = 0; |
| 480 | wl->elp = false; | 481 | wl->elp = false; |
| 481 | wl->station_mode = STATION_ACTIVE_MODE; | 482 | wl->station_mode = STATION_ACTIVE_MODE; |
| 483 | wl->psm_entry_retry = 0; | ||
| 482 | wl->tx_queue_stopped = false; | 484 | wl->tx_queue_stopped = false; |
| 483 | wl->power_level = WL1251_DEFAULT_POWER_LEVEL; | 485 | wl->power_level = WL1251_DEFAULT_POWER_LEVEL; |
| 484 | wl->rssi_thold = 0; | 486 | wl->rssi_thold = 0; |
| 485 | wl->channel = WL1251_DEFAULT_CHANNEL; | 487 | wl->channel = WL1251_DEFAULT_CHANNEL; |
| 488 | wl->monitor_present = false; | ||
| 489 | wl->joined = false; | ||
| 486 | 490 | ||
| 487 | wl1251_debugfs_reset(wl); | 491 | wl1251_debugfs_reset(wl); |
| 488 | 492 | ||
| @@ -542,6 +546,7 @@ static void wl1251_op_remove_interface(struct ieee80211_hw *hw, | |||
| 542 | mutex_lock(&wl->mutex); | 546 | mutex_lock(&wl->mutex); |
| 543 | wl1251_debug(DEBUG_MAC80211, "mac80211 remove interface"); | 547 | wl1251_debug(DEBUG_MAC80211, "mac80211 remove interface"); |
| 544 | wl->vif = NULL; | 548 | wl->vif = NULL; |
| 549 | memset(wl->bssid, 0, ETH_ALEN); | ||
| 545 | mutex_unlock(&wl->mutex); | 550 | mutex_unlock(&wl->mutex); |
| 546 | } | 551 | } |
| 547 | 552 | ||
| @@ -566,6 +571,11 @@ static int wl1251_build_qos_null_data(struct wl1251 *wl) | |||
| 566 | sizeof(template)); | 571 | sizeof(template)); |
| 567 | } | 572 | } |
| 568 | 573 | ||
| 574 | static bool wl1251_can_do_pm(struct ieee80211_conf *conf, struct wl1251 *wl) | ||
| 575 | { | ||
| 576 | return (conf->flags & IEEE80211_CONF_PS) && !wl->monitor_present; | ||
| 577 | } | ||
| 578 | |||
| 569 | static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) | 579 | static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) |
| 570 | { | 580 | { |
| 571 | struct wl1251 *wl = hw->priv; | 581 | struct wl1251 *wl = hw->priv; |
| @@ -575,8 +585,10 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) | |||
| 575 | channel = ieee80211_frequency_to_channel( | 585 | channel = ieee80211_frequency_to_channel( |
| 576 | conf->chandef.chan->center_freq); | 586 | conf->chandef.chan->center_freq); |
| 577 | 587 | ||
| 578 | wl1251_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d", | 588 | wl1251_debug(DEBUG_MAC80211, |
| 589 | "mac80211 config ch %d monitor %s psm %s power %d", | ||
| 579 | channel, | 590 | channel, |
| 591 | conf->flags & IEEE80211_CONF_MONITOR ? "on" : "off", | ||
| 580 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", | 592 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", |
| 581 | conf->power_level); | 593 | conf->power_level); |
| 582 | 594 | ||
| @@ -586,16 +598,44 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) | |||
| 586 | if (ret < 0) | 598 | if (ret < 0) |
| 587 | goto out; | 599 | goto out; |
| 588 | 600 | ||
| 601 | if (changed & IEEE80211_CONF_CHANGE_MONITOR) { | ||
| 602 | u32 mode; | ||
| 603 | |||
| 604 | if (conf->flags & IEEE80211_CONF_MONITOR) { | ||
| 605 | wl->monitor_present = true; | ||
| 606 | mode = DF_SNIFF_MODE_ENABLE | DF_ENCRYPTION_DISABLE; | ||
| 607 | } else { | ||
| 608 | wl->monitor_present = false; | ||
| 609 | mode = 0; | ||
| 610 | } | ||
| 611 | |||
| 612 | ret = wl1251_acx_feature_cfg(wl, mode); | ||
| 613 | if (ret < 0) | ||
| 614 | goto out_sleep; | ||
| 615 | } | ||
| 616 | |||
| 589 | if (channel != wl->channel) { | 617 | if (channel != wl->channel) { |
| 590 | wl->channel = channel; | 618 | wl->channel = channel; |
| 591 | 619 | ||
| 592 | ret = wl1251_join(wl, wl->bss_type, wl->channel, | 620 | /* |
| 593 | wl->beacon_int, wl->dtim_period); | 621 | * Use ENABLE_RX command for channel switching when no |
| 622 | * interface is present (monitor mode only). | ||
| 623 | * This leaves the tx path disabled in firmware, whereas | ||
| 624 | * the usual JOIN command seems to transmit some frames | ||
| 625 | * at firmware level. | ||
| 626 | */ | ||
| 627 | if (wl->vif == NULL) { | ||
| 628 | wl->joined = false; | ||
| 629 | ret = wl1251_cmd_data_path_rx(wl, wl->channel, 1); | ||
| 630 | } else { | ||
| 631 | ret = wl1251_join(wl, wl->bss_type, wl->channel, | ||
| 632 | wl->beacon_int, wl->dtim_period); | ||
| 633 | } | ||
| 594 | if (ret < 0) | 634 | if (ret < 0) |
| 595 | goto out_sleep; | 635 | goto out_sleep; |
| 596 | } | 636 | } |
| 597 | 637 | ||
| 598 | if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) { | 638 | if (wl1251_can_do_pm(conf, wl) && !wl->psm_requested) { |
| 599 | wl1251_debug(DEBUG_PSM, "psm enabled"); | 639 | wl1251_debug(DEBUG_PSM, "psm enabled"); |
| 600 | 640 | ||
| 601 | wl->psm_requested = true; | 641 | wl->psm_requested = true; |
| @@ -611,8 +651,7 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) | |||
| 611 | ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); | 651 | ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); |
| 612 | if (ret < 0) | 652 | if (ret < 0) |
| 613 | goto out_sleep; | 653 | goto out_sleep; |
| 614 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | 654 | } else if (!wl1251_can_do_pm(conf, wl) && wl->psm_requested) { |
| 615 | wl->psm_requested) { | ||
| 616 | wl1251_debug(DEBUG_PSM, "psm disabled"); | 655 | wl1251_debug(DEBUG_PSM, "psm disabled"); |
| 617 | 656 | ||
| 618 | wl->psm_requested = false; | 657 | wl->psm_requested = false; |
| @@ -648,6 +687,16 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) | |||
| 648 | wl->power_level = conf->power_level; | 687 | wl->power_level = conf->power_level; |
| 649 | } | 688 | } |
| 650 | 689 | ||
| 690 | /* | ||
| 691 | * Tell stack that connection is lost because hw encryption isn't | ||
| 692 | * supported in monitor mode. | ||
| 693 | * This requires temporary enabling of the hw connection monitor flag | ||
| 694 | */ | ||
| 695 | if ((changed & IEEE80211_CONF_CHANGE_MONITOR) && wl->vif) { | ||
| 696 | wl->hw->flags |= IEEE80211_HW_CONNECTION_MONITOR; | ||
| 697 | ieee80211_connection_loss(wl->vif); | ||
| 698 | } | ||
| 699 | |||
| 651 | out_sleep: | 700 | out_sleep: |
| 652 | wl1251_ps_elp_sleep(wl); | 701 | wl1251_ps_elp_sleep(wl); |
| 653 | 702 | ||
| @@ -657,6 +706,44 @@ out: | |||
| 657 | return ret; | 706 | return ret; |
| 658 | } | 707 | } |
| 659 | 708 | ||
| 709 | struct wl1251_filter_params { | ||
| 710 | bool enabled; | ||
| 711 | int mc_list_length; | ||
| 712 | u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN]; | ||
| 713 | }; | ||
| 714 | |||
| 715 | static u64 wl1251_op_prepare_multicast(struct ieee80211_hw *hw, | ||
| 716 | struct netdev_hw_addr_list *mc_list) | ||
| 717 | { | ||
| 718 | struct wl1251_filter_params *fp; | ||
| 719 | struct netdev_hw_addr *ha; | ||
| 720 | struct wl1251 *wl = hw->priv; | ||
| 721 | |||
| 722 | if (unlikely(wl->state == WL1251_STATE_OFF)) | ||
| 723 | return 0; | ||
| 724 | |||
| 725 | fp = kzalloc(sizeof(*fp), GFP_ATOMIC); | ||
| 726 | if (!fp) { | ||
| 727 | wl1251_error("Out of memory setting filters."); | ||
| 728 | return 0; | ||
| 729 | } | ||
| 730 | |||
| 731 | /* update multicast filtering parameters */ | ||
| 732 | fp->mc_list_length = 0; | ||
| 733 | if (netdev_hw_addr_list_count(mc_list) > ACX_MC_ADDRESS_GROUP_MAX) { | ||
| 734 | fp->enabled = false; | ||
| 735 | } else { | ||
| 736 | fp->enabled = true; | ||
| 737 | netdev_hw_addr_list_for_each(ha, mc_list) { | ||
| 738 | memcpy(fp->mc_list[fp->mc_list_length], | ||
| 739 | ha->addr, ETH_ALEN); | ||
| 740 | fp->mc_list_length++; | ||
| 741 | } | ||
| 742 | } | ||
| 743 | |||
| 744 | return (u64)(unsigned long)fp; | ||
| 745 | } | ||
| 746 | |||
| 660 | #define WL1251_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \ | 747 | #define WL1251_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \ |
| 661 | FIF_ALLMULTI | \ | 748 | FIF_ALLMULTI | \ |
| 662 | FIF_FCSFAIL | \ | 749 | FIF_FCSFAIL | \ |
| @@ -667,8 +754,9 @@ out: | |||
| 667 | 754 | ||
| 668 | static void wl1251_op_configure_filter(struct ieee80211_hw *hw, | 755 | static void wl1251_op_configure_filter(struct ieee80211_hw *hw, |
| 669 | unsigned int changed, | 756 | unsigned int changed, |
| 670 | unsigned int *total,u64 multicast) | 757 | unsigned int *total, u64 multicast) |
| 671 | { | 758 | { |
| 759 | struct wl1251_filter_params *fp = (void *)(unsigned long)multicast; | ||
| 672 | struct wl1251 *wl = hw->priv; | 760 | struct wl1251 *wl = hw->priv; |
| 673 | int ret; | 761 | int ret; |
| 674 | 762 | ||
| @@ -677,9 +765,11 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw, | |||
| 677 | *total &= WL1251_SUPPORTED_FILTERS; | 765 | *total &= WL1251_SUPPORTED_FILTERS; |
| 678 | changed &= WL1251_SUPPORTED_FILTERS; | 766 | changed &= WL1251_SUPPORTED_FILTERS; |
| 679 | 767 | ||
| 680 | if (changed == 0) | 768 | if (changed == 0) { |
| 681 | /* no filters which we support changed */ | 769 | /* no filters which we support changed */ |
| 770 | kfree(fp); | ||
| 682 | return; | 771 | return; |
| 772 | } | ||
| 683 | 773 | ||
| 684 | mutex_lock(&wl->mutex); | 774 | mutex_lock(&wl->mutex); |
| 685 | 775 | ||
| @@ -716,6 +806,15 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw, | |||
| 716 | if (ret < 0) | 806 | if (ret < 0) |
| 717 | goto out; | 807 | goto out; |
| 718 | 808 | ||
| 809 | if (*total & FIF_ALLMULTI || *total & FIF_PROMISC_IN_BSS) | ||
| 810 | ret = wl1251_acx_group_address_tbl(wl, false, NULL, 0); | ||
| 811 | else if (fp) | ||
| 812 | ret = wl1251_acx_group_address_tbl(wl, fp->enabled, | ||
| 813 | fp->mc_list, | ||
| 814 | fp->mc_list_length); | ||
| 815 | if (ret < 0) | ||
| 816 | goto out; | ||
| 817 | |||
| 719 | /* send filters to firmware */ | 818 | /* send filters to firmware */ |
| 720 | wl1251_acx_rx_config(wl, wl->rx_config, wl->rx_filter); | 819 | wl1251_acx_rx_config(wl, wl->rx_config, wl->rx_filter); |
| 721 | 820 | ||
| @@ -723,6 +822,7 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw, | |||
| 723 | 822 | ||
| 724 | out: | 823 | out: |
| 725 | mutex_unlock(&wl->mutex); | 824 | mutex_unlock(&wl->mutex); |
| 825 | kfree(fp); | ||
| 726 | } | 826 | } |
| 727 | 827 | ||
| 728 | /* HW encryption */ | 828 | /* HW encryption */ |
| @@ -802,12 +902,12 @@ static int wl1251_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
| 802 | 902 | ||
| 803 | mutex_lock(&wl->mutex); | 903 | mutex_lock(&wl->mutex); |
| 804 | 904 | ||
| 805 | ret = wl1251_ps_elp_wakeup(wl); | ||
| 806 | if (ret < 0) | ||
| 807 | goto out_unlock; | ||
| 808 | |||
| 809 | switch (cmd) { | 905 | switch (cmd) { |
| 810 | case SET_KEY: | 906 | case SET_KEY: |
| 907 | if (wl->monitor_present) { | ||
| 908 | ret = -EOPNOTSUPP; | ||
| 909 | goto out_unlock; | ||
| 910 | } | ||
| 811 | wl_cmd->key_action = KEY_ADD_OR_REPLACE; | 911 | wl_cmd->key_action = KEY_ADD_OR_REPLACE; |
| 812 | break; | 912 | break; |
| 813 | case DISABLE_KEY: | 913 | case DISABLE_KEY: |
| @@ -818,6 +918,10 @@ static int wl1251_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
| 818 | break; | 918 | break; |
| 819 | } | 919 | } |
| 820 | 920 | ||
| 921 | ret = wl1251_ps_elp_wakeup(wl); | ||
| 922 | if (ret < 0) | ||
| 923 | goto out_unlock; | ||
| 924 | |||
| 821 | ret = wl1251_set_key_type(wl, wl_cmd, cmd, key, addr); | 925 | ret = wl1251_set_key_type(wl, wl_cmd, cmd, key, addr); |
| 822 | if (ret < 0) { | 926 | if (ret < 0) { |
| 823 | wl1251_error("Set KEY type failed"); | 927 | wl1251_error("Set KEY type failed"); |
| @@ -930,6 +1034,7 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw, | |||
| 930 | ret = wl1251_cmd_scan(wl, ssid, ssid_len, req->channels, | 1034 | ret = wl1251_cmd_scan(wl, ssid, ssid_len, req->channels, |
| 931 | req->n_channels, WL1251_SCAN_NUM_PROBES); | 1035 | req->n_channels, WL1251_SCAN_NUM_PROBES); |
| 932 | if (ret < 0) { | 1036 | if (ret < 0) { |
| 1037 | wl1251_debug(DEBUG_SCAN, "scan failed %d", ret); | ||
| 933 | wl->scanning = false; | 1038 | wl->scanning = false; |
| 934 | goto out_idle; | 1039 | goto out_idle; |
| 935 | } | 1040 | } |
| @@ -977,6 +1082,7 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | |||
| 977 | { | 1082 | { |
| 978 | struct wl1251 *wl = hw->priv; | 1083 | struct wl1251 *wl = hw->priv; |
| 979 | struct sk_buff *beacon, *skb; | 1084 | struct sk_buff *beacon, *skb; |
| 1085 | bool enable; | ||
| 980 | int ret; | 1086 | int ret; |
| 981 | 1087 | ||
| 982 | wl1251_debug(DEBUG_MAC80211, "mac80211 bss info changed"); | 1088 | wl1251_debug(DEBUG_MAC80211, "mac80211 bss info changed"); |
| @@ -1023,6 +1129,9 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | |||
| 1023 | } | 1129 | } |
| 1024 | 1130 | ||
| 1025 | if (changed & BSS_CHANGED_ASSOC) { | 1131 | if (changed & BSS_CHANGED_ASSOC) { |
| 1132 | /* Disable temporary enabled hw connection monitor flag */ | ||
| 1133 | wl->hw->flags &= ~IEEE80211_HW_CONNECTION_MONITOR; | ||
| 1134 | |||
| 1026 | if (bss_conf->assoc) { | 1135 | if (bss_conf->assoc) { |
| 1027 | wl->beacon_int = bss_conf->beacon_int; | 1136 | wl->beacon_int = bss_conf->beacon_int; |
| 1028 | 1137 | ||
| @@ -1075,6 +1184,17 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | |||
| 1075 | } | 1184 | } |
| 1076 | } | 1185 | } |
| 1077 | 1186 | ||
| 1187 | if (changed & BSS_CHANGED_ARP_FILTER) { | ||
| 1188 | __be32 addr = bss_conf->arp_addr_list[0]; | ||
| 1189 | WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); | ||
| 1190 | |||
| 1191 | enable = bss_conf->arp_addr_cnt == 1 && bss_conf->assoc; | ||
| 1192 | wl1251_acx_arp_ip_filter(wl, enable, addr); | ||
| 1193 | |||
| 1194 | if (ret < 0) | ||
| 1195 | goto out_sleep; | ||
| 1196 | } | ||
| 1197 | |||
| 1078 | if (changed & BSS_CHANGED_BEACON) { | 1198 | if (changed & BSS_CHANGED_BEACON) { |
| 1079 | beacon = ieee80211_beacon_get(hw, vif); | 1199 | beacon = ieee80211_beacon_get(hw, vif); |
| 1080 | if (!beacon) | 1200 | if (!beacon) |
| @@ -1245,6 +1365,7 @@ static const struct ieee80211_ops wl1251_ops = { | |||
| 1245 | .add_interface = wl1251_op_add_interface, | 1365 | .add_interface = wl1251_op_add_interface, |
| 1246 | .remove_interface = wl1251_op_remove_interface, | 1366 | .remove_interface = wl1251_op_remove_interface, |
| 1247 | .config = wl1251_op_config, | 1367 | .config = wl1251_op_config, |
| 1368 | .prepare_multicast = wl1251_op_prepare_multicast, | ||
| 1248 | .configure_filter = wl1251_op_configure_filter, | 1369 | .configure_filter = wl1251_op_configure_filter, |
| 1249 | .tx = wl1251_op_tx, | 1370 | .tx = wl1251_op_tx, |
| 1250 | .set_key = wl1251_op_set_key, | 1371 | .set_key = wl1251_op_set_key, |
| @@ -1401,7 +1522,10 @@ struct ieee80211_hw *wl1251_alloc_hw(void) | |||
| 1401 | 1522 | ||
| 1402 | INIT_DELAYED_WORK(&wl->elp_work, wl1251_elp_work); | 1523 | INIT_DELAYED_WORK(&wl->elp_work, wl1251_elp_work); |
| 1403 | wl->channel = WL1251_DEFAULT_CHANNEL; | 1524 | wl->channel = WL1251_DEFAULT_CHANNEL; |
| 1525 | wl->monitor_present = false; | ||
| 1526 | wl->joined = false; | ||
| 1404 | wl->scanning = false; | 1527 | wl->scanning = false; |
| 1528 | wl->bss_type = MAX_BSS_TYPE; | ||
| 1405 | wl->default_key = 0; | 1529 | wl->default_key = 0; |
| 1406 | wl->listen_int = 1; | 1530 | wl->listen_int = 1; |
| 1407 | wl->rx_counter = 0; | 1531 | wl->rx_counter = 0; |
| @@ -1413,6 +1537,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void) | |||
| 1413 | wl->elp = false; | 1537 | wl->elp = false; |
| 1414 | wl->station_mode = STATION_ACTIVE_MODE; | 1538 | wl->station_mode = STATION_ACTIVE_MODE; |
| 1415 | wl->psm_requested = false; | 1539 | wl->psm_requested = false; |
| 1540 | wl->psm_entry_retry = 0; | ||
| 1416 | wl->tx_queue_stopped = false; | 1541 | wl->tx_queue_stopped = false; |
| 1417 | wl->power_level = WL1251_DEFAULT_POWER_LEVEL; | 1542 | wl->power_level = WL1251_DEFAULT_POWER_LEVEL; |
| 1418 | wl->rssi_thold = 0; | 1543 | wl->rssi_thold = 0; |
| @@ -1478,3 +1603,4 @@ MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core"); | |||
| 1478 | MODULE_LICENSE("GPL"); | 1603 | MODULE_LICENSE("GPL"); |
| 1479 | MODULE_AUTHOR("Kalle Valo <kvalo@adurom.com>"); | 1604 | MODULE_AUTHOR("Kalle Valo <kvalo@adurom.com>"); |
| 1480 | MODULE_FIRMWARE(WL1251_FW_NAME); | 1605 | MODULE_FIRMWARE(WL1251_FW_NAME); |
| 1606 | MODULE_FIRMWARE(WL1251_NVS_NAME); | ||
diff --git a/drivers/net/wireless/ti/wl1251/rx.c b/drivers/net/wireless/ti/wl1251/rx.c index 23289d49dd31..123c4bb50e0a 100644 --- a/drivers/net/wireless/ti/wl1251/rx.c +++ b/drivers/net/wireless/ti/wl1251/rx.c | |||
| @@ -83,7 +83,7 @@ static void wl1251_rx_status(struct wl1251 *wl, | |||
| 83 | 83 | ||
| 84 | status->flag |= RX_FLAG_MACTIME_START; | 84 | status->flag |= RX_FLAG_MACTIME_START; |
| 85 | 85 | ||
| 86 | if (desc->flags & RX_DESC_ENCRYPTION_MASK) { | 86 | if (!wl->monitor_present && (desc->flags & RX_DESC_ENCRYPTION_MASK)) { |
| 87 | status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; | 87 | status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; |
| 88 | 88 | ||
| 89 | if (likely(!(desc->flags & RX_DESC_DECRYPT_FAIL))) | 89 | if (likely(!(desc->flags & RX_DESC_DECRYPT_FAIL))) |
diff --git a/drivers/net/wireless/ti/wl1251/tx.c b/drivers/net/wireless/ti/wl1251/tx.c index 28121c590a2b..81de83c6fcf6 100644 --- a/drivers/net/wireless/ti/wl1251/tx.c +++ b/drivers/net/wireless/ti/wl1251/tx.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include "tx.h" | 28 | #include "tx.h" |
| 29 | #include "ps.h" | 29 | #include "ps.h" |
| 30 | #include "io.h" | 30 | #include "io.h" |
| 31 | #include "event.h" | ||
| 31 | 32 | ||
| 32 | static bool wl1251_tx_double_buffer_busy(struct wl1251 *wl, u32 data_out_count) | 33 | static bool wl1251_tx_double_buffer_busy(struct wl1251 *wl, u32 data_out_count) |
| 33 | { | 34 | { |
| @@ -89,8 +90,12 @@ static void wl1251_tx_control(struct tx_double_buffer_desc *tx_hdr, | |||
| 89 | /* 802.11 packets */ | 90 | /* 802.11 packets */ |
| 90 | tx_hdr->control.packet_type = 0; | 91 | tx_hdr->control.packet_type = 0; |
| 91 | 92 | ||
| 92 | if (control->flags & IEEE80211_TX_CTL_NO_ACK) | 93 | /* Also disable retry and ACK policy for injected packets */ |
| 94 | if ((control->flags & IEEE80211_TX_CTL_NO_ACK) || | ||
| 95 | (control->flags & IEEE80211_TX_CTL_INJECTED)) { | ||
| 96 | tx_hdr->control.rate_policy = 1; | ||
| 93 | tx_hdr->control.ack_policy = 1; | 97 | tx_hdr->control.ack_policy = 1; |
| 98 | } | ||
| 94 | 99 | ||
| 95 | tx_hdr->control.tx_complete = 1; | 100 | tx_hdr->control.tx_complete = 1; |
| 96 | 101 | ||
| @@ -277,6 +282,26 @@ static void wl1251_tx_trigger(struct wl1251 *wl) | |||
| 277 | TX_STATUS_DATA_OUT_COUNT_MASK; | 282 | TX_STATUS_DATA_OUT_COUNT_MASK; |
| 278 | } | 283 | } |
| 279 | 284 | ||
| 285 | static void enable_tx_for_packet_injection(struct wl1251 *wl) | ||
| 286 | { | ||
| 287 | int ret; | ||
| 288 | |||
| 289 | ret = wl1251_cmd_join(wl, BSS_TYPE_STA_BSS, wl->channel, | ||
| 290 | wl->beacon_int, wl->dtim_period); | ||
| 291 | if (ret < 0) { | ||
| 292 | wl1251_warning("join failed"); | ||
| 293 | return; | ||
| 294 | } | ||
| 295 | |||
| 296 | ret = wl1251_event_wait(wl, JOIN_EVENT_COMPLETE_ID, 100); | ||
| 297 | if (ret < 0) { | ||
| 298 | wl1251_warning("join timeout"); | ||
| 299 | return; | ||
| 300 | } | ||
| 301 | |||
| 302 | wl->joined = true; | ||
| 303 | } | ||
| 304 | |||
| 280 | /* caller must hold wl->mutex */ | 305 | /* caller must hold wl->mutex */ |
| 281 | static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb) | 306 | static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb) |
| 282 | { | 307 | { |
| @@ -287,6 +312,9 @@ static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb) | |||
| 287 | info = IEEE80211_SKB_CB(skb); | 312 | info = IEEE80211_SKB_CB(skb); |
| 288 | 313 | ||
| 289 | if (info->control.hw_key) { | 314 | if (info->control.hw_key) { |
| 315 | if (unlikely(wl->monitor_present)) | ||
| 316 | return -EINVAL; | ||
| 317 | |||
| 290 | idx = info->control.hw_key->hw_key_idx; | 318 | idx = info->control.hw_key->hw_key_idx; |
| 291 | if (unlikely(wl->default_key != idx)) { | 319 | if (unlikely(wl->default_key != idx)) { |
| 292 | ret = wl1251_acx_default_key(wl, idx); | 320 | ret = wl1251_acx_default_key(wl, idx); |
| @@ -295,6 +323,10 @@ static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb) | |||
| 295 | } | 323 | } |
| 296 | } | 324 | } |
| 297 | 325 | ||
| 326 | /* Enable tx path in monitor mode for packet injection */ | ||
| 327 | if ((wl->vif == NULL) && !wl->joined) | ||
| 328 | enable_tx_for_packet_injection(wl); | ||
| 329 | |||
| 298 | ret = wl1251_tx_path_status(wl); | 330 | ret = wl1251_tx_path_status(wl); |
| 299 | if (ret < 0) | 331 | if (ret < 0) |
| 300 | return ret; | 332 | return ret; |
| @@ -394,6 +426,7 @@ static void wl1251_tx_packet_cb(struct wl1251 *wl, | |||
| 394 | info = IEEE80211_SKB_CB(skb); | 426 | info = IEEE80211_SKB_CB(skb); |
| 395 | 427 | ||
| 396 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && | 428 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && |
| 429 | !(info->flags & IEEE80211_TX_CTL_INJECTED) && | ||
| 397 | (result->status == TX_SUCCESS)) | 430 | (result->status == TX_SUCCESS)) |
| 398 | info->flags |= IEEE80211_TX_STAT_ACK; | 431 | info->flags |= IEEE80211_TX_STAT_ACK; |
| 399 | 432 | ||
diff --git a/drivers/net/wireless/ti/wl1251/wl1251.h b/drivers/net/wireless/ti/wl1251/wl1251.h index 2c3bd1bff3f6..235617a7716d 100644 --- a/drivers/net/wireless/ti/wl1251/wl1251.h +++ b/drivers/net/wireless/ti/wl1251/wl1251.h | |||
| @@ -93,6 +93,7 @@ enum { | |||
| 93 | } while (0) | 93 | } while (0) |
| 94 | 94 | ||
| 95 | #define WL1251_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \ | 95 | #define WL1251_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \ |
| 96 | CFG_MC_FILTER_EN | \ | ||
| 96 | CFG_BSSID_FILTER_EN) | 97 | CFG_BSSID_FILTER_EN) |
| 97 | 98 | ||
| 98 | #define WL1251_DEFAULT_RX_FILTER (CFG_RX_PRSP_EN | \ | 99 | #define WL1251_DEFAULT_RX_FILTER (CFG_RX_PRSP_EN | \ |
| @@ -303,6 +304,8 @@ struct wl1251 { | |||
| 303 | u8 bss_type; | 304 | u8 bss_type; |
| 304 | u8 listen_int; | 305 | u8 listen_int; |
| 305 | int channel; | 306 | int channel; |
| 307 | bool monitor_present; | ||
| 308 | bool joined; | ||
| 306 | 309 | ||
| 307 | void *target_mem_map; | 310 | void *target_mem_map; |
| 308 | struct acx_data_path_params_resp *data_path; | 311 | struct acx_data_path_params_resp *data_path; |
| @@ -368,6 +371,9 @@ struct wl1251 { | |||
| 368 | /* PSM mode requested */ | 371 | /* PSM mode requested */ |
| 369 | bool psm_requested; | 372 | bool psm_requested; |
| 370 | 373 | ||
| 374 | /* retry counter for PSM entries */ | ||
| 375 | u8 psm_entry_retry; | ||
| 376 | |||
| 371 | u16 beacon_int; | 377 | u16 beacon_int; |
| 372 | u8 dtim_period; | 378 | u8 dtim_period; |
| 373 | 379 | ||
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 1477d7f05905..d24d4a958c67 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c | |||
| @@ -29,7 +29,6 @@ | |||
| 29 | 29 | ||
| 30 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
| 31 | #include <linux/types.h> | 31 | #include <linux/types.h> |
| 32 | #include <linux/init.h> | ||
| 33 | #include <linux/interrupt.h> | 32 | #include <linux/interrupt.h> |
| 34 | #include <linux/in.h> | 33 | #include <linux/in.h> |
| 35 | #include <linux/kernel.h> | 34 | #include <linux/kernel.h> |
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index c955fc39d69a..4c76bcb9a879 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h | |||
| @@ -143,6 +143,7 @@ struct xenvif { | |||
| 143 | char rx_irq_name[IFNAMSIZ+4]; /* DEVNAME-rx */ | 143 | char rx_irq_name[IFNAMSIZ+4]; /* DEVNAME-rx */ |
| 144 | struct xen_netif_rx_back_ring rx; | 144 | struct xen_netif_rx_back_ring rx; |
| 145 | struct sk_buff_head rx_queue; | 145 | struct sk_buff_head rx_queue; |
| 146 | bool rx_queue_stopped; | ||
| 146 | /* Set when the RX interrupt is triggered by the frontend. | 147 | /* Set when the RX interrupt is triggered by the frontend. |
| 147 | * The worker thread may need to wake the queue. | 148 | * The worker thread may need to wake the queue. |
| 148 | */ | 149 | */ |
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 4f81ac0e2f0a..27385639b6e5 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c | |||
| @@ -476,7 +476,8 @@ static void xenvif_rx_action(struct xenvif *vif) | |||
| 476 | int ret; | 476 | int ret; |
| 477 | unsigned long offset; | 477 | unsigned long offset; |
| 478 | struct skb_cb_overlay *sco; | 478 | struct skb_cb_overlay *sco; |
| 479 | int need_to_notify = 0; | 479 | bool need_to_notify = false; |
| 480 | bool ring_full = false; | ||
| 480 | 481 | ||
| 481 | struct netrx_pending_operations npo = { | 482 | struct netrx_pending_operations npo = { |
| 482 | .copy = vif->grant_copy_op, | 483 | .copy = vif->grant_copy_op, |
| @@ -508,7 +509,8 @@ static void xenvif_rx_action(struct xenvif *vif) | |||
| 508 | /* If the skb may not fit then bail out now */ | 509 | /* If the skb may not fit then bail out now */ |
| 509 | if (!xenvif_rx_ring_slots_available(vif, max_slots_needed)) { | 510 | if (!xenvif_rx_ring_slots_available(vif, max_slots_needed)) { |
| 510 | skb_queue_head(&vif->rx_queue, skb); | 511 | skb_queue_head(&vif->rx_queue, skb); |
| 511 | need_to_notify = 1; | 512 | need_to_notify = true; |
| 513 | ring_full = true; | ||
| 512 | break; | 514 | break; |
| 513 | } | 515 | } |
| 514 | 516 | ||
| @@ -521,6 +523,8 @@ static void xenvif_rx_action(struct xenvif *vif) | |||
| 521 | 523 | ||
| 522 | BUG_ON(npo.meta_prod > ARRAY_SIZE(vif->meta)); | 524 | BUG_ON(npo.meta_prod > ARRAY_SIZE(vif->meta)); |
| 523 | 525 | ||
| 526 | vif->rx_queue_stopped = !npo.copy_prod && ring_full; | ||
| 527 | |||
| 524 | if (!npo.copy_prod) | 528 | if (!npo.copy_prod) |
| 525 | goto done; | 529 | goto done; |
| 526 | 530 | ||
| @@ -592,8 +596,7 @@ static void xenvif_rx_action(struct xenvif *vif) | |||
| 592 | 596 | ||
| 593 | RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&vif->rx, ret); | 597 | RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&vif->rx, ret); |
| 594 | 598 | ||
| 595 | if (ret) | 599 | need_to_notify |= !!ret; |
| 596 | need_to_notify = 1; | ||
| 597 | 600 | ||
| 598 | npo.meta_cons += sco->meta_slots_used; | 601 | npo.meta_cons += sco->meta_slots_used; |
| 599 | dev_kfree_skb(skb); | 602 | dev_kfree_skb(skb); |
| @@ -1724,7 +1727,8 @@ static struct xen_netif_rx_response *make_rx_response(struct xenvif *vif, | |||
| 1724 | 1727 | ||
| 1725 | static inline int rx_work_todo(struct xenvif *vif) | 1728 | static inline int rx_work_todo(struct xenvif *vif) |
| 1726 | { | 1729 | { |
| 1727 | return !skb_queue_empty(&vif->rx_queue) || vif->rx_event; | 1730 | return (!skb_queue_empty(&vif->rx_queue) && !vif->rx_queue_stopped) || |
| 1731 | vif->rx_event; | ||
| 1728 | } | 1732 | } |
| 1729 | 1733 | ||
| 1730 | static inline int tx_work_todo(struct xenvif *vif) | 1734 | static inline int tx_work_todo(struct xenvif *vif) |
diff --git a/drivers/ssb/driver_chipcommon_sflash.c b/drivers/ssb/driver_chipcommon_sflash.c index 50328de712fa..937fc31971a7 100644 --- a/drivers/ssb/driver_chipcommon_sflash.c +++ b/drivers/ssb/driver_chipcommon_sflash.c | |||
| @@ -37,7 +37,7 @@ static const struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = { | |||
| 37 | { "M25P32", 0x15, 0x10000, 64, }, | 37 | { "M25P32", 0x15, 0x10000, 64, }, |
| 38 | { "M25P64", 0x16, 0x10000, 128, }, | 38 | { "M25P64", 0x16, 0x10000, 128, }, |
| 39 | { "M25FL128", 0x17, 0x10000, 256, }, | 39 | { "M25FL128", 0x17, 0x10000, 256, }, |
| 40 | { 0 }, | 40 | { NULL }, |
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | static const struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { | 43 | static const struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { |
| @@ -55,7 +55,7 @@ static const struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { | |||
| 55 | { "SST25VF016", 0x41, 0x1000, 512, }, | 55 | { "SST25VF016", 0x41, 0x1000, 512, }, |
| 56 | { "SST25VF032", 0x4a, 0x1000, 1024, }, | 56 | { "SST25VF032", 0x4a, 0x1000, 1024, }, |
| 57 | { "SST25VF064", 0x4b, 0x1000, 2048, }, | 57 | { "SST25VF064", 0x4b, 0x1000, 2048, }, |
| 58 | { 0 }, | 58 | { NULL }, |
| 59 | }; | 59 | }; |
| 60 | 60 | ||
| 61 | static const struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { | 61 | static const struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { |
| @@ -66,7 +66,7 @@ static const struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { | |||
| 66 | { "AT45DB161", 0x2c, 512, 4096, }, | 66 | { "AT45DB161", 0x2c, 512, 4096, }, |
| 67 | { "AT45DB321", 0x34, 512, 8192, }, | 67 | { "AT45DB321", 0x34, 512, 8192, }, |
| 68 | { "AT45DB642", 0x3c, 1024, 8192, }, | 68 | { "AT45DB642", 0x3c, 1024, 8192, }, |
| 69 | { 0 }, | 69 | { NULL }, |
| 70 | }; | 70 | }; |
| 71 | 71 | ||
| 72 | static void ssb_sflash_cmd(struct ssb_chipcommon *cc, u32 opcode) | 72 | static void ssb_sflash_cmd(struct ssb_chipcommon *cc, u32 opcode) |
diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h index 9f03feedc8e7..d8836623f36a 100644 --- a/include/linux/mmc/sdio_ids.h +++ b/include/linux/mmc/sdio_ids.h | |||
| @@ -23,6 +23,15 @@ | |||
| 23 | /* | 23 | /* |
| 24 | * Vendors and devices. Sort key: vendor first, device next. | 24 | * Vendors and devices. Sort key: vendor first, device next. |
| 25 | */ | 25 | */ |
| 26 | #define SDIO_VENDOR_ID_BROADCOM 0x02d0 | ||
| 27 | #define SDIO_DEVICE_ID_BROADCOM_43143 43143 | ||
| 28 | #define SDIO_DEVICE_ID_BROADCOM_43241 0x4324 | ||
| 29 | #define SDIO_DEVICE_ID_BROADCOM_4329 0x4329 | ||
| 30 | #define SDIO_DEVICE_ID_BROADCOM_4330 0x4330 | ||
| 31 | #define SDIO_DEVICE_ID_BROADCOM_4334 0x4334 | ||
| 32 | #define SDIO_DEVICE_ID_BROADCOM_4335_4339 0x4335 | ||
| 33 | #define SDIO_DEVICE_ID_BROADCOM_43362 43362 | ||
| 34 | |||
| 26 | #define SDIO_VENDOR_ID_INTEL 0x0089 | 35 | #define SDIO_VENDOR_ID_INTEL 0x0089 |
| 27 | #define SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX 0x1402 | 36 | #define SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX 0x1402 |
| 28 | #define SDIO_DEVICE_ID_INTEL_IWMC3200WIFI 0x1403 | 37 | #define SDIO_DEVICE_ID_INTEL_IWMC3200WIFI 0x1403 |
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index cc2da73055fa..66c1cd87bfe7 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h | |||
| @@ -83,7 +83,8 @@ | |||
| 83 | enum { | 83 | enum { |
| 84 | HCI_QUIRK_RESET_ON_CLOSE, | 84 | HCI_QUIRK_RESET_ON_CLOSE, |
| 85 | HCI_QUIRK_RAW_DEVICE, | 85 | HCI_QUIRK_RAW_DEVICE, |
| 86 | HCI_QUIRK_FIXUP_BUFFER_SIZE | 86 | HCI_QUIRK_FIXUP_BUFFER_SIZE, |
| 87 | HCI_QUIRK_BROKEN_STORED_LINK_KEY, | ||
| 87 | }; | 88 | }; |
| 88 | 89 | ||
| 89 | /* HCI device flags */ | 90 | /* HCI device flags */ |
| @@ -131,6 +132,7 @@ enum { | |||
| 131 | HCI_PERIODIC_INQ, | 132 | HCI_PERIODIC_INQ, |
| 132 | HCI_FAST_CONNECTABLE, | 133 | HCI_FAST_CONNECTABLE, |
| 133 | HCI_BREDR_ENABLED, | 134 | HCI_BREDR_ENABLED, |
| 135 | HCI_6LOWPAN_ENABLED, | ||
| 134 | }; | 136 | }; |
| 135 | 137 | ||
| 136 | /* A mask for the flags that are supposed to remain when a reset happens | 138 | /* A mask for the flags that are supposed to remain when a reset happens |
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index b796161fb04e..f2f0cf5865c4 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
| @@ -448,6 +448,7 @@ enum { | |||
| 448 | HCI_CONN_SSP_ENABLED, | 448 | HCI_CONN_SSP_ENABLED, |
| 449 | HCI_CONN_POWER_SAVE, | 449 | HCI_CONN_POWER_SAVE, |
| 450 | HCI_CONN_REMOTE_OOB, | 450 | HCI_CONN_REMOTE_OOB, |
| 451 | HCI_CONN_6LOWPAN, | ||
| 451 | }; | 452 | }; |
| 452 | 453 | ||
| 453 | static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) | 454 | static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) |
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index e149e992fdae..dbc4a89984ca 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
| @@ -136,6 +136,7 @@ struct l2cap_conninfo { | |||
| 136 | #define L2CAP_FC_L2CAP 0x02 | 136 | #define L2CAP_FC_L2CAP 0x02 |
| 137 | #define L2CAP_FC_CONNLESS 0x04 | 137 | #define L2CAP_FC_CONNLESS 0x04 |
| 138 | #define L2CAP_FC_A2MP 0x08 | 138 | #define L2CAP_FC_A2MP 0x08 |
| 139 | #define L2CAP_FC_6LOWPAN 0x3e /* reserved and temporary value */ | ||
| 139 | 140 | ||
| 140 | /* L2CAP Control Field bit masks */ | 141 | /* L2CAP Control Field bit masks */ |
| 141 | #define L2CAP_CTRL_SAR 0xC000 | 142 | #define L2CAP_CTRL_SAR 0xC000 |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 80a10212b1b9..56c597793d6d 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
| @@ -1972,6 +1972,50 @@ struct cfg80211_mgmt_tx_params { | |||
| 1972 | }; | 1972 | }; |
| 1973 | 1973 | ||
| 1974 | /** | 1974 | /** |
| 1975 | * struct cfg80211_dscp_exception - DSCP exception | ||
| 1976 | * | ||
| 1977 | * @dscp: DSCP value that does not adhere to the user priority range definition | ||
| 1978 | * @up: user priority value to which the corresponding DSCP value belongs | ||
| 1979 | */ | ||
| 1980 | struct cfg80211_dscp_exception { | ||
| 1981 | u8 dscp; | ||
| 1982 | u8 up; | ||
| 1983 | }; | ||
| 1984 | |||
| 1985 | /** | ||
| 1986 | * struct cfg80211_dscp_range - DSCP range definition for user priority | ||
| 1987 | * | ||
| 1988 | * @low: lowest DSCP value of this user priority range, inclusive | ||
| 1989 | * @high: highest DSCP value of this user priority range, inclusive | ||
| 1990 | */ | ||
| 1991 | struct cfg80211_dscp_range { | ||
| 1992 | u8 low; | ||
| 1993 | u8 high; | ||
| 1994 | }; | ||
| 1995 | |||
| 1996 | /* QoS Map Set element length defined in IEEE Std 802.11-2012, 8.4.2.97 */ | ||
| 1997 | #define IEEE80211_QOS_MAP_MAX_EX 21 | ||
| 1998 | #define IEEE80211_QOS_MAP_LEN_MIN 16 | ||
| 1999 | #define IEEE80211_QOS_MAP_LEN_MAX \ | ||
| 2000 | (IEEE80211_QOS_MAP_LEN_MIN + 2 * IEEE80211_QOS_MAP_MAX_EX) | ||
| 2001 | |||
| 2002 | /** | ||
| 2003 | * struct cfg80211_qos_map - QoS Map Information | ||
| 2004 | * | ||
| 2005 | * This struct defines the Interworking QoS map setting for DSCP values | ||
| 2006 | * | ||
| 2007 | * @num_des: number of DSCP exceptions (0..21) | ||
| 2008 | * @dscp_exception: optionally up to maximum of 21 DSCP exceptions from | ||
| 2009 | * the user priority DSCP range definition | ||
| 2010 | * @up: DSCP range definition for a particular user priority | ||
| 2011 | */ | ||
| 2012 | struct cfg80211_qos_map { | ||
| 2013 | u8 num_des; | ||
| 2014 | struct cfg80211_dscp_exception dscp_exception[IEEE80211_QOS_MAP_MAX_EX]; | ||
| 2015 | struct cfg80211_dscp_range up[8]; | ||
| 2016 | }; | ||
| 2017 | |||
| 2018 | /** | ||
| 1975 | * struct cfg80211_ops - backend description for wireless configuration | 2019 | * struct cfg80211_ops - backend description for wireless configuration |
| 1976 | * | 2020 | * |
| 1977 | * This struct is registered by fullmac card drivers and/or wireless stacks | 2021 | * This struct is registered by fullmac card drivers and/or wireless stacks |
| @@ -2213,6 +2257,8 @@ struct cfg80211_mgmt_tx_params { | |||
| 2213 | * @set_coalesce: Set coalesce parameters. | 2257 | * @set_coalesce: Set coalesce parameters. |
| 2214 | * | 2258 | * |
| 2215 | * @channel_switch: initiate channel-switch procedure (with CSA) | 2259 | * @channel_switch: initiate channel-switch procedure (with CSA) |
| 2260 | * | ||
| 2261 | * @set_qos_map: Set QoS mapping information to the driver | ||
| 2216 | */ | 2262 | */ |
| 2217 | struct cfg80211_ops { | 2263 | struct cfg80211_ops { |
| 2218 | int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); | 2264 | int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); |
| @@ -2454,6 +2500,9 @@ struct cfg80211_ops { | |||
| 2454 | int (*channel_switch)(struct wiphy *wiphy, | 2500 | int (*channel_switch)(struct wiphy *wiphy, |
| 2455 | struct net_device *dev, | 2501 | struct net_device *dev, |
| 2456 | struct cfg80211_csa_settings *params); | 2502 | struct cfg80211_csa_settings *params); |
| 2503 | int (*set_qos_map)(struct wiphy *wiphy, | ||
| 2504 | struct net_device *dev, | ||
| 2505 | struct cfg80211_qos_map *qos_map); | ||
| 2457 | }; | 2506 | }; |
| 2458 | 2507 | ||
| 2459 | /* | 2508 | /* |
| @@ -2824,6 +2873,8 @@ struct wiphy_vendor_command { | |||
| 2824 | * | 2873 | * |
| 2825 | * @vendor_commands: array of vendor commands supported by the hardware | 2874 | * @vendor_commands: array of vendor commands supported by the hardware |
| 2826 | * @n_vendor_commands: number of vendor commands | 2875 | * @n_vendor_commands: number of vendor commands |
| 2876 | * @vendor_events: array of vendor events supported by the hardware | ||
| 2877 | * @n_vendor_events: number of vendor events | ||
| 2827 | */ | 2878 | */ |
| 2828 | struct wiphy { | 2879 | struct wiphy { |
| 2829 | /* assign these fields before you register the wiphy */ | 2880 | /* assign these fields before you register the wiphy */ |
| @@ -2936,7 +2987,8 @@ struct wiphy { | |||
| 2936 | const struct wiphy_coalesce_support *coalesce; | 2987 | const struct wiphy_coalesce_support *coalesce; |
| 2937 | 2988 | ||
| 2938 | const struct wiphy_vendor_command *vendor_commands; | 2989 | const struct wiphy_vendor_command *vendor_commands; |
| 2939 | int n_vendor_commands; | 2990 | const struct nl80211_vendor_cmd_info *vendor_events; |
| 2991 | int n_vendor_commands, n_vendor_events; | ||
| 2940 | 2992 | ||
| 2941 | char priv[0] __aligned(NETDEV_ALIGN); | 2993 | char priv[0] __aligned(NETDEV_ALIGN); |
| 2942 | }; | 2994 | }; |
| @@ -3429,9 +3481,11 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, | |||
| 3429 | /** | 3481 | /** |
| 3430 | * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame | 3482 | * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame |
| 3431 | * @skb: the data frame | 3483 | * @skb: the data frame |
| 3484 | * @qos_map: Interworking QoS mapping or %NULL if not in use | ||
| 3432 | * Return: The 802.1p/1d tag. | 3485 | * Return: The 802.1p/1d tag. |
| 3433 | */ | 3486 | */ |
| 3434 | unsigned int cfg80211_classify8021d(struct sk_buff *skb); | 3487 | unsigned int cfg80211_classify8021d(struct sk_buff *skb, |
| 3488 | struct cfg80211_qos_map *qos_map); | ||
| 3435 | 3489 | ||
| 3436 | /** | 3490 | /** |
| 3437 | * cfg80211_find_ie - find information element in data | 3491 | * cfg80211_find_ie - find information element in data |
| @@ -3907,6 +3961,14 @@ struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy, | |||
| 3907 | enum nl80211_attrs attr, | 3961 | enum nl80211_attrs attr, |
| 3908 | int approxlen); | 3962 | int approxlen); |
| 3909 | 3963 | ||
| 3964 | struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy, | ||
| 3965 | enum nl80211_commands cmd, | ||
| 3966 | enum nl80211_attrs attr, | ||
| 3967 | int vendor_event_idx, | ||
| 3968 | int approxlen, gfp_t gfp); | ||
| 3969 | |||
| 3970 | void __cfg80211_send_event_skb(struct sk_buff *skb, gfp_t gfp); | ||
| 3971 | |||
| 3910 | /** | 3972 | /** |
| 3911 | * cfg80211_vendor_cmd_alloc_reply_skb - allocate vendor command reply | 3973 | * cfg80211_vendor_cmd_alloc_reply_skb - allocate vendor command reply |
| 3912 | * @wiphy: the wiphy | 3974 | * @wiphy: the wiphy |
| @@ -3951,6 +4013,44 @@ cfg80211_vendor_cmd_alloc_reply_skb(struct wiphy *wiphy, int approxlen) | |||
| 3951 | */ | 4013 | */ |
| 3952 | int cfg80211_vendor_cmd_reply(struct sk_buff *skb); | 4014 | int cfg80211_vendor_cmd_reply(struct sk_buff *skb); |
| 3953 | 4015 | ||
| 4016 | /** | ||
| 4017 | * cfg80211_vendor_event_alloc - allocate vendor-specific event skb | ||
| 4018 | * @wiphy: the wiphy | ||
| 4019 | * @event_idx: index of the vendor event in the wiphy's vendor_events | ||
| 4020 | * @approxlen: an upper bound of the length of the data that will | ||
| 4021 | * be put into the skb | ||
| 4022 | * @gfp: allocation flags | ||
| 4023 | * | ||
| 4024 | * This function allocates and pre-fills an skb for an event on the | ||
| 4025 | * vendor-specific multicast group. | ||
| 4026 | * | ||
| 4027 | * When done filling the skb, call cfg80211_vendor_event() with the | ||
| 4028 | * skb to send the event. | ||
| 4029 | * | ||
| 4030 | * Return: An allocated and pre-filled skb. %NULL if any errors happen. | ||
| 4031 | */ | ||
| 4032 | static inline struct sk_buff * | ||
| 4033 | cfg80211_vendor_event_alloc(struct wiphy *wiphy, int approxlen, | ||
| 4034 | int event_idx, gfp_t gfp) | ||
| 4035 | { | ||
| 4036 | return __cfg80211_alloc_event_skb(wiphy, NL80211_CMD_VENDOR, | ||
| 4037 | NL80211_ATTR_VENDOR_DATA, | ||
| 4038 | event_idx, approxlen, gfp); | ||
| 4039 | } | ||
| 4040 | |||
| 4041 | /** | ||
| 4042 | * cfg80211_vendor_event - send the event | ||
| 4043 | * @skb: The skb, must have been allocated with cfg80211_vendor_event_alloc() | ||
| 4044 | * @gfp: allocation flags | ||
| 4045 | * | ||
| 4046 | * This function sends the given @skb, which must have been allocated | ||
| 4047 | * by cfg80211_vendor_event_alloc(), as an event. It always consumes it. | ||
| 4048 | */ | ||
| 4049 | static inline void cfg80211_vendor_event(struct sk_buff *skb, gfp_t gfp) | ||
| 4050 | { | ||
| 4051 | __cfg80211_send_event_skb(skb, gfp); | ||
| 4052 | } | ||
| 4053 | |||
| 3954 | #ifdef CONFIG_NL80211_TESTMODE | 4054 | #ifdef CONFIG_NL80211_TESTMODE |
| 3955 | /** | 4055 | /** |
| 3956 | * DOC: Test mode | 4056 | * DOC: Test mode |
| @@ -4031,8 +4131,13 @@ static inline int cfg80211_testmode_reply(struct sk_buff *skb) | |||
| 4031 | * | 4131 | * |
| 4032 | * Return: An allocated and pre-filled skb. %NULL if any errors happen. | 4132 | * Return: An allocated and pre-filled skb. %NULL if any errors happen. |
| 4033 | */ | 4133 | */ |
| 4034 | struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy, | 4134 | static inline struct sk_buff * |
| 4035 | int approxlen, gfp_t gfp); | 4135 | cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy, int approxlen, gfp_t gfp) |
| 4136 | { | ||
| 4137 | return __cfg80211_alloc_event_skb(wiphy, NL80211_CMD_TESTMODE, | ||
| 4138 | NL80211_ATTR_TESTDATA, -1, | ||
| 4139 | approxlen, gfp); | ||
| 4140 | } | ||
| 4036 | 4141 | ||
| 4037 | /** | 4142 | /** |
| 4038 | * cfg80211_testmode_event - send the event | 4143 | * cfg80211_testmode_event - send the event |
| @@ -4044,7 +4149,10 @@ struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy, | |||
| 4044 | * by cfg80211_testmode_alloc_event_skb(), as an event. It always | 4149 | * by cfg80211_testmode_alloc_event_skb(), as an event. It always |
| 4045 | * consumes it. | 4150 | * consumes it. |
| 4046 | */ | 4151 | */ |
| 4047 | void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp); | 4152 | static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp) |
| 4153 | { | ||
| 4154 | __cfg80211_send_event_skb(skb, gfp); | ||
| 4155 | } | ||
| 4048 | 4156 | ||
| 4049 | #define CFG80211_TESTMODE_CMD(cmd) .testmode_cmd = (cmd), | 4157 | #define CFG80211_TESTMODE_CMD(cmd) .testmode_cmd = (cmd), |
| 4050 | #define CFG80211_TESTMODE_DUMP(cmd) .testmode_dump = (cmd), | 4158 | #define CFG80211_TESTMODE_DUMP(cmd) .testmode_dump = (cmd), |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 531785f5819e..f838af816b56 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
| @@ -4652,4 +4652,51 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw, | |||
| 4652 | struct ieee80211_vif *vif, struct sk_buff *skb, | 4652 | struct ieee80211_vif *vif, struct sk_buff *skb, |
| 4653 | int band, struct ieee80211_sta **sta); | 4653 | int band, struct ieee80211_sta **sta); |
| 4654 | 4654 | ||
| 4655 | /** | ||
| 4656 | * struct ieee80211_noa_data - holds temporary data for tracking P2P NoA state | ||
| 4657 | * | ||
| 4658 | * @next_tsf: TSF timestamp of the next absent state change | ||
| 4659 | * @has_next_tsf: next absent state change event pending | ||
| 4660 | * | ||
| 4661 | * @absent: descriptor bitmask, set if GO is currently absent | ||
| 4662 | * | ||
| 4663 | * private: | ||
| 4664 | * | ||
| 4665 | * @count: count fields from the NoA descriptors | ||
| 4666 | * @desc: adjusted data from the NoA | ||
| 4667 | */ | ||
| 4668 | struct ieee80211_noa_data { | ||
| 4669 | u32 next_tsf; | ||
| 4670 | bool has_next_tsf; | ||
| 4671 | |||
| 4672 | u8 absent; | ||
| 4673 | |||
| 4674 | u8 count[IEEE80211_P2P_NOA_DESC_MAX]; | ||
| 4675 | struct { | ||
| 4676 | u32 start; | ||
| 4677 | u32 duration; | ||
| 4678 | u32 interval; | ||
| 4679 | } desc[IEEE80211_P2P_NOA_DESC_MAX]; | ||
| 4680 | }; | ||
| 4681 | |||
| 4682 | /** | ||
| 4683 | * ieee80211_parse_p2p_noa - initialize NoA tracking data from P2P IE | ||
| 4684 | * | ||
| 4685 | * @attr: P2P NoA IE | ||
| 4686 | * @data: NoA tracking data | ||
| 4687 | * @tsf: current TSF timestamp | ||
| 4688 | * | ||
| 4689 | * Return: number of successfully parsed descriptors | ||
| 4690 | */ | ||
| 4691 | int ieee80211_parse_p2p_noa(const struct ieee80211_p2p_noa_attr *attr, | ||
| 4692 | struct ieee80211_noa_data *data, u32 tsf); | ||
| 4693 | |||
| 4694 | /** | ||
| 4695 | * ieee80211_update_p2p_noa - get next pending P2P GO absent state change | ||
| 4696 | * | ||
| 4697 | * @data: NoA tracking data | ||
| 4698 | * @tsf: current TSF timestamp | ||
| 4699 | */ | ||
| 4700 | void ieee80211_update_p2p_noa(struct ieee80211_noa_data *data, u32 tsf); | ||
| 4701 | |||
| 4655 | #endif /* MAC80211_H */ | 4702 | #endif /* MAC80211_H */ |
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 5a91abfc0c30..57c8ff7955df 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h | |||
| @@ -13,9 +13,10 @@ struct nft_pktinfo { | |||
| 13 | struct sk_buff *skb; | 13 | struct sk_buff *skb; |
| 14 | const struct net_device *in; | 14 | const struct net_device *in; |
| 15 | const struct net_device *out; | 15 | const struct net_device *out; |
| 16 | u8 hooknum; | 16 | const struct nf_hook_ops *ops; |
| 17 | u8 nhoff; | 17 | u8 nhoff; |
| 18 | u8 thoff; | 18 | u8 thoff; |
| 19 | u8 tprot; | ||
| 19 | /* for x_tables compatibility */ | 20 | /* for x_tables compatibility */ |
| 20 | struct xt_action_param xt; | 21 | struct xt_action_param xt; |
| 21 | }; | 22 | }; |
| @@ -29,7 +30,8 @@ static inline void nft_set_pktinfo(struct nft_pktinfo *pkt, | |||
| 29 | pkt->skb = skb; | 30 | pkt->skb = skb; |
| 30 | pkt->in = pkt->xt.in = in; | 31 | pkt->in = pkt->xt.in = in; |
| 31 | pkt->out = pkt->xt.out = out; | 32 | pkt->out = pkt->xt.out = out; |
| 32 | pkt->hooknum = pkt->xt.hooknum = ops->hooknum; | 33 | pkt->ops = ops; |
| 34 | pkt->xt.hooknum = ops->hooknum; | ||
| 33 | pkt->xt.family = ops->pf; | 35 | pkt->xt.family = ops->pf; |
| 34 | } | 36 | } |
| 35 | 37 | ||
| @@ -421,6 +423,8 @@ struct nft_stats { | |||
| 421 | u64 pkts; | 423 | u64 pkts; |
| 422 | }; | 424 | }; |
| 423 | 425 | ||
| 426 | #define NFT_HOOK_OPS_MAX 2 | ||
| 427 | |||
| 424 | /** | 428 | /** |
| 425 | * struct nft_base_chain - nf_tables base chain | 429 | * struct nft_base_chain - nf_tables base chain |
| 426 | * | 430 | * |
| @@ -431,8 +435,8 @@ struct nft_stats { | |||
| 431 | * @chain: the chain | 435 | * @chain: the chain |
| 432 | */ | 436 | */ |
| 433 | struct nft_base_chain { | 437 | struct nft_base_chain { |
| 434 | struct nf_hook_ops ops; | 438 | struct nf_hook_ops ops[NFT_HOOK_OPS_MAX]; |
| 435 | enum nft_chain_type type; | 439 | const struct nf_chain_type *type; |
| 436 | u8 policy; | 440 | u8 policy; |
| 437 | struct nft_stats __percpu *stats; | 441 | struct nft_stats __percpu *stats; |
| 438 | struct nft_chain chain; | 442 | struct nft_chain chain; |
| @@ -443,8 +447,8 @@ static inline struct nft_base_chain *nft_base_chain(const struct nft_chain *chai | |||
| 443 | return container_of(chain, struct nft_base_chain, chain); | 447 | return container_of(chain, struct nft_base_chain, chain); |
| 444 | } | 448 | } |
| 445 | 449 | ||
| 446 | unsigned int nft_do_chain_pktinfo(struct nft_pktinfo *pkt, | 450 | unsigned int nft_do_chain(struct nft_pktinfo *pkt, |
| 447 | const struct nf_hook_ops *ops); | 451 | const struct nf_hook_ops *ops); |
| 448 | 452 | ||
| 449 | /** | 453 | /** |
| 450 | * struct nft_table - nf_tables table | 454 | * struct nft_table - nf_tables table |
| @@ -475,6 +479,8 @@ struct nft_table { | |||
| 475 | * @nhooks: number of hooks in this family | 479 | * @nhooks: number of hooks in this family |
| 476 | * @owner: module owner | 480 | * @owner: module owner |
| 477 | * @tables: used internally | 481 | * @tables: used internally |
| 482 | * @nops: number of hook ops in this family | ||
| 483 | * @hook_ops_init: initialization function for chain hook ops | ||
| 478 | * @hooks: hookfn overrides for packet validation | 484 | * @hooks: hookfn overrides for packet validation |
| 479 | */ | 485 | */ |
| 480 | struct nft_af_info { | 486 | struct nft_af_info { |
| @@ -483,23 +489,36 @@ struct nft_af_info { | |||
| 483 | unsigned int nhooks; | 489 | unsigned int nhooks; |
| 484 | struct module *owner; | 490 | struct module *owner; |
| 485 | struct list_head tables; | 491 | struct list_head tables; |
| 492 | unsigned int nops; | ||
| 493 | void (*hook_ops_init)(struct nf_hook_ops *, | ||
| 494 | unsigned int); | ||
| 486 | nf_hookfn *hooks[NF_MAX_HOOKS]; | 495 | nf_hookfn *hooks[NF_MAX_HOOKS]; |
| 487 | }; | 496 | }; |
| 488 | 497 | ||
| 489 | int nft_register_afinfo(struct net *, struct nft_af_info *); | 498 | int nft_register_afinfo(struct net *, struct nft_af_info *); |
| 490 | void nft_unregister_afinfo(struct nft_af_info *); | 499 | void nft_unregister_afinfo(struct nft_af_info *); |
| 491 | 500 | ||
| 501 | /** | ||
| 502 | * struct nf_chain_type - nf_tables chain type info | ||
| 503 | * | ||
| 504 | * @name: name of the type | ||
| 505 | * @type: numeric identifier | ||
| 506 | * @family: address family | ||
| 507 | * @owner: module owner | ||
| 508 | * @hook_mask: mask of valid hooks | ||
| 509 | * @hooks: hookfn overrides | ||
| 510 | */ | ||
| 492 | struct nf_chain_type { | 511 | struct nf_chain_type { |
| 493 | unsigned int hook_mask; | 512 | const char *name; |
| 494 | const char *name; | 513 | enum nft_chain_type type; |
| 495 | enum nft_chain_type type; | 514 | int family; |
| 496 | nf_hookfn *fn[NF_MAX_HOOKS]; | 515 | struct module *owner; |
| 497 | struct module *me; | 516 | unsigned int hook_mask; |
| 498 | int family; | 517 | nf_hookfn *hooks[NF_MAX_HOOKS]; |
| 499 | }; | 518 | }; |
| 500 | 519 | ||
| 501 | int nft_register_chain_type(struct nf_chain_type *); | 520 | int nft_register_chain_type(const struct nf_chain_type *); |
| 502 | void nft_unregister_chain_type(struct nf_chain_type *); | 521 | void nft_unregister_chain_type(const struct nf_chain_type *); |
| 503 | 522 | ||
| 504 | int nft_register_expr(struct nft_expr_type *); | 523 | int nft_register_expr(struct nft_expr_type *); |
| 505 | void nft_unregister_expr(struct nft_expr_type *); | 524 | void nft_unregister_expr(struct nft_expr_type *); |
diff --git a/include/net/netfilter/nf_tables_ipv4.h b/include/net/netfilter/nf_tables_ipv4.h index 1be1c2c197ee..cba143fbd2e4 100644 --- a/include/net/netfilter/nf_tables_ipv4.h +++ b/include/net/netfilter/nf_tables_ipv4.h | |||
| @@ -15,9 +15,12 @@ nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt, | |||
| 15 | 15 | ||
| 16 | nft_set_pktinfo(pkt, ops, skb, in, out); | 16 | nft_set_pktinfo(pkt, ops, skb, in, out); |
| 17 | 17 | ||
| 18 | pkt->xt.thoff = ip_hdrlen(pkt->skb); | ||
| 19 | ip = ip_hdr(pkt->skb); | 18 | ip = ip_hdr(pkt->skb); |
| 19 | pkt->tprot = ip->protocol; | ||
| 20 | pkt->xt.thoff = ip_hdrlen(pkt->skb); | ||
| 20 | pkt->xt.fragoff = ntohs(ip->frag_off) & IP_OFFSET; | 21 | pkt->xt.fragoff = ntohs(ip->frag_off) & IP_OFFSET; |
| 21 | } | 22 | } |
| 22 | 23 | ||
| 24 | extern struct nft_af_info nft_af_ipv4; | ||
| 25 | |||
| 23 | #endif | 26 | #endif |
diff --git a/include/net/netfilter/nf_tables_ipv6.h b/include/net/netfilter/nf_tables_ipv6.h index 4a9b88a65963..74d976137658 100644 --- a/include/net/netfilter/nf_tables_ipv6.h +++ b/include/net/netfilter/nf_tables_ipv6.h | |||
| @@ -21,10 +21,13 @@ nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt, | |||
| 21 | if (protohdr < 0) | 21 | if (protohdr < 0) |
| 22 | return -1; | 22 | return -1; |
| 23 | 23 | ||
| 24 | pkt->tprot = protohdr; | ||
| 24 | pkt->xt.thoff = thoff; | 25 | pkt->xt.thoff = thoff; |
| 25 | pkt->xt.fragoff = frag_off; | 26 | pkt->xt.fragoff = frag_off; |
| 26 | 27 | ||
| 27 | return 0; | 28 | return 0; |
| 28 | } | 29 | } |
| 29 | 30 | ||
| 31 | extern struct nft_af_info nft_af_ipv6; | ||
| 32 | |||
| 30 | #endif | 33 | #endif |
diff --git a/include/net/netns/nftables.h b/include/net/netns/nftables.h index 15d056d534e3..26a394cb91a8 100644 --- a/include/net/netns/nftables.h +++ b/include/net/netns/nftables.h | |||
| @@ -10,6 +10,7 @@ struct netns_nftables { | |||
| 10 | struct list_head commit_list; | 10 | struct list_head commit_list; |
| 11 | struct nft_af_info *ipv4; | 11 | struct nft_af_info *ipv4; |
| 12 | struct nft_af_info *ipv6; | 12 | struct nft_af_info *ipv6; |
| 13 | struct nft_af_info *inet; | ||
| 13 | struct nft_af_info *arp; | 14 | struct nft_af_info *arp; |
| 14 | struct nft_af_info *bridge; | 15 | struct nft_af_info *bridge; |
| 15 | u8 gencursor; | 16 | u8 gencursor; |
diff --git a/include/uapi/linux/if_arp.h b/include/uapi/linux/if_arp.h index d7fea3496f32..4d024d75d64b 100644 --- a/include/uapi/linux/if_arp.h +++ b/include/uapi/linux/if_arp.h | |||
| @@ -94,6 +94,7 @@ | |||
| 94 | #define ARPHRD_CAIF 822 /* CAIF media type */ | 94 | #define ARPHRD_CAIF 822 /* CAIF media type */ |
| 95 | #define ARPHRD_IP6GRE 823 /* GRE over IPv6 */ | 95 | #define ARPHRD_IP6GRE 823 /* GRE over IPv6 */ |
| 96 | #define ARPHRD_NETLINK 824 /* Netlink header */ | 96 | #define ARPHRD_NETLINK 824 /* Netlink header */ |
| 97 | #define ARPHRD_6LOWPAN 825 /* IPv6 over LoWPAN */ | ||
| 97 | 98 | ||
| 98 | #define ARPHRD_VOID 0xFFFF /* Void type, nothing is known */ | 99 | #define ARPHRD_VOID 0xFFFF /* Void type, nothing is known */ |
| 99 | #define ARPHRD_NONE 0xFFFE /* zero header length */ | 100 | #define ARPHRD_NONE 0xFFFE /* zero header length */ |
diff --git a/include/uapi/linux/netfilter.h b/include/uapi/linux/netfilter.h index f7dc0ebeeba5..ef1b1f88ca18 100644 --- a/include/uapi/linux/netfilter.h +++ b/include/uapi/linux/netfilter.h | |||
| @@ -53,6 +53,7 @@ enum nf_inet_hooks { | |||
| 53 | 53 | ||
| 54 | enum { | 54 | enum { |
| 55 | NFPROTO_UNSPEC = 0, | 55 | NFPROTO_UNSPEC = 0, |
| 56 | NFPROTO_INET = 1, | ||
| 56 | NFPROTO_IPV4 = 2, | 57 | NFPROTO_IPV4 = 2, |
| 57 | NFPROTO_ARP = 3, | 58 | NFPROTO_ARP = 3, |
| 58 | NFPROTO_BRIDGE = 7, | 59 | NFPROTO_BRIDGE = 7, |
diff --git a/include/uapi/linux/netfilter/Kbuild b/include/uapi/linux/netfilter/Kbuild index 2344f5a319fc..1d973d2ba417 100644 --- a/include/uapi/linux/netfilter/Kbuild +++ b/include/uapi/linux/netfilter/Kbuild | |||
| @@ -58,6 +58,7 @@ header-y += xt_helper.h | |||
| 58 | header-y += xt_ipcomp.h | 58 | header-y += xt_ipcomp.h |
| 59 | header-y += xt_iprange.h | 59 | header-y += xt_iprange.h |
| 60 | header-y += xt_ipvs.h | 60 | header-y += xt_ipvs.h |
| 61 | header-y += xt_l2tp.h | ||
| 61 | header-y += xt_length.h | 62 | header-y += xt_length.h |
| 62 | header-y += xt_limit.h | 63 | header-y += xt_limit.h |
| 63 | header-y += xt_mac.h | 64 | header-y += xt_mac.h |
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index aa86a15293e1..83c985a6170b 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h | |||
| @@ -531,6 +531,8 @@ enum nft_exthdr_attributes { | |||
| 531 | * @NFT_META_NFTRACE: packet nftrace bit | 531 | * @NFT_META_NFTRACE: packet nftrace bit |
| 532 | * @NFT_META_RTCLASSID: realm value of packet's route (skb->dst->tclassid) | 532 | * @NFT_META_RTCLASSID: realm value of packet's route (skb->dst->tclassid) |
| 533 | * @NFT_META_SECMARK: packet secmark (skb->secmark) | 533 | * @NFT_META_SECMARK: packet secmark (skb->secmark) |
| 534 | * @NFT_META_NFPROTO: netfilter protocol | ||
| 535 | * @NFT_META_L4PROTO: layer 4 protocol number | ||
| 534 | */ | 536 | */ |
| 535 | enum nft_meta_keys { | 537 | enum nft_meta_keys { |
| 536 | NFT_META_LEN, | 538 | NFT_META_LEN, |
| @@ -548,6 +550,8 @@ enum nft_meta_keys { | |||
| 548 | NFT_META_NFTRACE, | 550 | NFT_META_NFTRACE, |
| 549 | NFT_META_RTCLASSID, | 551 | NFT_META_RTCLASSID, |
| 550 | NFT_META_SECMARK, | 552 | NFT_META_SECMARK, |
| 553 | NFT_META_NFPROTO, | ||
| 554 | NFT_META_L4PROTO, | ||
| 551 | }; | 555 | }; |
| 552 | 556 | ||
| 553 | /** | 557 | /** |
| @@ -605,12 +609,14 @@ enum nft_ct_keys { | |||
| 605 | * @NFTA_CT_DREG: destination register (NLA_U32) | 609 | * @NFTA_CT_DREG: destination register (NLA_U32) |
| 606 | * @NFTA_CT_KEY: conntrack data item to load (NLA_U32: nft_ct_keys) | 610 | * @NFTA_CT_KEY: conntrack data item to load (NLA_U32: nft_ct_keys) |
| 607 | * @NFTA_CT_DIRECTION: direction in case of directional keys (NLA_U8) | 611 | * @NFTA_CT_DIRECTION: direction in case of directional keys (NLA_U8) |
| 612 | * @NFTA_CT_SREG: source register (NLA_U32) | ||
| 608 | */ | 613 | */ |
| 609 | enum nft_ct_attributes { | 614 | enum nft_ct_attributes { |
| 610 | NFTA_CT_UNSPEC, | 615 | NFTA_CT_UNSPEC, |
| 611 | NFTA_CT_DREG, | 616 | NFTA_CT_DREG, |
| 612 | NFTA_CT_KEY, | 617 | NFTA_CT_KEY, |
| 613 | NFTA_CT_DIRECTION, | 618 | NFTA_CT_DIRECTION, |
| 619 | NFTA_CT_SREG, | ||
| 614 | __NFTA_CT_MAX | 620 | __NFTA_CT_MAX |
| 615 | }; | 621 | }; |
| 616 | #define NFTA_CT_MAX (__NFTA_CT_MAX - 1) | 622 | #define NFTA_CT_MAX (__NFTA_CT_MAX - 1) |
diff --git a/include/uapi/linux/netfilter/xt_l2tp.h b/include/uapi/linux/netfilter/xt_l2tp.h new file mode 100644 index 000000000000..7dccfa0acbfa --- /dev/null +++ b/include/uapi/linux/netfilter/xt_l2tp.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | #ifndef _LINUX_NETFILTER_XT_L2TP_H | ||
| 2 | #define _LINUX_NETFILTER_XT_L2TP_H | ||
| 3 | |||
| 4 | #include <linux/types.h> | ||
| 5 | |||
| 6 | enum xt_l2tp_type { | ||
| 7 | XT_L2TP_TYPE_CONTROL, | ||
| 8 | XT_L2TP_TYPE_DATA, | ||
| 9 | }; | ||
| 10 | |||
| 11 | /* L2TP matching stuff */ | ||
| 12 | struct xt_l2tp_info { | ||
| 13 | __u32 tid; /* tunnel id */ | ||
| 14 | __u32 sid; /* session id */ | ||
| 15 | __u8 version; /* L2TP protocol version */ | ||
| 16 | __u8 type; /* L2TP packet type */ | ||
| 17 | __u8 flags; /* which fields to match */ | ||
| 18 | }; | ||
| 19 | |||
| 20 | enum { | ||
| 21 | XT_L2TP_TID = (1 << 0), /* match L2TP tunnel id */ | ||
| 22 | XT_L2TP_SID = (1 << 1), /* match L2TP session id */ | ||
| 23 | XT_L2TP_VERSION = (1 << 2), /* match L2TP protocol version */ | ||
| 24 | XT_L2TP_TYPE = (1 << 3), /* match L2TP packet type */ | ||
| 25 | }; | ||
| 26 | |||
| 27 | #endif /* _LINUX_NETFILTER_XT_L2TP_H */ | ||
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index e1307909ecf1..91054fd660e0 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
| @@ -702,6 +702,12 @@ | |||
| 702 | * (&struct nl80211_vendor_cmd_info) of the supported vendor commands. | 702 | * (&struct nl80211_vendor_cmd_info) of the supported vendor commands. |
| 703 | * This may also be sent as an event with the same attributes. | 703 | * This may also be sent as an event with the same attributes. |
| 704 | * | 704 | * |
| 705 | * @NL80211_CMD_SET_QOS_MAP: Set Interworking QoS mapping for IP DSCP values. | ||
| 706 | * The QoS mapping information is included in %NL80211_ATTR_QOS_MAP. If | ||
| 707 | * that attribute is not included, QoS mapping is disabled. Since this | ||
| 708 | * QoS mapping is relevant for IP packets, it is only valid during an | ||
| 709 | * association. This is cleared on disassociation and AP restart. | ||
| 710 | * | ||
| 705 | * @NL80211_CMD_MAX: highest used command number | 711 | * @NL80211_CMD_MAX: highest used command number |
| 706 | * @__NL80211_CMD_AFTER_LAST: internal use | 712 | * @__NL80211_CMD_AFTER_LAST: internal use |
| 707 | */ | 713 | */ |
| @@ -871,6 +877,8 @@ enum nl80211_commands { | |||
| 871 | 877 | ||
| 872 | NL80211_CMD_VENDOR, | 878 | NL80211_CMD_VENDOR, |
| 873 | 879 | ||
| 880 | NL80211_CMD_SET_QOS_MAP, | ||
| 881 | |||
| 874 | /* add new commands above here */ | 882 | /* add new commands above here */ |
| 875 | 883 | ||
| 876 | /* used to define NL80211_CMD_MAX below */ | 884 | /* used to define NL80211_CMD_MAX below */ |
| @@ -1540,6 +1548,12 @@ enum nl80211_commands { | |||
| 1540 | * @NL80211_ATTR_VENDOR_SUBCMD: vendor sub-command | 1548 | * @NL80211_ATTR_VENDOR_SUBCMD: vendor sub-command |
| 1541 | * @NL80211_ATTR_VENDOR_DATA: data for the vendor command, if any; this | 1549 | * @NL80211_ATTR_VENDOR_DATA: data for the vendor command, if any; this |
| 1542 | * attribute is also used for vendor command feature advertisement | 1550 | * attribute is also used for vendor command feature advertisement |
| 1551 | * @NL80211_ATTR_VENDOR_EVENTS: used for event list advertising in the wiphy | ||
| 1552 | * info, containing a nested array of possible events | ||
| 1553 | * | ||
| 1554 | * @NL80211_ATTR_QOS_MAP: IP DSCP mapping for Interworking QoS mapping. This | ||
| 1555 | * data is in the format defined for the payload of the QoS Map Set element | ||
| 1556 | * in IEEE Std 802.11-2012, 8.4.2.97. | ||
| 1543 | * | 1557 | * |
| 1544 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 1558 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
| 1545 | * @__NL80211_ATTR_AFTER_LAST: internal use | 1559 | * @__NL80211_ATTR_AFTER_LAST: internal use |
| @@ -1865,6 +1879,9 @@ enum nl80211_attrs { | |||
| 1865 | NL80211_ATTR_VENDOR_ID, | 1879 | NL80211_ATTR_VENDOR_ID, |
| 1866 | NL80211_ATTR_VENDOR_SUBCMD, | 1880 | NL80211_ATTR_VENDOR_SUBCMD, |
| 1867 | NL80211_ATTR_VENDOR_DATA, | 1881 | NL80211_ATTR_VENDOR_DATA, |
| 1882 | NL80211_ATTR_VENDOR_EVENTS, | ||
| 1883 | |||
| 1884 | NL80211_ATTR_QOS_MAP, | ||
| 1868 | 1885 | ||
| 1869 | /* add attributes here, update the policy in nl80211.c */ | 1886 | /* add attributes here, update the policy in nl80211.c */ |
| 1870 | 1887 | ||
diff --git a/include/uapi/linux/tcp_metrics.h b/include/uapi/linux/tcp_metrics.h index cb5157b55f32..54a37b13f2c4 100644 --- a/include/uapi/linux/tcp_metrics.h +++ b/include/uapi/linux/tcp_metrics.h | |||
| @@ -35,6 +35,8 @@ enum { | |||
| 35 | TCP_METRICS_ATTR_FOPEN_SYN_DROPS, /* u16, count of drops */ | 35 | TCP_METRICS_ATTR_FOPEN_SYN_DROPS, /* u16, count of drops */ |
| 36 | TCP_METRICS_ATTR_FOPEN_SYN_DROP_TS, /* msecs age */ | 36 | TCP_METRICS_ATTR_FOPEN_SYN_DROP_TS, /* msecs age */ |
| 37 | TCP_METRICS_ATTR_FOPEN_COOKIE, /* binary */ | 37 | TCP_METRICS_ATTR_FOPEN_COOKIE, /* binary */ |
| 38 | TCP_METRICS_ATTR_SADDR_IPV4, /* u32 */ | ||
| 39 | TCP_METRICS_ATTR_SADDR_IPV6, /* binary */ | ||
| 38 | 40 | ||
| 39 | __TCP_METRICS_ATTR_MAX, | 41 | __TCP_METRICS_ATTR_MAX, |
| 40 | }; | 42 | }; |
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c new file mode 100644 index 000000000000..adb3ea04adaa --- /dev/null +++ b/net/bluetooth/6lowpan.c | |||
| @@ -0,0 +1,860 @@ | |||
| 1 | /* | ||
| 2 | Copyright (c) 2013 Intel Corp. | ||
| 3 | |||
| 4 | This program is free software; you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License version 2 and | ||
| 6 | only version 2 as published by the Free Software Foundation. | ||
| 7 | |||
| 8 | This program is distributed in the hope that it will be useful, | ||
| 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | GNU General Public License for more details. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/if_arp.h> | ||
| 15 | #include <linux/netdevice.h> | ||
| 16 | #include <linux/etherdevice.h> | ||
| 17 | |||
| 18 | #include <net/ipv6.h> | ||
| 19 | #include <net/ip6_route.h> | ||
| 20 | #include <net/addrconf.h> | ||
| 21 | |||
| 22 | #include <net/af_ieee802154.h> /* to get the address type */ | ||
| 23 | |||
| 24 | #include <net/bluetooth/bluetooth.h> | ||
| 25 | #include <net/bluetooth/hci_core.h> | ||
| 26 | #include <net/bluetooth/l2cap.h> | ||
| 27 | |||
| 28 | #include "6lowpan.h" | ||
| 29 | |||
| 30 | #include "../ieee802154/6lowpan.h" /* for the compression support */ | ||
| 31 | |||
| 32 | #define IFACE_NAME_TEMPLATE "bt%d" | ||
| 33 | #define EUI64_ADDR_LEN 8 | ||
| 34 | |||
| 35 | struct skb_cb { | ||
| 36 | struct in6_addr addr; | ||
| 37 | struct l2cap_conn *conn; | ||
| 38 | }; | ||
| 39 | #define lowpan_cb(skb) ((struct skb_cb *)((skb)->cb)) | ||
| 40 | |||
| 41 | /* The devices list contains those devices that we are acting | ||
| 42 | * as a proxy. The BT 6LoWPAN device is a virtual device that | ||
| 43 | * connects to the Bluetooth LE device. The real connection to | ||
| 44 | * BT device is done via l2cap layer. There exists one | ||
| 45 | * virtual device / one BT 6LoWPAN network (=hciX device). | ||
| 46 | * The list contains struct lowpan_dev elements. | ||
| 47 | */ | ||
| 48 | static LIST_HEAD(bt_6lowpan_devices); | ||
| 49 | static DEFINE_RWLOCK(devices_lock); | ||
| 50 | |||
| 51 | struct lowpan_peer { | ||
| 52 | struct list_head list; | ||
| 53 | struct l2cap_conn *conn; | ||
| 54 | |||
| 55 | /* peer addresses in various formats */ | ||
| 56 | unsigned char eui64_addr[EUI64_ADDR_LEN]; | ||
| 57 | struct in6_addr peer_addr; | ||
| 58 | }; | ||
| 59 | |||
| 60 | struct lowpan_dev { | ||
| 61 | struct list_head list; | ||
| 62 | |||
| 63 | struct hci_dev *hdev; | ||
| 64 | struct net_device *netdev; | ||
| 65 | struct list_head peers; | ||
| 66 | atomic_t peer_count; /* number of items in peers list */ | ||
| 67 | |||
| 68 | struct work_struct delete_netdev; | ||
| 69 | struct delayed_work notify_peers; | ||
| 70 | }; | ||
| 71 | |||
| 72 | static inline struct lowpan_dev *lowpan_dev(const struct net_device *netdev) | ||
| 73 | { | ||
| 74 | return netdev_priv(netdev); | ||
| 75 | } | ||
| 76 | |||
| 77 | static inline void peer_add(struct lowpan_dev *dev, struct lowpan_peer *peer) | ||
| 78 | { | ||
| 79 | list_add(&peer->list, &dev->peers); | ||
| 80 | atomic_inc(&dev->peer_count); | ||
| 81 | } | ||
| 82 | |||
| 83 | static inline bool peer_del(struct lowpan_dev *dev, struct lowpan_peer *peer) | ||
| 84 | { | ||
| 85 | list_del(&peer->list); | ||
| 86 | |||
| 87 | if (atomic_dec_and_test(&dev->peer_count)) { | ||
| 88 | BT_DBG("last peer"); | ||
| 89 | return true; | ||
| 90 | } | ||
| 91 | |||
| 92 | return false; | ||
| 93 | } | ||
| 94 | |||
| 95 | static inline struct lowpan_peer *peer_lookup_ba(struct lowpan_dev *dev, | ||
| 96 | bdaddr_t *ba, __u8 type) | ||
| 97 | { | ||
| 98 | struct lowpan_peer *peer, *tmp; | ||
| 99 | |||
| 100 | BT_DBG("peers %d addr %pMR type %d", atomic_read(&dev->peer_count), | ||
| 101 | ba, type); | ||
| 102 | |||
| 103 | list_for_each_entry_safe(peer, tmp, &dev->peers, list) { | ||
| 104 | BT_DBG("addr %pMR type %d", | ||
| 105 | &peer->conn->hcon->dst, peer->conn->hcon->dst_type); | ||
| 106 | |||
| 107 | if (bacmp(&peer->conn->hcon->dst, ba)) | ||
| 108 | continue; | ||
| 109 | |||
| 110 | if (type == peer->conn->hcon->dst_type) | ||
| 111 | return peer; | ||
| 112 | } | ||
| 113 | |||
| 114 | return NULL; | ||
| 115 | } | ||
| 116 | |||
| 117 | static inline struct lowpan_peer *peer_lookup_conn(struct lowpan_dev *dev, | ||
| 118 | struct l2cap_conn *conn) | ||
| 119 | { | ||
| 120 | struct lowpan_peer *peer, *tmp; | ||
| 121 | |||
| 122 | list_for_each_entry_safe(peer, tmp, &dev->peers, list) { | ||
| 123 | if (peer->conn == conn) | ||
| 124 | return peer; | ||
| 125 | } | ||
| 126 | |||
| 127 | return NULL; | ||
| 128 | } | ||
| 129 | |||
| 130 | static struct lowpan_peer *lookup_peer(struct l2cap_conn *conn) | ||
| 131 | { | ||
| 132 | struct lowpan_dev *entry, *tmp; | ||
| 133 | struct lowpan_peer *peer = NULL; | ||
| 134 | unsigned long flags; | ||
| 135 | |||
| 136 | read_lock_irqsave(&devices_lock, flags); | ||
| 137 | |||
| 138 | list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) { | ||
| 139 | peer = peer_lookup_conn(entry, conn); | ||
| 140 | if (peer) | ||
| 141 | break; | ||
| 142 | } | ||
| 143 | |||
| 144 | read_unlock_irqrestore(&devices_lock, flags); | ||
| 145 | |||
| 146 | return peer; | ||
| 147 | } | ||
| 148 | |||
| 149 | static struct lowpan_dev *lookup_dev(struct l2cap_conn *conn) | ||
| 150 | { | ||
| 151 | struct lowpan_dev *entry, *tmp; | ||
| 152 | struct lowpan_dev *dev = NULL; | ||
| 153 | unsigned long flags; | ||
| 154 | |||
| 155 | read_lock_irqsave(&devices_lock, flags); | ||
| 156 | |||
| 157 | list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) { | ||
| 158 | if (conn->hcon->hdev == entry->hdev) { | ||
| 159 | dev = entry; | ||
| 160 | break; | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | read_unlock_irqrestore(&devices_lock, flags); | ||
| 165 | |||
| 166 | return dev; | ||
| 167 | } | ||
| 168 | |||
| 169 | static int give_skb_to_upper(struct sk_buff *skb, struct net_device *dev) | ||
| 170 | { | ||
| 171 | struct sk_buff *skb_cp; | ||
| 172 | int ret; | ||
| 173 | |||
| 174 | skb_cp = skb_copy(skb, GFP_ATOMIC); | ||
| 175 | if (!skb_cp) | ||
| 176 | return -ENOMEM; | ||
| 177 | |||
| 178 | ret = netif_rx(skb_cp); | ||
| 179 | |||
| 180 | BT_DBG("receive skb %d", ret); | ||
| 181 | if (ret < 0) | ||
| 182 | return NET_RX_DROP; | ||
| 183 | |||
| 184 | return ret; | ||
| 185 | } | ||
| 186 | |||
| 187 | static int process_data(struct sk_buff *skb, struct net_device *netdev, | ||
| 188 | struct l2cap_conn *conn) | ||
| 189 | { | ||
| 190 | const u8 *saddr, *daddr; | ||
| 191 | u8 iphc0, iphc1; | ||
| 192 | struct lowpan_dev *dev; | ||
| 193 | struct lowpan_peer *peer; | ||
| 194 | unsigned long flags; | ||
| 195 | |||
| 196 | dev = lowpan_dev(netdev); | ||
| 197 | |||
| 198 | read_lock_irqsave(&devices_lock, flags); | ||
| 199 | peer = peer_lookup_conn(dev, conn); | ||
| 200 | read_unlock_irqrestore(&devices_lock, flags); | ||
| 201 | if (!peer) | ||
| 202 | goto drop; | ||
| 203 | |||
| 204 | saddr = peer->eui64_addr; | ||
| 205 | daddr = dev->netdev->dev_addr; | ||
| 206 | |||
| 207 | /* at least two bytes will be used for the encoding */ | ||
| 208 | if (skb->len < 2) | ||
| 209 | goto drop; | ||
| 210 | |||
| 211 | if (lowpan_fetch_skb_u8(skb, &iphc0)) | ||
| 212 | goto drop; | ||
| 213 | |||
| 214 | if (lowpan_fetch_skb_u8(skb, &iphc1)) | ||
| 215 | goto drop; | ||
| 216 | |||
| 217 | return lowpan_process_data(skb, netdev, | ||
| 218 | saddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN, | ||
| 219 | daddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN, | ||
| 220 | iphc0, iphc1, give_skb_to_upper); | ||
| 221 | |||
| 222 | drop: | ||
| 223 | kfree_skb(skb); | ||
| 224 | return -EINVAL; | ||
| 225 | } | ||
| 226 | |||
| 227 | static int recv_pkt(struct sk_buff *skb, struct net_device *dev, | ||
| 228 | struct l2cap_conn *conn) | ||
| 229 | { | ||
| 230 | struct sk_buff *local_skb; | ||
| 231 | int ret; | ||
| 232 | |||
| 233 | if (!netif_running(dev)) | ||
| 234 | goto drop; | ||
| 235 | |||
| 236 | if (dev->type != ARPHRD_6LOWPAN) | ||
| 237 | goto drop; | ||
| 238 | |||
| 239 | /* check that it's our buffer */ | ||
| 240 | if (skb->data[0] == LOWPAN_DISPATCH_IPV6) { | ||
| 241 | /* Copy the packet so that the IPv6 header is | ||
| 242 | * properly aligned. | ||
| 243 | */ | ||
| 244 | local_skb = skb_copy_expand(skb, NET_SKB_PAD - 1, | ||
| 245 | skb_tailroom(skb), GFP_ATOMIC); | ||
| 246 | if (!local_skb) | ||
| 247 | goto drop; | ||
| 248 | |||
| 249 | local_skb->protocol = htons(ETH_P_IPV6); | ||
| 250 | local_skb->pkt_type = PACKET_HOST; | ||
| 251 | |||
| 252 | skb_reset_network_header(local_skb); | ||
| 253 | skb_set_transport_header(local_skb, sizeof(struct ipv6hdr)); | ||
| 254 | |||
| 255 | if (give_skb_to_upper(local_skb, dev) != NET_RX_SUCCESS) { | ||
| 256 | kfree_skb(local_skb); | ||
| 257 | goto drop; | ||
| 258 | } | ||
| 259 | |||
| 260 | dev->stats.rx_bytes += skb->len; | ||
| 261 | dev->stats.rx_packets++; | ||
| 262 | |||
| 263 | kfree_skb(local_skb); | ||
| 264 | kfree_skb(skb); | ||
| 265 | } else { | ||
| 266 | switch (skb->data[0] & 0xe0) { | ||
| 267 | case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */ | ||
| 268 | local_skb = skb_clone(skb, GFP_ATOMIC); | ||
| 269 | if (!local_skb) | ||
| 270 | goto drop; | ||
| 271 | |||
| 272 | ret = process_data(local_skb, dev, conn); | ||
| 273 | if (ret != NET_RX_SUCCESS) | ||
| 274 | goto drop; | ||
| 275 | |||
| 276 | dev->stats.rx_bytes += skb->len; | ||
| 277 | dev->stats.rx_packets++; | ||
| 278 | |||
| 279 | kfree_skb(skb); | ||
| 280 | break; | ||
| 281 | default: | ||
| 282 | break; | ||
| 283 | } | ||
| 284 | } | ||
| 285 | |||
| 286 | return NET_RX_SUCCESS; | ||
| 287 | |||
| 288 | drop: | ||
| 289 | kfree_skb(skb); | ||
| 290 | return NET_RX_DROP; | ||
| 291 | } | ||
| 292 | |||
| 293 | /* Packet from BT LE device */ | ||
| 294 | int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb) | ||
| 295 | { | ||
| 296 | struct lowpan_dev *dev; | ||
| 297 | struct lowpan_peer *peer; | ||
| 298 | int err; | ||
| 299 | |||
| 300 | peer = lookup_peer(conn); | ||
| 301 | if (!peer) | ||
| 302 | return -ENOENT; | ||
| 303 | |||
| 304 | dev = lookup_dev(conn); | ||
| 305 | if (!dev || !dev->netdev) | ||
| 306 | return -ENOENT; | ||
| 307 | |||
| 308 | err = recv_pkt(skb, dev->netdev, conn); | ||
| 309 | BT_DBG("recv pkt %d", err); | ||
| 310 | |||
| 311 | return err; | ||
| 312 | } | ||
| 313 | |||
| 314 | static inline int skbuff_copy(void *msg, int len, int count, int mtu, | ||
| 315 | struct sk_buff *skb, struct net_device *dev) | ||
| 316 | { | ||
| 317 | struct sk_buff **frag; | ||
| 318 | int sent = 0; | ||
| 319 | |||
| 320 | memcpy(skb_put(skb, count), msg, count); | ||
| 321 | |||
| 322 | sent += count; | ||
| 323 | msg += count; | ||
| 324 | len -= count; | ||
| 325 | |||
| 326 | dev->stats.tx_bytes += count; | ||
| 327 | dev->stats.tx_packets++; | ||
| 328 | |||
| 329 | raw_dump_table(__func__, "Sending", skb->data, skb->len); | ||
| 330 | |||
| 331 | /* Continuation fragments (no L2CAP header) */ | ||
| 332 | frag = &skb_shinfo(skb)->frag_list; | ||
| 333 | while (len > 0) { | ||
| 334 | struct sk_buff *tmp; | ||
| 335 | |||
| 336 | count = min_t(unsigned int, mtu, len); | ||
| 337 | |||
| 338 | tmp = bt_skb_alloc(count, GFP_ATOMIC); | ||
| 339 | if (!tmp) | ||
| 340 | return -ENOMEM; | ||
| 341 | |||
| 342 | *frag = tmp; | ||
| 343 | |||
| 344 | memcpy(skb_put(*frag, count), msg, count); | ||
| 345 | |||
| 346 | raw_dump_table(__func__, "Sending fragment", | ||
| 347 | (*frag)->data, count); | ||
| 348 | |||
| 349 | (*frag)->priority = skb->priority; | ||
| 350 | |||
| 351 | sent += count; | ||
| 352 | msg += count; | ||
| 353 | len -= count; | ||
| 354 | |||
| 355 | skb->len += (*frag)->len; | ||
| 356 | skb->data_len += (*frag)->len; | ||
| 357 | |||
| 358 | frag = &(*frag)->next; | ||
| 359 | |||
| 360 | dev->stats.tx_bytes += count; | ||
| 361 | dev->stats.tx_packets++; | ||
| 362 | } | ||
| 363 | |||
| 364 | return sent; | ||
| 365 | } | ||
| 366 | |||
| 367 | static struct sk_buff *create_pdu(struct l2cap_conn *conn, void *msg, | ||
| 368 | size_t len, u32 priority, | ||
| 369 | struct net_device *dev) | ||
| 370 | { | ||
| 371 | struct sk_buff *skb; | ||
| 372 | int err, count; | ||
| 373 | struct l2cap_hdr *lh; | ||
| 374 | |||
| 375 | /* FIXME: This mtu check should be not needed and atm is only used for | ||
| 376 | * testing purposes | ||
| 377 | */ | ||
| 378 | if (conn->mtu > (L2CAP_LE_MIN_MTU + L2CAP_HDR_SIZE)) | ||
| 379 | conn->mtu = L2CAP_LE_MIN_MTU + L2CAP_HDR_SIZE; | ||
| 380 | |||
| 381 | count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); | ||
| 382 | |||
| 383 | BT_DBG("conn %p len %zu mtu %d count %d", conn, len, conn->mtu, count); | ||
| 384 | |||
| 385 | skb = bt_skb_alloc(count + L2CAP_HDR_SIZE, GFP_ATOMIC); | ||
| 386 | if (!skb) | ||
| 387 | return ERR_PTR(-ENOMEM); | ||
| 388 | |||
| 389 | skb->priority = priority; | ||
| 390 | |||
| 391 | lh = (struct l2cap_hdr *)skb_put(skb, L2CAP_HDR_SIZE); | ||
| 392 | lh->cid = cpu_to_le16(L2CAP_FC_6LOWPAN); | ||
| 393 | lh->len = cpu_to_le16(len); | ||
| 394 | |||
| 395 | err = skbuff_copy(msg, len, count, conn->mtu, skb, dev); | ||
| 396 | if (unlikely(err < 0)) { | ||
| 397 | kfree_skb(skb); | ||
| 398 | BT_DBG("skbuff copy %d failed", err); | ||
| 399 | return ERR_PTR(err); | ||
| 400 | } | ||
| 401 | |||
| 402 | return skb; | ||
| 403 | } | ||
| 404 | |||
| 405 | static int conn_send(struct l2cap_conn *conn, | ||
| 406 | void *msg, size_t len, u32 priority, | ||
| 407 | struct net_device *dev) | ||
| 408 | { | ||
| 409 | struct sk_buff *skb; | ||
| 410 | |||
| 411 | skb = create_pdu(conn, msg, len, priority, dev); | ||
| 412 | if (IS_ERR(skb)) | ||
| 413 | return -EINVAL; | ||
| 414 | |||
| 415 | BT_DBG("conn %p skb %p len %d priority %u", conn, skb, skb->len, | ||
| 416 | skb->priority); | ||
| 417 | |||
| 418 | hci_send_acl(conn->hchan, skb, ACL_START); | ||
| 419 | |||
| 420 | return 0; | ||
| 421 | } | ||
| 422 | |||
| 423 | static void get_dest_bdaddr(struct in6_addr *ip6_daddr, | ||
| 424 | bdaddr_t *addr, u8 *addr_type) | ||
| 425 | { | ||
| 426 | u8 *eui64; | ||
| 427 | |||
| 428 | eui64 = ip6_daddr->s6_addr + 8; | ||
| 429 | |||
| 430 | addr->b[0] = eui64[7]; | ||
| 431 | addr->b[1] = eui64[6]; | ||
| 432 | addr->b[2] = eui64[5]; | ||
| 433 | addr->b[3] = eui64[2]; | ||
| 434 | addr->b[4] = eui64[1]; | ||
| 435 | addr->b[5] = eui64[0]; | ||
| 436 | |||
| 437 | addr->b[5] ^= 2; | ||
| 438 | |||
| 439 | /* Set universal/local bit to 0 */ | ||
| 440 | if (addr->b[5] & 1) { | ||
| 441 | addr->b[5] &= ~1; | ||
| 442 | *addr_type = ADDR_LE_DEV_PUBLIC; | ||
| 443 | } else { | ||
| 444 | *addr_type = ADDR_LE_DEV_RANDOM; | ||
| 445 | } | ||
| 446 | } | ||
| 447 | |||
| 448 | static int header_create(struct sk_buff *skb, struct net_device *netdev, | ||
| 449 | unsigned short type, const void *_daddr, | ||
| 450 | const void *_saddr, unsigned int len) | ||
| 451 | { | ||
| 452 | struct ipv6hdr *hdr; | ||
| 453 | struct lowpan_dev *dev; | ||
| 454 | struct lowpan_peer *peer; | ||
| 455 | bdaddr_t addr, *any = BDADDR_ANY; | ||
| 456 | u8 *saddr, *daddr = any->b; | ||
| 457 | u8 addr_type; | ||
| 458 | |||
| 459 | if (type != ETH_P_IPV6) | ||
| 460 | return -EINVAL; | ||
| 461 | |||
| 462 | hdr = ipv6_hdr(skb); | ||
| 463 | |||
| 464 | dev = lowpan_dev(netdev); | ||
| 465 | |||
| 466 | if (ipv6_addr_is_multicast(&hdr->daddr)) { | ||
| 467 | memcpy(&lowpan_cb(skb)->addr, &hdr->daddr, | ||
| 468 | sizeof(struct in6_addr)); | ||
| 469 | lowpan_cb(skb)->conn = NULL; | ||
| 470 | } else { | ||
| 471 | unsigned long flags; | ||
| 472 | |||
| 473 | /* Get destination BT device from skb. | ||
| 474 | * If there is no such peer then discard the packet. | ||
| 475 | */ | ||
| 476 | get_dest_bdaddr(&hdr->daddr, &addr, &addr_type); | ||
| 477 | |||
| 478 | BT_DBG("dest addr %pMR type %d", &addr, addr_type); | ||
| 479 | |||
| 480 | read_lock_irqsave(&devices_lock, flags); | ||
| 481 | peer = peer_lookup_ba(dev, &addr, addr_type); | ||
| 482 | read_unlock_irqrestore(&devices_lock, flags); | ||
| 483 | |||
| 484 | if (!peer) { | ||
| 485 | BT_DBG("no such peer %pMR found", &addr); | ||
| 486 | return -ENOENT; | ||
| 487 | } | ||
| 488 | |||
| 489 | daddr = peer->eui64_addr; | ||
| 490 | |||
| 491 | memcpy(&lowpan_cb(skb)->addr, &hdr->daddr, | ||
| 492 | sizeof(struct in6_addr)); | ||
| 493 | lowpan_cb(skb)->conn = peer->conn; | ||
| 494 | } | ||
| 495 | |||
| 496 | saddr = dev->netdev->dev_addr; | ||
| 497 | |||
| 498 | return lowpan_header_compress(skb, netdev, type, daddr, saddr, len); | ||
| 499 | } | ||
| 500 | |||
| 501 | /* Packet to BT LE device */ | ||
| 502 | static int send_pkt(struct l2cap_conn *conn, const void *saddr, | ||
| 503 | const void *daddr, struct sk_buff *skb, | ||
| 504 | struct net_device *netdev) | ||
| 505 | { | ||
| 506 | raw_dump_table(__func__, "raw skb data dump before fragmentation", | ||
| 507 | skb->data, skb->len); | ||
| 508 | |||
| 509 | return conn_send(conn, skb->data, skb->len, 0, netdev); | ||
| 510 | } | ||
| 511 | |||
| 512 | static void send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev) | ||
| 513 | { | ||
| 514 | struct sk_buff *local_skb; | ||
| 515 | struct lowpan_dev *entry, *tmp; | ||
| 516 | unsigned long flags; | ||
| 517 | |||
| 518 | read_lock_irqsave(&devices_lock, flags); | ||
| 519 | |||
| 520 | list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) { | ||
| 521 | struct lowpan_peer *pentry, *ptmp; | ||
| 522 | struct lowpan_dev *dev; | ||
| 523 | |||
| 524 | if (entry->netdev != netdev) | ||
| 525 | continue; | ||
| 526 | |||
| 527 | dev = lowpan_dev(entry->netdev); | ||
| 528 | |||
| 529 | list_for_each_entry_safe(pentry, ptmp, &dev->peers, list) { | ||
| 530 | local_skb = skb_clone(skb, GFP_ATOMIC); | ||
| 531 | |||
| 532 | send_pkt(pentry->conn, netdev->dev_addr, | ||
| 533 | pentry->eui64_addr, local_skb, netdev); | ||
| 534 | |||
| 535 | kfree_skb(local_skb); | ||
| 536 | } | ||
| 537 | } | ||
| 538 | |||
| 539 | read_unlock_irqrestore(&devices_lock, flags); | ||
| 540 | } | ||
| 541 | |||
| 542 | static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev) | ||
| 543 | { | ||
| 544 | int err = 0; | ||
| 545 | unsigned char *eui64_addr; | ||
| 546 | struct lowpan_dev *dev; | ||
| 547 | struct lowpan_peer *peer; | ||
| 548 | bdaddr_t addr; | ||
| 549 | u8 addr_type; | ||
| 550 | |||
| 551 | if (ipv6_addr_is_multicast(&lowpan_cb(skb)->addr)) { | ||
| 552 | /* We need to send the packet to every device | ||
| 553 | * behind this interface. | ||
| 554 | */ | ||
| 555 | send_mcast_pkt(skb, netdev); | ||
| 556 | } else { | ||
| 557 | unsigned long flags; | ||
| 558 | |||
| 559 | get_dest_bdaddr(&lowpan_cb(skb)->addr, &addr, &addr_type); | ||
| 560 | eui64_addr = lowpan_cb(skb)->addr.s6_addr + 8; | ||
| 561 | dev = lowpan_dev(netdev); | ||
| 562 | |||
| 563 | read_lock_irqsave(&devices_lock, flags); | ||
| 564 | peer = peer_lookup_ba(dev, &addr, addr_type); | ||
| 565 | read_unlock_irqrestore(&devices_lock, flags); | ||
| 566 | |||
| 567 | BT_DBG("xmit from %s to %pMR (%pI6c) peer %p", netdev->name, | ||
| 568 | &addr, &lowpan_cb(skb)->addr, peer); | ||
| 569 | |||
| 570 | if (peer && peer->conn) | ||
| 571 | err = send_pkt(peer->conn, netdev->dev_addr, | ||
| 572 | eui64_addr, skb, netdev); | ||
| 573 | } | ||
| 574 | dev_kfree_skb(skb); | ||
| 575 | |||
| 576 | if (err) | ||
| 577 | BT_DBG("ERROR: xmit failed (%d)", err); | ||
| 578 | |||
| 579 | return (err < 0) ? NET_XMIT_DROP : err; | ||
| 580 | } | ||
| 581 | |||
| 582 | static const struct net_device_ops netdev_ops = { | ||
| 583 | .ndo_start_xmit = bt_xmit, | ||
| 584 | }; | ||
| 585 | |||
| 586 | static struct header_ops header_ops = { | ||
| 587 | .create = header_create, | ||
| 588 | }; | ||
| 589 | |||
| 590 | static void netdev_setup(struct net_device *dev) | ||
| 591 | { | ||
| 592 | dev->addr_len = EUI64_ADDR_LEN; | ||
| 593 | dev->type = ARPHRD_6LOWPAN; | ||
| 594 | |||
| 595 | dev->hard_header_len = 0; | ||
| 596 | dev->needed_tailroom = 0; | ||
| 597 | dev->mtu = IPV6_MIN_MTU; | ||
| 598 | dev->tx_queue_len = 0; | ||
| 599 | dev->flags = IFF_RUNNING | IFF_POINTOPOINT; | ||
| 600 | dev->watchdog_timeo = 0; | ||
| 601 | |||
| 602 | dev->netdev_ops = &netdev_ops; | ||
| 603 | dev->header_ops = &header_ops; | ||
| 604 | dev->destructor = free_netdev; | ||
| 605 | } | ||
| 606 | |||
| 607 | static struct device_type bt_type = { | ||
| 608 | .name = "bluetooth", | ||
| 609 | }; | ||
| 610 | |||
| 611 | static void set_addr(u8 *eui, u8 *addr, u8 addr_type) | ||
| 612 | { | ||
| 613 | /* addr is the BT address in little-endian format */ | ||
| 614 | eui[0] = addr[5]; | ||
| 615 | eui[1] = addr[4]; | ||
| 616 | eui[2] = addr[3]; | ||
| 617 | eui[3] = 0xFF; | ||
| 618 | eui[4] = 0xFE; | ||
| 619 | eui[5] = addr[2]; | ||
| 620 | eui[6] = addr[1]; | ||
| 621 | eui[7] = addr[0]; | ||
| 622 | |||
| 623 | eui[0] ^= 2; | ||
| 624 | |||
| 625 | /* Universal/local bit set, RFC 4291 */ | ||
| 626 | if (addr_type == ADDR_LE_DEV_PUBLIC) | ||
| 627 | eui[0] |= 1; | ||
| 628 | else | ||
| 629 | eui[0] &= ~1; | ||
| 630 | } | ||
| 631 | |||
| 632 | static void set_dev_addr(struct net_device *netdev, bdaddr_t *addr, | ||
| 633 | u8 addr_type) | ||
| 634 | { | ||
| 635 | netdev->addr_assign_type = NET_ADDR_PERM; | ||
| 636 | set_addr(netdev->dev_addr, addr->b, addr_type); | ||
| 637 | netdev->dev_addr[0] ^= 2; | ||
| 638 | } | ||
| 639 | |||
| 640 | static void ifup(struct net_device *netdev) | ||
| 641 | { | ||
| 642 | int err; | ||
| 643 | |||
| 644 | rtnl_lock(); | ||
| 645 | err = dev_open(netdev); | ||
| 646 | if (err < 0) | ||
| 647 | BT_INFO("iface %s cannot be opened (%d)", netdev->name, err); | ||
| 648 | rtnl_unlock(); | ||
| 649 | } | ||
| 650 | |||
| 651 | static void do_notify_peers(struct work_struct *work) | ||
| 652 | { | ||
| 653 | struct lowpan_dev *dev = container_of(work, struct lowpan_dev, | ||
| 654 | notify_peers.work); | ||
| 655 | |||
| 656 | netdev_notify_peers(dev->netdev); /* send neighbour adv at startup */ | ||
| 657 | } | ||
| 658 | |||
| 659 | static bool is_bt_6lowpan(struct hci_conn *hcon) | ||
| 660 | { | ||
| 661 | if (hcon->type != LE_LINK) | ||
| 662 | return false; | ||
| 663 | |||
| 664 | return test_bit(HCI_CONN_6LOWPAN, &hcon->flags); | ||
| 665 | } | ||
| 666 | |||
| 667 | static int add_peer_conn(struct l2cap_conn *conn, struct lowpan_dev *dev) | ||
| 668 | { | ||
| 669 | struct lowpan_peer *peer; | ||
| 670 | unsigned long flags; | ||
| 671 | |||
| 672 | peer = kzalloc(sizeof(*peer), GFP_ATOMIC); | ||
| 673 | if (!peer) | ||
| 674 | return -ENOMEM; | ||
| 675 | |||
| 676 | peer->conn = conn; | ||
| 677 | memset(&peer->peer_addr, 0, sizeof(struct in6_addr)); | ||
| 678 | |||
| 679 | /* RFC 2464 ch. 5 */ | ||
| 680 | peer->peer_addr.s6_addr[0] = 0xFE; | ||
| 681 | peer->peer_addr.s6_addr[1] = 0x80; | ||
| 682 | set_addr((u8 *)&peer->peer_addr.s6_addr + 8, conn->hcon->dst.b, | ||
| 683 | conn->hcon->dst_type); | ||
| 684 | |||
| 685 | memcpy(&peer->eui64_addr, (u8 *)&peer->peer_addr.s6_addr + 8, | ||
| 686 | EUI64_ADDR_LEN); | ||
| 687 | peer->eui64_addr[0] ^= 2; /* second bit-flip (Universe/Local) | ||
| 688 | * is done according RFC2464 | ||
| 689 | */ | ||
| 690 | |||
| 691 | raw_dump_inline(__func__, "peer IPv6 address", | ||
| 692 | (unsigned char *)&peer->peer_addr, 16); | ||
| 693 | raw_dump_inline(__func__, "peer EUI64 address", peer->eui64_addr, 8); | ||
| 694 | |||
| 695 | write_lock_irqsave(&devices_lock, flags); | ||
| 696 | INIT_LIST_HEAD(&peer->list); | ||
| 697 | peer_add(dev, peer); | ||
| 698 | write_unlock_irqrestore(&devices_lock, flags); | ||
| 699 | |||
| 700 | /* Notifying peers about us needs to be done without locks held */ | ||
| 701 | INIT_DELAYED_WORK(&dev->notify_peers, do_notify_peers); | ||
| 702 | schedule_delayed_work(&dev->notify_peers, msecs_to_jiffies(100)); | ||
| 703 | |||
| 704 | return 0; | ||
| 705 | } | ||
| 706 | |||
| 707 | /* This gets called when BT LE 6LoWPAN device is connected. We then | ||
| 708 | * create network device that acts as a proxy between BT LE device | ||
| 709 | * and kernel network stack. | ||
| 710 | */ | ||
| 711 | int bt_6lowpan_add_conn(struct l2cap_conn *conn) | ||
| 712 | { | ||
| 713 | struct lowpan_peer *peer = NULL; | ||
| 714 | struct lowpan_dev *dev; | ||
| 715 | struct net_device *netdev; | ||
| 716 | int err = 0; | ||
| 717 | unsigned long flags; | ||
| 718 | |||
| 719 | if (!is_bt_6lowpan(conn->hcon)) | ||
| 720 | return 0; | ||
| 721 | |||
| 722 | peer = lookup_peer(conn); | ||
| 723 | if (peer) | ||
| 724 | return -EEXIST; | ||
| 725 | |||
| 726 | dev = lookup_dev(conn); | ||
| 727 | if (dev) | ||
| 728 | return add_peer_conn(conn, dev); | ||
| 729 | |||
| 730 | netdev = alloc_netdev(sizeof(*dev), IFACE_NAME_TEMPLATE, netdev_setup); | ||
| 731 | if (!netdev) | ||
| 732 | return -ENOMEM; | ||
| 733 | |||
| 734 | set_dev_addr(netdev, &conn->hcon->src, conn->hcon->src_type); | ||
| 735 | |||
| 736 | netdev->netdev_ops = &netdev_ops; | ||
| 737 | SET_NETDEV_DEV(netdev, &conn->hcon->dev); | ||
| 738 | SET_NETDEV_DEVTYPE(netdev, &bt_type); | ||
| 739 | |||
| 740 | err = register_netdev(netdev); | ||
| 741 | if (err < 0) { | ||
| 742 | BT_INFO("register_netdev failed %d", err); | ||
| 743 | free_netdev(netdev); | ||
| 744 | goto out; | ||
| 745 | } | ||
| 746 | |||
| 747 | BT_DBG("ifindex %d peer bdaddr %pMR my addr %pMR", | ||
| 748 | netdev->ifindex, &conn->hcon->dst, &conn->hcon->src); | ||
| 749 | set_bit(__LINK_STATE_PRESENT, &netdev->state); | ||
| 750 | |||
| 751 | dev = netdev_priv(netdev); | ||
| 752 | dev->netdev = netdev; | ||
| 753 | dev->hdev = conn->hcon->hdev; | ||
| 754 | INIT_LIST_HEAD(&dev->peers); | ||
| 755 | |||
| 756 | write_lock_irqsave(&devices_lock, flags); | ||
| 757 | INIT_LIST_HEAD(&dev->list); | ||
| 758 | list_add(&dev->list, &bt_6lowpan_devices); | ||
| 759 | write_unlock_irqrestore(&devices_lock, flags); | ||
| 760 | |||
| 761 | ifup(netdev); | ||
| 762 | |||
| 763 | return add_peer_conn(conn, dev); | ||
| 764 | |||
| 765 | out: | ||
| 766 | return err; | ||
| 767 | } | ||
| 768 | |||
| 769 | static void delete_netdev(struct work_struct *work) | ||
| 770 | { | ||
| 771 | struct lowpan_dev *entry = container_of(work, struct lowpan_dev, | ||
| 772 | delete_netdev); | ||
| 773 | |||
| 774 | unregister_netdev(entry->netdev); | ||
| 775 | |||
| 776 | /* The entry pointer is deleted in device_event() */ | ||
| 777 | } | ||
| 778 | |||
| 779 | int bt_6lowpan_del_conn(struct l2cap_conn *conn) | ||
| 780 | { | ||
| 781 | struct lowpan_dev *entry, *tmp; | ||
| 782 | struct lowpan_dev *dev = NULL; | ||
| 783 | struct lowpan_peer *peer; | ||
| 784 | int err = -ENOENT; | ||
| 785 | unsigned long flags; | ||
| 786 | bool last = false; | ||
| 787 | |||
| 788 | if (!conn || !is_bt_6lowpan(conn->hcon)) | ||
| 789 | return 0; | ||
| 790 | |||
| 791 | write_lock_irqsave(&devices_lock, flags); | ||
| 792 | |||
| 793 | list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) { | ||
| 794 | dev = lowpan_dev(entry->netdev); | ||
| 795 | peer = peer_lookup_conn(dev, conn); | ||
| 796 | if (peer) { | ||
| 797 | last = peer_del(dev, peer); | ||
| 798 | err = 0; | ||
| 799 | break; | ||
| 800 | } | ||
| 801 | } | ||
| 802 | |||
| 803 | if (!err && last && dev && !atomic_read(&dev->peer_count)) { | ||
| 804 | write_unlock_irqrestore(&devices_lock, flags); | ||
| 805 | |||
| 806 | cancel_delayed_work_sync(&dev->notify_peers); | ||
| 807 | |||
| 808 | /* bt_6lowpan_del_conn() is called with hci dev lock held which | ||
| 809 | * means that we must delete the netdevice in worker thread. | ||
| 810 | */ | ||
| 811 | INIT_WORK(&entry->delete_netdev, delete_netdev); | ||
| 812 | schedule_work(&entry->delete_netdev); | ||
| 813 | } else { | ||
| 814 | write_unlock_irqrestore(&devices_lock, flags); | ||
| 815 | } | ||
| 816 | |||
| 817 | return err; | ||
| 818 | } | ||
| 819 | |||
| 820 | static int device_event(struct notifier_block *unused, | ||
| 821 | unsigned long event, void *ptr) | ||
| 822 | { | ||
| 823 | struct net_device *netdev = netdev_notifier_info_to_dev(ptr); | ||
| 824 | struct lowpan_dev *entry, *tmp; | ||
| 825 | unsigned long flags; | ||
| 826 | |||
| 827 | if (netdev->type != ARPHRD_6LOWPAN) | ||
| 828 | return NOTIFY_DONE; | ||
| 829 | |||
| 830 | switch (event) { | ||
| 831 | case NETDEV_UNREGISTER: | ||
| 832 | write_lock_irqsave(&devices_lock, flags); | ||
| 833 | list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, | ||
| 834 | list) { | ||
| 835 | if (entry->netdev == netdev) { | ||
| 836 | list_del(&entry->list); | ||
| 837 | kfree(entry); | ||
| 838 | break; | ||
| 839 | } | ||
| 840 | } | ||
| 841 | write_unlock_irqrestore(&devices_lock, flags); | ||
| 842 | break; | ||
| 843 | } | ||
| 844 | |||
| 845 | return NOTIFY_DONE; | ||
| 846 | } | ||
| 847 | |||
| 848 | static struct notifier_block bt_6lowpan_dev_notifier = { | ||
| 849 | .notifier_call = device_event, | ||
| 850 | }; | ||
| 851 | |||
| 852 | int bt_6lowpan_init(void) | ||
| 853 | { | ||
| 854 | return register_netdevice_notifier(&bt_6lowpan_dev_notifier); | ||
| 855 | } | ||
| 856 | |||
| 857 | void bt_6lowpan_cleanup(void) | ||
| 858 | { | ||
| 859 | unregister_netdevice_notifier(&bt_6lowpan_dev_notifier); | ||
| 860 | } | ||
diff --git a/net/bluetooth/6lowpan.h b/net/bluetooth/6lowpan.h new file mode 100644 index 000000000000..680eac808d74 --- /dev/null +++ b/net/bluetooth/6lowpan.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | /* | ||
| 2 | Copyright (c) 2013 Intel Corp. | ||
| 3 | |||
| 4 | This program is free software; you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License version 2 and | ||
| 6 | only version 2 as published by the Free Software Foundation. | ||
| 7 | |||
| 8 | This program is distributed in the hope that it will be useful, | ||
| 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | GNU General Public License for more details. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #ifndef __6LOWPAN_H | ||
| 15 | #define __6LOWPAN_H | ||
| 16 | |||
| 17 | #include <linux/skbuff.h> | ||
| 18 | #include <net/bluetooth/l2cap.h> | ||
| 19 | |||
| 20 | int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb); | ||
| 21 | int bt_6lowpan_add_conn(struct l2cap_conn *conn); | ||
| 22 | int bt_6lowpan_del_conn(struct l2cap_conn *conn); | ||
| 23 | int bt_6lowpan_init(void); | ||
| 24 | void bt_6lowpan_cleanup(void); | ||
| 25 | |||
| 26 | #endif /* __6LOWPAN_H */ | ||
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile index 6a791e73e39d..cc6827e2ce68 100644 --- a/net/bluetooth/Makefile +++ b/net/bluetooth/Makefile | |||
| @@ -10,6 +10,10 @@ obj-$(CONFIG_BT_HIDP) += hidp/ | |||
| 10 | 10 | ||
| 11 | bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \ | 11 | bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \ |
| 12 | hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \ | 12 | hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \ |
| 13 | a2mp.o amp.o | 13 | a2mp.o amp.o 6lowpan.o |
| 14 | |||
| 15 | ifeq ($(CONFIG_IEEE802154_6LOWPAN),) | ||
| 16 | bluetooth-y += ../ieee802154/6lowpan_iphc.o | ||
| 17 | endif | ||
| 14 | 18 | ||
| 15 | subdir-ccflags-y += -D__CHECK_ENDIAN__ | 19 | subdir-ccflags-y += -D__CHECK_ENDIAN__ |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 8b8b5f80dd89..5e8663c194c1 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
| @@ -636,6 +636,49 @@ static int conn_max_interval_get(void *data, u64 *val) | |||
| 636 | DEFINE_SIMPLE_ATTRIBUTE(conn_max_interval_fops, conn_max_interval_get, | 636 | DEFINE_SIMPLE_ATTRIBUTE(conn_max_interval_fops, conn_max_interval_get, |
| 637 | conn_max_interval_set, "%llu\n"); | 637 | conn_max_interval_set, "%llu\n"); |
| 638 | 638 | ||
| 639 | static ssize_t lowpan_read(struct file *file, char __user *user_buf, | ||
| 640 | size_t count, loff_t *ppos) | ||
| 641 | { | ||
| 642 | struct hci_dev *hdev = file->private_data; | ||
| 643 | char buf[3]; | ||
| 644 | |||
| 645 | buf[0] = test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags) ? 'Y' : 'N'; | ||
| 646 | buf[1] = '\n'; | ||
| 647 | buf[2] = '\0'; | ||
| 648 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | ||
| 649 | } | ||
| 650 | |||
| 651 | static ssize_t lowpan_write(struct file *fp, const char __user *user_buffer, | ||
| 652 | size_t count, loff_t *position) | ||
| 653 | { | ||
| 654 | struct hci_dev *hdev = fp->private_data; | ||
| 655 | bool enable; | ||
| 656 | char buf[32]; | ||
| 657 | size_t buf_size = min(count, (sizeof(buf)-1)); | ||
| 658 | |||
| 659 | if (copy_from_user(buf, user_buffer, buf_size)) | ||
| 660 | return -EFAULT; | ||
| 661 | |||
| 662 | buf[buf_size] = '\0'; | ||
| 663 | |||
| 664 | if (strtobool(buf, &enable) < 0) | ||
| 665 | return -EINVAL; | ||
| 666 | |||
| 667 | if (enable == test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags)) | ||
| 668 | return -EALREADY; | ||
| 669 | |||
| 670 | change_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags); | ||
| 671 | |||
| 672 | return count; | ||
| 673 | } | ||
| 674 | |||
| 675 | static const struct file_operations lowpan_debugfs_fops = { | ||
| 676 | .open = simple_open, | ||
| 677 | .read = lowpan_read, | ||
| 678 | .write = lowpan_write, | ||
| 679 | .llseek = default_llseek, | ||
| 680 | }; | ||
| 681 | |||
| 639 | /* ---- HCI requests ---- */ | 682 | /* ---- HCI requests ---- */ |
| 640 | 683 | ||
| 641 | static void hci_req_sync_complete(struct hci_dev *hdev, u8 result) | 684 | static void hci_req_sync_complete(struct hci_dev *hdev, u8 result) |
| @@ -1261,8 +1304,13 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt) | |||
| 1261 | * as supported send it. If not supported assume that the controller | 1304 | * as supported send it. If not supported assume that the controller |
| 1262 | * does not have actual support for stored link keys which makes this | 1305 | * does not have actual support for stored link keys which makes this |
| 1263 | * command redundant anyway. | 1306 | * command redundant anyway. |
| 1307 | * | ||
| 1308 | * Some controllers indicate that they support handling deleting | ||
| 1309 | * stored link keys, but they don't. The quirk lets a driver | ||
| 1310 | * just disable this command. | ||
| 1264 | */ | 1311 | */ |
| 1265 | if (hdev->commands[6] & 0x80) { | 1312 | if (hdev->commands[6] & 0x80 && |
| 1313 | !test_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks)) { | ||
| 1266 | struct hci_cp_delete_stored_link_key cp; | 1314 | struct hci_cp_delete_stored_link_key cp; |
| 1267 | 1315 | ||
| 1268 | bacpy(&cp.bdaddr, BDADDR_ANY); | 1316 | bacpy(&cp.bdaddr, BDADDR_ANY); |
| @@ -1406,6 +1454,8 @@ static int __hci_init(struct hci_dev *hdev) | |||
| 1406 | hdev, &conn_min_interval_fops); | 1454 | hdev, &conn_min_interval_fops); |
| 1407 | debugfs_create_file("conn_max_interval", 0644, hdev->debugfs, | 1455 | debugfs_create_file("conn_max_interval", 0644, hdev->debugfs, |
| 1408 | hdev, &conn_max_interval_fops); | 1456 | hdev, &conn_max_interval_fops); |
| 1457 | debugfs_create_file("6lowpan", 0644, hdev->debugfs, hdev, | ||
| 1458 | &lowpan_debugfs_fops); | ||
| 1409 | } | 1459 | } |
| 1410 | 1460 | ||
| 1411 | return 0; | 1461 | return 0; |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 5fb3df66c2cd..5f812455a450 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
| @@ -3533,6 +3533,9 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 3533 | conn->handle = __le16_to_cpu(ev->handle); | 3533 | conn->handle = __le16_to_cpu(ev->handle); |
| 3534 | conn->state = BT_CONNECTED; | 3534 | conn->state = BT_CONNECTED; |
| 3535 | 3535 | ||
| 3536 | if (test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags)) | ||
| 3537 | set_bit(HCI_CONN_6LOWPAN, &conn->flags); | ||
| 3538 | |||
| 3536 | hci_conn_add_sysfs(conn); | 3539 | hci_conn_add_sysfs(conn); |
| 3537 | 3540 | ||
| 3538 | hci_proto_connect_cfm(conn, ev->status); | 3541 | hci_proto_connect_cfm(conn, ev->status); |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index b6bca64b320d..b0ad2c752d73 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #include "smp.h" | 40 | #include "smp.h" |
| 41 | #include "a2mp.h" | 41 | #include "a2mp.h" |
| 42 | #include "amp.h" | 42 | #include "amp.h" |
| 43 | #include "6lowpan.h" | ||
| 43 | 44 | ||
| 44 | bool disable_ertm; | 45 | bool disable_ertm; |
| 45 | 46 | ||
| @@ -1468,6 +1469,8 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
| 1468 | 1469 | ||
| 1469 | BT_DBG(""); | 1470 | BT_DBG(""); |
| 1470 | 1471 | ||
| 1472 | bt_6lowpan_add_conn(conn); | ||
| 1473 | |||
| 1471 | /* Check if we have socket listening on cid */ | 1474 | /* Check if we have socket listening on cid */ |
| 1472 | pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT, | 1475 | pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT, |
| 1473 | &hcon->src, &hcon->dst); | 1476 | &hcon->src, &hcon->dst); |
| @@ -7119,6 +7122,10 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) | |||
| 7119 | l2cap_conn_del(conn->hcon, EACCES); | 7122 | l2cap_conn_del(conn->hcon, EACCES); |
| 7120 | break; | 7123 | break; |
| 7121 | 7124 | ||
| 7125 | case L2CAP_FC_6LOWPAN: | ||
| 7126 | bt_6lowpan_recv(conn, skb); | ||
| 7127 | break; | ||
| 7128 | |||
| 7122 | default: | 7129 | default: |
| 7123 | l2cap_data_channel(conn, cid, skb); | 7130 | l2cap_data_channel(conn, cid, skb); |
| 7124 | break; | 7131 | break; |
| @@ -7186,6 +7193,8 @@ void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) | |||
| 7186 | { | 7193 | { |
| 7187 | BT_DBG("hcon %p reason %d", hcon, reason); | 7194 | BT_DBG("hcon %p reason %d", hcon, reason); |
| 7188 | 7195 | ||
| 7196 | bt_6lowpan_del_conn(hcon->l2cap_data); | ||
| 7197 | |||
| 7189 | l2cap_conn_del(hcon, bt_to_errno(reason)); | 7198 | l2cap_conn_del(hcon, bt_to_errno(reason)); |
| 7190 | } | 7199 | } |
| 7191 | 7200 | ||
| @@ -7467,11 +7476,14 @@ int __init l2cap_init(void) | |||
| 7467 | debugfs_create_u16("l2cap_le_default_mps", 0466, bt_debugfs, | 7476 | debugfs_create_u16("l2cap_le_default_mps", 0466, bt_debugfs, |
| 7468 | &le_default_mps); | 7477 | &le_default_mps); |
| 7469 | 7478 | ||
| 7479 | bt_6lowpan_init(); | ||
| 7480 | |||
| 7470 | return 0; | 7481 | return 0; |
| 7471 | } | 7482 | } |
| 7472 | 7483 | ||
| 7473 | void l2cap_exit(void) | 7484 | void l2cap_exit(void) |
| 7474 | { | 7485 | { |
| 7486 | bt_6lowpan_cleanup(); | ||
| 7475 | debugfs_remove(l2cap_debugfs); | 7487 | debugfs_remove(l2cap_debugfs); |
| 7476 | l2cap_cleanup_sockets(); | 7488 | l2cap_cleanup_sockets(); |
| 7477 | } | 7489 | } |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index e7806e6d282c..20ef748b2906 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
| @@ -147,6 +147,9 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
| 147 | __le16_to_cpu(la.l2_psm) == L2CAP_PSM_RFCOMM) | 147 | __le16_to_cpu(la.l2_psm) == L2CAP_PSM_RFCOMM) |
| 148 | chan->sec_level = BT_SECURITY_SDP; | 148 | chan->sec_level = BT_SECURITY_SDP; |
| 149 | break; | 149 | break; |
| 150 | case L2CAP_CHAN_RAW: | ||
| 151 | chan->sec_level = BT_SECURITY_SDP; | ||
| 152 | break; | ||
| 150 | } | 153 | } |
| 151 | 154 | ||
| 152 | bacpy(&chan->src, &la.l2_bdaddr); | 155 | bacpy(&chan->src, &la.l2_bdaddr); |
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 84fcf9fff3ea..f9c0980abeea 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
| @@ -58,6 +58,7 @@ struct rfcomm_dev { | |||
| 58 | uint modem_status; | 58 | uint modem_status; |
| 59 | 59 | ||
| 60 | struct rfcomm_dlc *dlc; | 60 | struct rfcomm_dlc *dlc; |
| 61 | wait_queue_head_t conn_wait; | ||
| 61 | 62 | ||
| 62 | struct device *tty_dev; | 63 | struct device *tty_dev; |
| 63 | 64 | ||
| @@ -103,20 +104,60 @@ static void rfcomm_dev_destruct(struct tty_port *port) | |||
| 103 | module_put(THIS_MODULE); | 104 | module_put(THIS_MODULE); |
| 104 | } | 105 | } |
| 105 | 106 | ||
| 106 | /* device-specific initialization: open the dlc */ | 107 | static struct device *rfcomm_get_device(struct rfcomm_dev *dev) |
| 107 | static int rfcomm_dev_activate(struct tty_port *port, struct tty_struct *tty) | ||
| 108 | { | 108 | { |
| 109 | struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port); | 109 | struct hci_dev *hdev; |
| 110 | struct hci_conn *conn; | ||
| 110 | 111 | ||
| 111 | return rfcomm_dlc_open(dev->dlc, &dev->src, &dev->dst, dev->channel); | 112 | hdev = hci_get_route(&dev->dst, &dev->src); |
| 113 | if (!hdev) | ||
| 114 | return NULL; | ||
| 115 | |||
| 116 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst); | ||
| 117 | |||
| 118 | hci_dev_put(hdev); | ||
| 119 | |||
| 120 | return conn ? &conn->dev : NULL; | ||
| 112 | } | 121 | } |
| 113 | 122 | ||
| 114 | /* we block the open until the dlc->state becomes BT_CONNECTED */ | 123 | /* device-specific initialization: open the dlc */ |
| 115 | static int rfcomm_dev_carrier_raised(struct tty_port *port) | 124 | static int rfcomm_dev_activate(struct tty_port *port, struct tty_struct *tty) |
| 116 | { | 125 | { |
| 117 | struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port); | 126 | struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port); |
| 127 | DEFINE_WAIT(wait); | ||
| 128 | int err; | ||
| 129 | |||
| 130 | err = rfcomm_dlc_open(dev->dlc, &dev->src, &dev->dst, dev->channel); | ||
| 131 | if (err) | ||
| 132 | return err; | ||
| 133 | |||
| 134 | while (1) { | ||
| 135 | prepare_to_wait(&dev->conn_wait, &wait, TASK_INTERRUPTIBLE); | ||
| 136 | |||
| 137 | if (dev->dlc->state == BT_CLOSED) { | ||
| 138 | err = -dev->err; | ||
| 139 | break; | ||
| 140 | } | ||
| 141 | |||
| 142 | if (dev->dlc->state == BT_CONNECTED) | ||
| 143 | break; | ||
| 144 | |||
| 145 | if (signal_pending(current)) { | ||
| 146 | err = -ERESTARTSYS; | ||
| 147 | break; | ||
| 148 | } | ||
| 149 | |||
| 150 | tty_unlock(tty); | ||
| 151 | schedule(); | ||
| 152 | tty_lock(tty); | ||
| 153 | } | ||
| 154 | finish_wait(&dev->conn_wait, &wait); | ||
| 155 | |||
| 156 | if (!err) | ||
| 157 | device_move(dev->tty_dev, rfcomm_get_device(dev), | ||
| 158 | DPM_ORDER_DEV_AFTER_PARENT); | ||
| 118 | 159 | ||
| 119 | return (dev->dlc->state == BT_CONNECTED); | 160 | return err; |
| 120 | } | 161 | } |
| 121 | 162 | ||
| 122 | /* device-specific cleanup: close the dlc */ | 163 | /* device-specific cleanup: close the dlc */ |
| @@ -135,7 +176,6 @@ static const struct tty_port_operations rfcomm_port_ops = { | |||
| 135 | .destruct = rfcomm_dev_destruct, | 176 | .destruct = rfcomm_dev_destruct, |
| 136 | .activate = rfcomm_dev_activate, | 177 | .activate = rfcomm_dev_activate, |
| 137 | .shutdown = rfcomm_dev_shutdown, | 178 | .shutdown = rfcomm_dev_shutdown, |
| 138 | .carrier_raised = rfcomm_dev_carrier_raised, | ||
| 139 | }; | 179 | }; |
| 140 | 180 | ||
| 141 | static struct rfcomm_dev *__rfcomm_dev_get(int id) | 181 | static struct rfcomm_dev *__rfcomm_dev_get(int id) |
| @@ -169,22 +209,6 @@ static struct rfcomm_dev *rfcomm_dev_get(int id) | |||
| 169 | return dev; | 209 | return dev; |
| 170 | } | 210 | } |
| 171 | 211 | ||
| 172 | static struct device *rfcomm_get_device(struct rfcomm_dev *dev) | ||
| 173 | { | ||
| 174 | struct hci_dev *hdev; | ||
| 175 | struct hci_conn *conn; | ||
| 176 | |||
| 177 | hdev = hci_get_route(&dev->dst, &dev->src); | ||
| 178 | if (!hdev) | ||
| 179 | return NULL; | ||
| 180 | |||
| 181 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst); | ||
| 182 | |||
| 183 | hci_dev_put(hdev); | ||
| 184 | |||
| 185 | return conn ? &conn->dev : NULL; | ||
| 186 | } | ||
| 187 | |||
| 188 | static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf) | 212 | static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf) |
| 189 | { | 213 | { |
| 190 | struct rfcomm_dev *dev = dev_get_drvdata(tty_dev); | 214 | struct rfcomm_dev *dev = dev_get_drvdata(tty_dev); |
| @@ -258,6 +282,7 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) | |||
| 258 | 282 | ||
| 259 | tty_port_init(&dev->port); | 283 | tty_port_init(&dev->port); |
| 260 | dev->port.ops = &rfcomm_port_ops; | 284 | dev->port.ops = &rfcomm_port_ops; |
| 285 | init_waitqueue_head(&dev->conn_wait); | ||
| 261 | 286 | ||
| 262 | skb_queue_head_init(&dev->pending); | 287 | skb_queue_head_init(&dev->pending); |
| 263 | 288 | ||
| @@ -437,7 +462,8 @@ static int rfcomm_release_dev(void __user *arg) | |||
| 437 | tty_kref_put(tty); | 462 | tty_kref_put(tty); |
| 438 | } | 463 | } |
| 439 | 464 | ||
| 440 | if (!test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags)) | 465 | if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags) && |
| 466 | !test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags)) | ||
| 441 | tty_port_put(&dev->port); | 467 | tty_port_put(&dev->port); |
| 442 | 468 | ||
| 443 | tty_port_put(&dev->port); | 469 | tty_port_put(&dev->port); |
| @@ -575,12 +601,9 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err) | |||
| 575 | BT_DBG("dlc %p dev %p err %d", dlc, dev, err); | 601 | BT_DBG("dlc %p dev %p err %d", dlc, dev, err); |
| 576 | 602 | ||
| 577 | dev->err = err; | 603 | dev->err = err; |
| 578 | if (dlc->state == BT_CONNECTED) { | 604 | wake_up_interruptible(&dev->conn_wait); |
| 579 | device_move(dev->tty_dev, rfcomm_get_device(dev), | ||
| 580 | DPM_ORDER_DEV_AFTER_PARENT); | ||
| 581 | 605 | ||
| 582 | wake_up_interruptible(&dev->port.open_wait); | 606 | if (dlc->state == BT_CLOSED) |
| 583 | } else if (dlc->state == BT_CLOSED) | ||
| 584 | tty_port_tty_hangup(&dev->port, false); | 607 | tty_port_tty_hangup(&dev->port, false); |
| 585 | } | 608 | } |
| 586 | 609 | ||
| @@ -670,10 +693,20 @@ static int rfcomm_tty_install(struct tty_driver *driver, struct tty_struct *tty) | |||
| 670 | 693 | ||
| 671 | /* install the tty_port */ | 694 | /* install the tty_port */ |
| 672 | err = tty_port_install(&dev->port, driver, tty); | 695 | err = tty_port_install(&dev->port, driver, tty); |
| 673 | if (err) | 696 | if (err) { |
| 674 | rfcomm_tty_cleanup(tty); | 697 | rfcomm_tty_cleanup(tty); |
| 698 | return err; | ||
| 699 | } | ||
| 675 | 700 | ||
| 676 | return err; | 701 | /* take over the tty_port reference if the port was created with the |
| 702 | * flag RFCOMM_RELEASE_ONHUP. This will force the release of the port | ||
| 703 | * when the last process closes the tty. The behaviour is expected by | ||
| 704 | * userspace. | ||
| 705 | */ | ||
| 706 | if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) | ||
| 707 | tty_port_put(&dev->port); | ||
| 708 | |||
| 709 | return 0; | ||
| 677 | } | 710 | } |
| 678 | 711 | ||
| 679 | static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) | 712 | static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) |
| @@ -1010,10 +1043,6 @@ static void rfcomm_tty_hangup(struct tty_struct *tty) | |||
| 1010 | BT_DBG("tty %p dev %p", tty, dev); | 1043 | BT_DBG("tty %p dev %p", tty, dev); |
| 1011 | 1044 | ||
| 1012 | tty_port_hangup(&dev->port); | 1045 | tty_port_hangup(&dev->port); |
| 1013 | |||
| 1014 | if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags) && | ||
| 1015 | !test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags)) | ||
| 1016 | tty_port_put(&dev->port); | ||
| 1017 | } | 1046 | } |
| 1018 | 1047 | ||
| 1019 | static int rfcomm_tty_tiocmget(struct tty_struct *tty) | 1048 | static int rfcomm_tty_tiocmget(struct tty_struct *tty) |
| @@ -1096,7 +1125,7 @@ int __init rfcomm_init_ttys(void) | |||
| 1096 | rfcomm_tty_driver->subtype = SERIAL_TYPE_NORMAL; | 1125 | rfcomm_tty_driver->subtype = SERIAL_TYPE_NORMAL; |
| 1097 | rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; | 1126 | rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; |
| 1098 | rfcomm_tty_driver->init_termios = tty_std_termios; | 1127 | rfcomm_tty_driver->init_termios = tty_std_termios; |
| 1099 | rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL; | 1128 | rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; |
| 1100 | rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON; | 1129 | rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON; |
| 1101 | tty_set_operations(rfcomm_tty_driver, &rfcomm_ops); | 1130 | tty_set_operations(rfcomm_tty_driver, &rfcomm_ops); |
| 1102 | 1131 | ||
diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c index cf54b22818c8..5bcc0d8b31f2 100644 --- a/net/bridge/netfilter/nf_tables_bridge.c +++ b/net/bridge/netfilter/nf_tables_bridge.c | |||
| @@ -14,10 +14,30 @@ | |||
| 14 | #include <linux/netfilter_bridge.h> | 14 | #include <linux/netfilter_bridge.h> |
| 15 | #include <net/netfilter/nf_tables.h> | 15 | #include <net/netfilter/nf_tables.h> |
| 16 | 16 | ||
| 17 | static unsigned int | ||
| 18 | nft_do_chain_bridge(const struct nf_hook_ops *ops, | ||
| 19 | struct sk_buff *skb, | ||
| 20 | const struct net_device *in, | ||
| 21 | const struct net_device *out, | ||
| 22 | int (*okfn)(struct sk_buff *)) | ||
| 23 | { | ||
| 24 | struct nft_pktinfo pkt; | ||
| 25 | |||
| 26 | nft_set_pktinfo(&pkt, ops, skb, in, out); | ||
| 27 | |||
| 28 | return nft_do_chain(&pkt, ops); | ||
| 29 | } | ||
| 30 | |||
| 17 | static struct nft_af_info nft_af_bridge __read_mostly = { | 31 | static struct nft_af_info nft_af_bridge __read_mostly = { |
| 18 | .family = NFPROTO_BRIDGE, | 32 | .family = NFPROTO_BRIDGE, |
| 19 | .nhooks = NF_BR_NUMHOOKS, | 33 | .nhooks = NF_BR_NUMHOOKS, |
| 20 | .owner = THIS_MODULE, | 34 | .owner = THIS_MODULE, |
| 35 | .nops = 1, | ||
| 36 | .hooks = { | ||
| 37 | [NF_BR_LOCAL_IN] = nft_do_chain_bridge, | ||
| 38 | [NF_BR_FORWARD] = nft_do_chain_bridge, | ||
| 39 | [NF_BR_LOCAL_OUT] = nft_do_chain_bridge, | ||
| 40 | }, | ||
| 21 | }; | 41 | }; |
| 22 | 42 | ||
| 23 | static int nf_tables_bridge_init_net(struct net *net) | 43 | static int nf_tables_bridge_init_net(struct net *net) |
| @@ -48,32 +68,14 @@ static struct pernet_operations nf_tables_bridge_net_ops = { | |||
| 48 | .exit = nf_tables_bridge_exit_net, | 68 | .exit = nf_tables_bridge_exit_net, |
| 49 | }; | 69 | }; |
| 50 | 70 | ||
| 51 | static unsigned int | 71 | static const struct nf_chain_type filter_bridge = { |
| 52 | nft_do_chain_bridge(const struct nf_hook_ops *ops, | ||
| 53 | struct sk_buff *skb, | ||
| 54 | const struct net_device *in, | ||
| 55 | const struct net_device *out, | ||
| 56 | int (*okfn)(struct sk_buff *)) | ||
| 57 | { | ||
| 58 | struct nft_pktinfo pkt; | ||
| 59 | |||
| 60 | nft_set_pktinfo(&pkt, ops, skb, in, out); | ||
| 61 | |||
| 62 | return nft_do_chain_pktinfo(&pkt, ops); | ||
| 63 | } | ||
| 64 | |||
| 65 | static struct nf_chain_type filter_bridge = { | ||
| 66 | .family = NFPROTO_BRIDGE, | ||
| 67 | .name = "filter", | 72 | .name = "filter", |
| 68 | .type = NFT_CHAIN_T_DEFAULT, | 73 | .type = NFT_CHAIN_T_DEFAULT, |
| 74 | .family = NFPROTO_BRIDGE, | ||
| 75 | .owner = THIS_MODULE, | ||
| 69 | .hook_mask = (1 << NF_BR_LOCAL_IN) | | 76 | .hook_mask = (1 << NF_BR_LOCAL_IN) | |
| 70 | (1 << NF_BR_FORWARD) | | 77 | (1 << NF_BR_FORWARD) | |
| 71 | (1 << NF_BR_LOCAL_OUT), | 78 | (1 << NF_BR_LOCAL_OUT), |
| 72 | .fn = { | ||
| 73 | [NF_BR_LOCAL_IN] = nft_do_chain_bridge, | ||
| 74 | [NF_BR_FORWARD] = nft_do_chain_bridge, | ||
| 75 | [NF_BR_LOCAL_OUT] = nft_do_chain_bridge, | ||
| 76 | }, | ||
| 77 | }; | 79 | }; |
| 78 | 80 | ||
| 79 | static int __init nf_tables_bridge_init(void) | 81 | static int __init nf_tables_bridge_init(void) |
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c index a2d2456a557a..48b25c0af4d0 100644 --- a/net/ieee802154/6lowpan.c +++ b/net/ieee802154/6lowpan.c | |||
| @@ -62,9 +62,6 @@ | |||
| 62 | 62 | ||
| 63 | #include "6lowpan.h" | 63 | #include "6lowpan.h" |
| 64 | 64 | ||
| 65 | /* TTL uncompression values */ | ||
| 66 | static const u8 lowpan_ttl_values[] = {0, 1, 64, 255}; | ||
| 67 | |||
| 68 | static LIST_HEAD(lowpan_devices); | 65 | static LIST_HEAD(lowpan_devices); |
| 69 | 66 | ||
| 70 | /* private device info */ | 67 | /* private device info */ |
| @@ -104,378 +101,14 @@ static inline void lowpan_address_flip(u8 *src, u8 *dest) | |||
| 104 | (dest)[IEEE802154_ADDR_LEN - i - 1] = (src)[i]; | 101 | (dest)[IEEE802154_ADDR_LEN - i - 1] = (src)[i]; |
| 105 | } | 102 | } |
| 106 | 103 | ||
| 107 | /* list of all 6lowpan devices, uses for package delivering */ | ||
| 108 | /* print data in line */ | ||
| 109 | static inline void lowpan_raw_dump_inline(const char *caller, char *msg, | ||
| 110 | unsigned char *buf, int len) | ||
| 111 | { | ||
| 112 | #ifdef DEBUG | ||
| 113 | if (msg) | ||
| 114 | pr_debug("(%s) %s: ", caller, msg); | ||
| 115 | print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE, | ||
| 116 | 16, 1, buf, len, false); | ||
| 117 | #endif /* DEBUG */ | ||
| 118 | } | ||
| 119 | |||
| 120 | /* | ||
| 121 | * print data in a table format: | ||
| 122 | * | ||
| 123 | * addr: xx xx xx xx xx xx | ||
| 124 | * addr: xx xx xx xx xx xx | ||
| 125 | * ... | ||
| 126 | */ | ||
| 127 | static inline void lowpan_raw_dump_table(const char *caller, char *msg, | ||
| 128 | unsigned char *buf, int len) | ||
| 129 | { | ||
| 130 | #ifdef DEBUG | ||
| 131 | if (msg) | ||
| 132 | pr_debug("(%s) %s:\n", caller, msg); | ||
| 133 | print_hex_dump(KERN_DEBUG, "\t", DUMP_PREFIX_OFFSET, | ||
| 134 | 16, 1, buf, len, false); | ||
| 135 | #endif /* DEBUG */ | ||
| 136 | } | ||
| 137 | |||
| 138 | static u8 | ||
| 139 | lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift, const struct in6_addr *ipaddr, | ||
| 140 | const unsigned char *lladdr) | ||
| 141 | { | ||
| 142 | u8 val = 0; | ||
| 143 | |||
| 144 | if (is_addr_mac_addr_based(ipaddr, lladdr)) | ||
| 145 | val = 3; /* 0-bits */ | ||
| 146 | else if (lowpan_is_iid_16_bit_compressable(ipaddr)) { | ||
| 147 | /* compress IID to 16 bits xxxx::XXXX */ | ||
| 148 | memcpy(*hc06_ptr, &ipaddr->s6_addr16[7], 2); | ||
| 149 | *hc06_ptr += 2; | ||
| 150 | val = 2; /* 16-bits */ | ||
| 151 | } else { | ||
| 152 | /* do not compress IID => xxxx::IID */ | ||
| 153 | memcpy(*hc06_ptr, &ipaddr->s6_addr16[4], 8); | ||
| 154 | *hc06_ptr += 8; | ||
| 155 | val = 1; /* 64-bits */ | ||
| 156 | } | ||
| 157 | |||
| 158 | return rol8(val, shift); | ||
| 159 | } | ||
| 160 | |||
| 161 | /* | ||
| 162 | * Uncompress address function for source and | ||
| 163 | * destination address(non-multicast). | ||
| 164 | * | ||
| 165 | * address_mode is sam value or dam value. | ||
| 166 | */ | ||
| 167 | static int | ||
| 168 | lowpan_uncompress_addr(struct sk_buff *skb, | ||
| 169 | struct in6_addr *ipaddr, | ||
| 170 | const u8 address_mode, | ||
| 171 | const struct ieee802154_addr *lladdr) | ||
| 172 | { | ||
| 173 | bool fail; | ||
| 174 | |||
| 175 | switch (address_mode) { | ||
| 176 | case LOWPAN_IPHC_ADDR_00: | ||
| 177 | /* for global link addresses */ | ||
| 178 | fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16); | ||
| 179 | break; | ||
| 180 | case LOWPAN_IPHC_ADDR_01: | ||
| 181 | /* fe:80::XXXX:XXXX:XXXX:XXXX */ | ||
| 182 | ipaddr->s6_addr[0] = 0xFE; | ||
| 183 | ipaddr->s6_addr[1] = 0x80; | ||
| 184 | fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8); | ||
| 185 | break; | ||
| 186 | case LOWPAN_IPHC_ADDR_02: | ||
| 187 | /* fe:80::ff:fe00:XXXX */ | ||
| 188 | ipaddr->s6_addr[0] = 0xFE; | ||
| 189 | ipaddr->s6_addr[1] = 0x80; | ||
| 190 | ipaddr->s6_addr[11] = 0xFF; | ||
| 191 | ipaddr->s6_addr[12] = 0xFE; | ||
| 192 | fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2); | ||
| 193 | break; | ||
| 194 | case LOWPAN_IPHC_ADDR_03: | ||
| 195 | fail = false; | ||
| 196 | switch (lladdr->addr_type) { | ||
| 197 | case IEEE802154_ADDR_LONG: | ||
| 198 | /* fe:80::XXXX:XXXX:XXXX:XXXX | ||
| 199 | * \_________________/ | ||
| 200 | * hwaddr | ||
| 201 | */ | ||
| 202 | ipaddr->s6_addr[0] = 0xFE; | ||
| 203 | ipaddr->s6_addr[1] = 0x80; | ||
| 204 | memcpy(&ipaddr->s6_addr[8], lladdr->hwaddr, | ||
| 205 | IEEE802154_ADDR_LEN); | ||
| 206 | /* second bit-flip (Universe/Local) | ||
| 207 | * is done according RFC2464 | ||
| 208 | */ | ||
| 209 | ipaddr->s6_addr[8] ^= 0x02; | ||
| 210 | break; | ||
| 211 | case IEEE802154_ADDR_SHORT: | ||
| 212 | /* fe:80::ff:fe00:XXXX | ||
| 213 | * \__/ | ||
| 214 | * short_addr | ||
| 215 | * | ||
| 216 | * Universe/Local bit is zero. | ||
| 217 | */ | ||
| 218 | ipaddr->s6_addr[0] = 0xFE; | ||
| 219 | ipaddr->s6_addr[1] = 0x80; | ||
| 220 | ipaddr->s6_addr[11] = 0xFF; | ||
| 221 | ipaddr->s6_addr[12] = 0xFE; | ||
| 222 | ipaddr->s6_addr16[7] = htons(lladdr->short_addr); | ||
| 223 | break; | ||
| 224 | default: | ||
| 225 | pr_debug("Invalid addr_type set\n"); | ||
| 226 | return -EINVAL; | ||
| 227 | } | ||
| 228 | break; | ||
| 229 | default: | ||
| 230 | pr_debug("Invalid address mode value: 0x%x\n", address_mode); | ||
| 231 | return -EINVAL; | ||
| 232 | } | ||
| 233 | |||
| 234 | if (fail) { | ||
| 235 | pr_debug("Failed to fetch skb data\n"); | ||
| 236 | return -EIO; | ||
| 237 | } | ||
| 238 | |||
| 239 | lowpan_raw_dump_inline(NULL, "Reconstructed ipv6 addr is:\n", | ||
| 240 | ipaddr->s6_addr, 16); | ||
| 241 | |||
| 242 | return 0; | ||
| 243 | } | ||
| 244 | |||
| 245 | /* Uncompress address function for source context | ||
| 246 | * based address(non-multicast). | ||
| 247 | */ | ||
| 248 | static int | ||
| 249 | lowpan_uncompress_context_based_src_addr(struct sk_buff *skb, | ||
| 250 | struct in6_addr *ipaddr, | ||
| 251 | const u8 sam) | ||
| 252 | { | ||
| 253 | switch (sam) { | ||
| 254 | case LOWPAN_IPHC_ADDR_00: | ||
| 255 | /* unspec address :: | ||
| 256 | * Do nothing, address is already :: | ||
| 257 | */ | ||
| 258 | break; | ||
| 259 | case LOWPAN_IPHC_ADDR_01: | ||
| 260 | /* TODO */ | ||
| 261 | case LOWPAN_IPHC_ADDR_02: | ||
| 262 | /* TODO */ | ||
| 263 | case LOWPAN_IPHC_ADDR_03: | ||
| 264 | /* TODO */ | ||
| 265 | netdev_warn(skb->dev, "SAM value 0x%x not supported\n", sam); | ||
| 266 | return -EINVAL; | ||
| 267 | default: | ||
| 268 | pr_debug("Invalid sam value: 0x%x\n", sam); | ||
| 269 | return -EINVAL; | ||
| 270 | } | ||
| 271 | |||
| 272 | lowpan_raw_dump_inline(NULL, | ||
| 273 | "Reconstructed context based ipv6 src addr is:\n", | ||
| 274 | ipaddr->s6_addr, 16); | ||
| 275 | |||
| 276 | return 0; | ||
| 277 | } | ||
| 278 | |||
| 279 | /* Uncompress function for multicast destination address, | ||
| 280 | * when M bit is set. | ||
| 281 | */ | ||
| 282 | static int | ||
| 283 | lowpan_uncompress_multicast_daddr(struct sk_buff *skb, | ||
| 284 | struct in6_addr *ipaddr, | ||
| 285 | const u8 dam) | ||
| 286 | { | ||
| 287 | bool fail; | ||
| 288 | |||
| 289 | switch (dam) { | ||
| 290 | case LOWPAN_IPHC_DAM_00: | ||
| 291 | /* 00: 128 bits. The full address | ||
| 292 | * is carried in-line. | ||
| 293 | */ | ||
| 294 | fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16); | ||
| 295 | break; | ||
| 296 | case LOWPAN_IPHC_DAM_01: | ||
| 297 | /* 01: 48 bits. The address takes | ||
| 298 | * the form ffXX::00XX:XXXX:XXXX. | ||
| 299 | */ | ||
| 300 | ipaddr->s6_addr[0] = 0xFF; | ||
| 301 | fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1); | ||
| 302 | fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5); | ||
| 303 | break; | ||
| 304 | case LOWPAN_IPHC_DAM_10: | ||
| 305 | /* 10: 32 bits. The address takes | ||
| 306 | * the form ffXX::00XX:XXXX. | ||
| 307 | */ | ||
| 308 | ipaddr->s6_addr[0] = 0xFF; | ||
| 309 | fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1); | ||
| 310 | fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3); | ||
| 311 | break; | ||
| 312 | case LOWPAN_IPHC_DAM_11: | ||
| 313 | /* 11: 8 bits. The address takes | ||
| 314 | * the form ff02::00XX. | ||
| 315 | */ | ||
| 316 | ipaddr->s6_addr[0] = 0xFF; | ||
| 317 | ipaddr->s6_addr[1] = 0x02; | ||
| 318 | fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1); | ||
| 319 | break; | ||
| 320 | default: | ||
| 321 | pr_debug("DAM value has a wrong value: 0x%x\n", dam); | ||
| 322 | return -EINVAL; | ||
| 323 | } | ||
| 324 | |||
| 325 | if (fail) { | ||
| 326 | pr_debug("Failed to fetch skb data\n"); | ||
| 327 | return -EIO; | ||
| 328 | } | ||
| 329 | |||
| 330 | lowpan_raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is:\n", | ||
| 331 | ipaddr->s6_addr, 16); | ||
| 332 | |||
| 333 | return 0; | ||
| 334 | } | ||
| 335 | |||
| 336 | static void | ||
| 337 | lowpan_compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb) | ||
| 338 | { | ||
| 339 | struct udphdr *uh = udp_hdr(skb); | ||
| 340 | |||
| 341 | if (((uh->source & LOWPAN_NHC_UDP_4BIT_MASK) == | ||
| 342 | LOWPAN_NHC_UDP_4BIT_PORT) && | ||
| 343 | ((uh->dest & LOWPAN_NHC_UDP_4BIT_MASK) == | ||
| 344 | LOWPAN_NHC_UDP_4BIT_PORT)) { | ||
| 345 | pr_debug("UDP header: both ports compression to 4 bits\n"); | ||
| 346 | **hc06_ptr = LOWPAN_NHC_UDP_CS_P_11; | ||
| 347 | **(hc06_ptr + 1) = /* subtraction is faster */ | ||
| 348 | (u8)((uh->dest - LOWPAN_NHC_UDP_4BIT_PORT) + | ||
| 349 | ((uh->source & LOWPAN_NHC_UDP_4BIT_PORT) << 4)); | ||
| 350 | *hc06_ptr += 2; | ||
| 351 | } else if ((uh->dest & LOWPAN_NHC_UDP_8BIT_MASK) == | ||
| 352 | LOWPAN_NHC_UDP_8BIT_PORT) { | ||
| 353 | pr_debug("UDP header: remove 8 bits of dest\n"); | ||
| 354 | **hc06_ptr = LOWPAN_NHC_UDP_CS_P_01; | ||
| 355 | memcpy(*hc06_ptr + 1, &uh->source, 2); | ||
| 356 | **(hc06_ptr + 3) = (u8)(uh->dest - LOWPAN_NHC_UDP_8BIT_PORT); | ||
| 357 | *hc06_ptr += 4; | ||
| 358 | } else if ((uh->source & LOWPAN_NHC_UDP_8BIT_MASK) == | ||
| 359 | LOWPAN_NHC_UDP_8BIT_PORT) { | ||
| 360 | pr_debug("UDP header: remove 8 bits of source\n"); | ||
| 361 | **hc06_ptr = LOWPAN_NHC_UDP_CS_P_10; | ||
| 362 | memcpy(*hc06_ptr + 1, &uh->dest, 2); | ||
| 363 | **(hc06_ptr + 3) = (u8)(uh->source - LOWPAN_NHC_UDP_8BIT_PORT); | ||
| 364 | *hc06_ptr += 4; | ||
| 365 | } else { | ||
| 366 | pr_debug("UDP header: can't compress\n"); | ||
| 367 | **hc06_ptr = LOWPAN_NHC_UDP_CS_P_00; | ||
| 368 | memcpy(*hc06_ptr + 1, &uh->source, 2); | ||
| 369 | memcpy(*hc06_ptr + 3, &uh->dest, 2); | ||
| 370 | *hc06_ptr += 5; | ||
| 371 | } | ||
| 372 | |||
| 373 | /* checksum is always inline */ | ||
| 374 | memcpy(*hc06_ptr, &uh->check, 2); | ||
| 375 | *hc06_ptr += 2; | ||
| 376 | |||
| 377 | /* skip the UDP header */ | ||
| 378 | skb_pull(skb, sizeof(struct udphdr)); | ||
| 379 | } | ||
| 380 | |||
| 381 | static inline int lowpan_fetch_skb_u8(struct sk_buff *skb, u8 *val) | ||
| 382 | { | ||
| 383 | if (unlikely(!pskb_may_pull(skb, 1))) | ||
| 384 | return -EINVAL; | ||
| 385 | |||
| 386 | *val = skb->data[0]; | ||
| 387 | skb_pull(skb, 1); | ||
| 388 | |||
| 389 | return 0; | ||
| 390 | } | ||
| 391 | |||
| 392 | static inline int lowpan_fetch_skb_u16(struct sk_buff *skb, u16 *val) | ||
| 393 | { | ||
| 394 | if (unlikely(!pskb_may_pull(skb, 2))) | ||
| 395 | return -EINVAL; | ||
| 396 | |||
| 397 | *val = (skb->data[0] << 8) | skb->data[1]; | ||
| 398 | skb_pull(skb, 2); | ||
| 399 | |||
| 400 | return 0; | ||
| 401 | } | ||
| 402 | |||
| 403 | static int | ||
| 404 | lowpan_uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh) | ||
| 405 | { | ||
| 406 | u8 tmp; | ||
| 407 | |||
| 408 | if (!uh) | ||
| 409 | goto err; | ||
| 410 | |||
| 411 | if (lowpan_fetch_skb_u8(skb, &tmp)) | ||
| 412 | goto err; | ||
| 413 | |||
| 414 | if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) { | ||
| 415 | pr_debug("UDP header uncompression\n"); | ||
| 416 | switch (tmp & LOWPAN_NHC_UDP_CS_P_11) { | ||
| 417 | case LOWPAN_NHC_UDP_CS_P_00: | ||
| 418 | memcpy(&uh->source, &skb->data[0], 2); | ||
| 419 | memcpy(&uh->dest, &skb->data[2], 2); | ||
| 420 | skb_pull(skb, 4); | ||
| 421 | break; | ||
| 422 | case LOWPAN_NHC_UDP_CS_P_01: | ||
| 423 | memcpy(&uh->source, &skb->data[0], 2); | ||
| 424 | uh->dest = | ||
| 425 | skb->data[2] + LOWPAN_NHC_UDP_8BIT_PORT; | ||
| 426 | skb_pull(skb, 3); | ||
| 427 | break; | ||
| 428 | case LOWPAN_NHC_UDP_CS_P_10: | ||
| 429 | uh->source = skb->data[0] + LOWPAN_NHC_UDP_8BIT_PORT; | ||
| 430 | memcpy(&uh->dest, &skb->data[1], 2); | ||
| 431 | skb_pull(skb, 3); | ||
| 432 | break; | ||
| 433 | case LOWPAN_NHC_UDP_CS_P_11: | ||
| 434 | uh->source = | ||
| 435 | LOWPAN_NHC_UDP_4BIT_PORT + (skb->data[0] >> 4); | ||
| 436 | uh->dest = | ||
| 437 | LOWPAN_NHC_UDP_4BIT_PORT + (skb->data[0] & 0x0f); | ||
| 438 | skb_pull(skb, 1); | ||
| 439 | break; | ||
| 440 | default: | ||
| 441 | pr_debug("ERROR: unknown UDP format\n"); | ||
| 442 | goto err; | ||
| 443 | } | ||
| 444 | |||
| 445 | pr_debug("uncompressed UDP ports: src = %d, dst = %d\n", | ||
| 446 | uh->source, uh->dest); | ||
| 447 | |||
| 448 | /* copy checksum */ | ||
| 449 | memcpy(&uh->check, &skb->data[0], 2); | ||
| 450 | skb_pull(skb, 2); | ||
| 451 | |||
| 452 | /* | ||
| 453 | * UDP lenght needs to be infered from the lower layers | ||
| 454 | * here, we obtain the hint from the remaining size of the | ||
| 455 | * frame | ||
| 456 | */ | ||
| 457 | uh->len = htons(skb->len + sizeof(struct udphdr)); | ||
| 458 | pr_debug("uncompressed UDP length: src = %d", uh->len); | ||
| 459 | } else { | ||
| 460 | pr_debug("ERROR: unsupported NH format\n"); | ||
| 461 | goto err; | ||
| 462 | } | ||
| 463 | |||
| 464 | return 0; | ||
| 465 | err: | ||
| 466 | return -EINVAL; | ||
| 467 | } | ||
| 468 | |||
| 469 | static int lowpan_header_create(struct sk_buff *skb, | 104 | static int lowpan_header_create(struct sk_buff *skb, |
| 470 | struct net_device *dev, | 105 | struct net_device *dev, |
| 471 | unsigned short type, const void *_daddr, | 106 | unsigned short type, const void *_daddr, |
| 472 | const void *_saddr, unsigned int len) | 107 | const void *_saddr, unsigned int len) |
| 473 | { | 108 | { |
| 474 | u8 tmp, iphc0, iphc1, *hc06_ptr; | ||
| 475 | struct ipv6hdr *hdr; | 109 | struct ipv6hdr *hdr; |
| 476 | const u8 *saddr = _saddr; | 110 | const u8 *saddr = _saddr; |
| 477 | const u8 *daddr = _daddr; | 111 | const u8 *daddr = _daddr; |
| 478 | u8 head[100]; | ||
| 479 | struct ieee802154_addr sa, da; | 112 | struct ieee802154_addr sa, da; |
| 480 | 113 | ||
| 481 | /* TODO: | 114 | /* TODO: |
| @@ -485,181 +118,14 @@ static int lowpan_header_create(struct sk_buff *skb, | |||
| 485 | return 0; | 118 | return 0; |
| 486 | 119 | ||
| 487 | hdr = ipv6_hdr(skb); | 120 | hdr = ipv6_hdr(skb); |
| 488 | hc06_ptr = head + 2; | ||
| 489 | |||
| 490 | pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n" | ||
| 491 | "\tnexthdr = 0x%02x\n\thop_lim = %d\n", hdr->version, | ||
| 492 | ntohs(hdr->payload_len), hdr->nexthdr, hdr->hop_limit); | ||
| 493 | |||
| 494 | lowpan_raw_dump_table(__func__, "raw skb network header dump", | ||
| 495 | skb_network_header(skb), sizeof(struct ipv6hdr)); | ||
| 496 | 121 | ||
| 497 | if (!saddr) | 122 | if (!saddr) |
| 498 | saddr = dev->dev_addr; | 123 | saddr = dev->dev_addr; |
| 499 | 124 | ||
| 500 | lowpan_raw_dump_inline(__func__, "saddr", (unsigned char *)saddr, 8); | 125 | raw_dump_inline(__func__, "saddr", (unsigned char *)saddr, 8); |
| 501 | 126 | raw_dump_inline(__func__, "daddr", (unsigned char *)daddr, 8); | |
| 502 | /* | ||
| 503 | * As we copy some bit-length fields, in the IPHC encoding bytes, | ||
| 504 | * we sometimes use |= | ||
| 505 | * If the field is 0, and the current bit value in memory is 1, | ||
| 506 | * this does not work. We therefore reset the IPHC encoding here | ||
| 507 | */ | ||
| 508 | iphc0 = LOWPAN_DISPATCH_IPHC; | ||
| 509 | iphc1 = 0; | ||
| 510 | |||
| 511 | /* TODO: context lookup */ | ||
| 512 | 127 | ||
| 513 | lowpan_raw_dump_inline(__func__, "daddr", (unsigned char *)daddr, 8); | 128 | lowpan_header_compress(skb, dev, type, daddr, saddr, len); |
| 514 | |||
| 515 | /* | ||
| 516 | * Traffic class, flow label | ||
| 517 | * If flow label is 0, compress it. If traffic class is 0, compress it | ||
| 518 | * We have to process both in the same time as the offset of traffic | ||
| 519 | * class depends on the presence of version and flow label | ||
| 520 | */ | ||
| 521 | |||
| 522 | /* hc06 format of TC is ECN | DSCP , original one is DSCP | ECN */ | ||
| 523 | tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4); | ||
| 524 | tmp = ((tmp & 0x03) << 6) | (tmp >> 2); | ||
| 525 | |||
| 526 | if (((hdr->flow_lbl[0] & 0x0F) == 0) && | ||
| 527 | (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) { | ||
| 528 | /* flow label can be compressed */ | ||
| 529 | iphc0 |= LOWPAN_IPHC_FL_C; | ||
| 530 | if ((hdr->priority == 0) && | ||
| 531 | ((hdr->flow_lbl[0] & 0xF0) == 0)) { | ||
| 532 | /* compress (elide) all */ | ||
| 533 | iphc0 |= LOWPAN_IPHC_TC_C; | ||
| 534 | } else { | ||
| 535 | /* compress only the flow label */ | ||
| 536 | *hc06_ptr = tmp; | ||
| 537 | hc06_ptr += 1; | ||
| 538 | } | ||
| 539 | } else { | ||
| 540 | /* Flow label cannot be compressed */ | ||
| 541 | if ((hdr->priority == 0) && | ||
| 542 | ((hdr->flow_lbl[0] & 0xF0) == 0)) { | ||
| 543 | /* compress only traffic class */ | ||
| 544 | iphc0 |= LOWPAN_IPHC_TC_C; | ||
| 545 | *hc06_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F); | ||
| 546 | memcpy(hc06_ptr + 1, &hdr->flow_lbl[1], 2); | ||
| 547 | hc06_ptr += 3; | ||
| 548 | } else { | ||
| 549 | /* compress nothing */ | ||
| 550 | memcpy(hc06_ptr, hdr, 4); | ||
| 551 | /* replace the top byte with new ECN | DSCP format */ | ||
| 552 | *hc06_ptr = tmp; | ||
| 553 | hc06_ptr += 4; | ||
| 554 | } | ||
| 555 | } | ||
| 556 | |||
| 557 | /* NOTE: payload length is always compressed */ | ||
| 558 | |||
| 559 | /* Next Header is compress if UDP */ | ||
| 560 | if (hdr->nexthdr == UIP_PROTO_UDP) | ||
| 561 | iphc0 |= LOWPAN_IPHC_NH_C; | ||
| 562 | |||
| 563 | if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { | ||
| 564 | *hc06_ptr = hdr->nexthdr; | ||
| 565 | hc06_ptr += 1; | ||
| 566 | } | ||
| 567 | |||
| 568 | /* | ||
| 569 | * Hop limit | ||
| 570 | * if 1: compress, encoding is 01 | ||
| 571 | * if 64: compress, encoding is 10 | ||
| 572 | * if 255: compress, encoding is 11 | ||
| 573 | * else do not compress | ||
| 574 | */ | ||
| 575 | switch (hdr->hop_limit) { | ||
| 576 | case 1: | ||
| 577 | iphc0 |= LOWPAN_IPHC_TTL_1; | ||
| 578 | break; | ||
| 579 | case 64: | ||
| 580 | iphc0 |= LOWPAN_IPHC_TTL_64; | ||
| 581 | break; | ||
| 582 | case 255: | ||
| 583 | iphc0 |= LOWPAN_IPHC_TTL_255; | ||
| 584 | break; | ||
| 585 | default: | ||
| 586 | *hc06_ptr = hdr->hop_limit; | ||
| 587 | hc06_ptr += 1; | ||
| 588 | break; | ||
| 589 | } | ||
| 590 | |||
| 591 | /* source address compression */ | ||
| 592 | if (is_addr_unspecified(&hdr->saddr)) { | ||
| 593 | pr_debug("source address is unspecified, setting SAC\n"); | ||
| 594 | iphc1 |= LOWPAN_IPHC_SAC; | ||
| 595 | /* TODO: context lookup */ | ||
| 596 | } else if (is_addr_link_local(&hdr->saddr)) { | ||
| 597 | pr_debug("source address is link-local\n"); | ||
| 598 | iphc1 |= lowpan_compress_addr_64(&hc06_ptr, | ||
| 599 | LOWPAN_IPHC_SAM_BIT, &hdr->saddr, saddr); | ||
| 600 | } else { | ||
| 601 | pr_debug("send the full source address\n"); | ||
| 602 | memcpy(hc06_ptr, &hdr->saddr.s6_addr16[0], 16); | ||
| 603 | hc06_ptr += 16; | ||
| 604 | } | ||
| 605 | |||
| 606 | /* destination address compression */ | ||
| 607 | if (is_addr_mcast(&hdr->daddr)) { | ||
| 608 | pr_debug("destination address is multicast: "); | ||
| 609 | iphc1 |= LOWPAN_IPHC_M; | ||
| 610 | if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) { | ||
| 611 | pr_debug("compressed to 1 octet\n"); | ||
| 612 | iphc1 |= LOWPAN_IPHC_DAM_11; | ||
| 613 | /* use last byte */ | ||
| 614 | *hc06_ptr = hdr->daddr.s6_addr[15]; | ||
| 615 | hc06_ptr += 1; | ||
| 616 | } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) { | ||
| 617 | pr_debug("compressed to 4 octets\n"); | ||
| 618 | iphc1 |= LOWPAN_IPHC_DAM_10; | ||
| 619 | /* second byte + the last three */ | ||
| 620 | *hc06_ptr = hdr->daddr.s6_addr[1]; | ||
| 621 | memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[13], 3); | ||
| 622 | hc06_ptr += 4; | ||
| 623 | } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) { | ||
| 624 | pr_debug("compressed to 6 octets\n"); | ||
| 625 | iphc1 |= LOWPAN_IPHC_DAM_01; | ||
| 626 | /* second byte + the last five */ | ||
| 627 | *hc06_ptr = hdr->daddr.s6_addr[1]; | ||
| 628 | memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[11], 5); | ||
| 629 | hc06_ptr += 6; | ||
| 630 | } else { | ||
| 631 | pr_debug("using full address\n"); | ||
| 632 | iphc1 |= LOWPAN_IPHC_DAM_00; | ||
| 633 | memcpy(hc06_ptr, &hdr->daddr.s6_addr[0], 16); | ||
| 634 | hc06_ptr += 16; | ||
| 635 | } | ||
| 636 | } else { | ||
| 637 | /* TODO: context lookup */ | ||
| 638 | if (is_addr_link_local(&hdr->daddr)) { | ||
| 639 | pr_debug("dest address is unicast and link-local\n"); | ||
| 640 | iphc1 |= lowpan_compress_addr_64(&hc06_ptr, | ||
| 641 | LOWPAN_IPHC_DAM_BIT, &hdr->daddr, daddr); | ||
| 642 | } else { | ||
| 643 | pr_debug("dest address is unicast: using full one\n"); | ||
| 644 | memcpy(hc06_ptr, &hdr->daddr.s6_addr16[0], 16); | ||
| 645 | hc06_ptr += 16; | ||
| 646 | } | ||
| 647 | } | ||
| 648 | |||
| 649 | /* UDP header compression */ | ||
| 650 | if (hdr->nexthdr == UIP_PROTO_UDP) | ||
| 651 | lowpan_compress_udp_header(&hc06_ptr, skb); | ||
| 652 | |||
| 653 | head[0] = iphc0; | ||
| 654 | head[1] = iphc1; | ||
| 655 | |||
| 656 | skb_pull(skb, sizeof(struct ipv6hdr)); | ||
| 657 | skb_reset_transport_header(skb); | ||
| 658 | memcpy(skb_push(skb, hc06_ptr - head), head, hc06_ptr - head); | ||
| 659 | skb_reset_network_header(skb); | ||
| 660 | |||
| 661 | lowpan_raw_dump_table(__func__, "raw skb data dump", skb->data, | ||
| 662 | skb->len); | ||
| 663 | 129 | ||
| 664 | /* | 130 | /* |
| 665 | * NOTE1: I'm still unsure about the fact that compression and WPAN | 131 | * NOTE1: I'm still unsure about the fact that compression and WPAN |
| @@ -671,39 +137,38 @@ static int lowpan_header_create(struct sk_buff *skb, | |||
| 671 | * from MAC subif of the 'dev' and 'real_dev' network devices, but | 137 | * from MAC subif of the 'dev' and 'real_dev' network devices, but |
| 672 | * this isn't implemented in mainline yet, so currently we assign 0xff | 138 | * this isn't implemented in mainline yet, so currently we assign 0xff |
| 673 | */ | 139 | */ |
| 674 | { | 140 | mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA; |
| 675 | mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA; | 141 | mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev); |
| 676 | mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev); | ||
| 677 | 142 | ||
| 678 | /* prepare wpan address data */ | 143 | /* prepare wpan address data */ |
| 679 | sa.addr_type = IEEE802154_ADDR_LONG; | 144 | sa.addr_type = IEEE802154_ADDR_LONG; |
| 680 | sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); | 145 | sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); |
| 681 | 146 | ||
| 682 | memcpy(&(sa.hwaddr), saddr, 8); | 147 | memcpy(&(sa.hwaddr), saddr, 8); |
| 683 | /* intra-PAN communications */ | 148 | /* intra-PAN communications */ |
| 684 | da.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); | 149 | da.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); |
| 685 | 150 | ||
| 686 | /* | 151 | /* |
| 687 | * if the destination address is the broadcast address, use the | 152 | * if the destination address is the broadcast address, use the |
| 688 | * corresponding short address | 153 | * corresponding short address |
| 689 | */ | 154 | */ |
| 690 | if (lowpan_is_addr_broadcast(daddr)) { | 155 | if (lowpan_is_addr_broadcast(daddr)) { |
| 691 | da.addr_type = IEEE802154_ADDR_SHORT; | 156 | da.addr_type = IEEE802154_ADDR_SHORT; |
| 692 | da.short_addr = IEEE802154_ADDR_BROADCAST; | 157 | da.short_addr = IEEE802154_ADDR_BROADCAST; |
| 693 | } else { | 158 | } else { |
| 694 | da.addr_type = IEEE802154_ADDR_LONG; | 159 | da.addr_type = IEEE802154_ADDR_LONG; |
| 695 | memcpy(&(da.hwaddr), daddr, IEEE802154_ADDR_LEN); | 160 | memcpy(&(da.hwaddr), daddr, IEEE802154_ADDR_LEN); |
| 696 | |||
| 697 | /* request acknowledgment */ | ||
| 698 | mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ; | ||
| 699 | } | ||
| 700 | 161 | ||
| 701 | return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev, | 162 | /* request acknowledgment */ |
| 702 | type, (void *)&da, (void *)&sa, skb->len); | 163 | mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ; |
| 703 | } | 164 | } |
| 165 | |||
| 166 | return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev, | ||
| 167 | type, (void *)&da, (void *)&sa, skb->len); | ||
| 704 | } | 168 | } |
| 705 | 169 | ||
| 706 | static int lowpan_give_skb_to_devices(struct sk_buff *skb) | 170 | static int lowpan_give_skb_to_devices(struct sk_buff *skb, |
| 171 | struct net_device *dev) | ||
| 707 | { | 172 | { |
| 708 | struct lowpan_dev_record *entry; | 173 | struct lowpan_dev_record *entry; |
| 709 | struct sk_buff *skb_cp; | 174 | struct sk_buff *skb_cp; |
| @@ -726,31 +191,6 @@ static int lowpan_give_skb_to_devices(struct sk_buff *skb) | |||
| 726 | return stat; | 191 | return stat; |
| 727 | } | 192 | } |
| 728 | 193 | ||
| 729 | static int lowpan_skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr) | ||
| 730 | { | ||
| 731 | struct sk_buff *new; | ||
| 732 | int stat = NET_RX_SUCCESS; | ||
| 733 | |||
| 734 | new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb), | ||
| 735 | GFP_ATOMIC); | ||
| 736 | kfree_skb(skb); | ||
| 737 | |||
| 738 | if (!new) | ||
| 739 | return -ENOMEM; | ||
| 740 | |||
| 741 | skb_push(new, sizeof(struct ipv6hdr)); | ||
| 742 | skb_copy_to_linear_data(new, hdr, sizeof(struct ipv6hdr)); | ||
| 743 | |||
| 744 | new->protocol = htons(ETH_P_IPV6); | ||
| 745 | new->pkt_type = PACKET_HOST; | ||
| 746 | |||
| 747 | stat = lowpan_give_skb_to_devices(new); | ||
| 748 | |||
| 749 | kfree_skb(new); | ||
| 750 | |||
| 751 | return stat; | ||
| 752 | } | ||
| 753 | |||
| 754 | static void lowpan_fragment_timer_expired(unsigned long entry_addr) | 194 | static void lowpan_fragment_timer_expired(unsigned long entry_addr) |
| 755 | { | 195 | { |
| 756 | struct lowpan_fragment *entry = (struct lowpan_fragment *)entry_addr; | 196 | struct lowpan_fragment *entry = (struct lowpan_fragment *)entry_addr; |
| @@ -814,16 +254,12 @@ frame_err: | |||
| 814 | return NULL; | 254 | return NULL; |
| 815 | } | 255 | } |
| 816 | 256 | ||
| 817 | static int | 257 | static int process_data(struct sk_buff *skb) |
| 818 | lowpan_process_data(struct sk_buff *skb) | ||
| 819 | { | 258 | { |
| 820 | struct ipv6hdr hdr = {}; | 259 | u8 iphc0, iphc1; |
| 821 | u8 tmp, iphc0, iphc1, num_context = 0; | ||
| 822 | const struct ieee802154_addr *_saddr, *_daddr; | 260 | const struct ieee802154_addr *_saddr, *_daddr; |
| 823 | int err; | ||
| 824 | 261 | ||
| 825 | lowpan_raw_dump_table(__func__, "raw skb data dump", skb->data, | 262 | raw_dump_table(__func__, "raw skb data dump", skb->data, skb->len); |
| 826 | skb->len); | ||
| 827 | /* at least two bytes will be used for the encoding */ | 263 | /* at least two bytes will be used for the encoding */ |
| 828 | if (skb->len < 2) | 264 | if (skb->len < 2) |
| 829 | goto drop; | 265 | goto drop; |
| @@ -925,162 +361,11 @@ lowpan_process_data(struct sk_buff *skb) | |||
| 925 | _saddr = &mac_cb(skb)->sa; | 361 | _saddr = &mac_cb(skb)->sa; |
| 926 | _daddr = &mac_cb(skb)->da; | 362 | _daddr = &mac_cb(skb)->da; |
| 927 | 363 | ||
| 928 | pr_debug("iphc0 = %02x, iphc1 = %02x\n", iphc0, iphc1); | 364 | return lowpan_process_data(skb, skb->dev, (u8 *)_saddr->hwaddr, |
| 929 | 365 | _saddr->addr_type, IEEE802154_ADDR_LEN, | |
| 930 | /* another if the CID flag is set */ | 366 | (u8 *)_daddr->hwaddr, _daddr->addr_type, |
| 931 | if (iphc1 & LOWPAN_IPHC_CID) { | 367 | IEEE802154_ADDR_LEN, iphc0, iphc1, |
| 932 | pr_debug("CID flag is set, increase header with one\n"); | 368 | lowpan_give_skb_to_devices); |
| 933 | if (lowpan_fetch_skb_u8(skb, &num_context)) | ||
| 934 | goto drop; | ||
| 935 | } | ||
| 936 | |||
| 937 | hdr.version = 6; | ||
| 938 | |||
| 939 | /* Traffic Class and Flow Label */ | ||
| 940 | switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) { | ||
| 941 | /* | ||
| 942 | * Traffic Class and FLow Label carried in-line | ||
| 943 | * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes) | ||
| 944 | */ | ||
| 945 | case 0: /* 00b */ | ||
| 946 | if (lowpan_fetch_skb_u8(skb, &tmp)) | ||
| 947 | goto drop; | ||
| 948 | |||
| 949 | memcpy(&hdr.flow_lbl, &skb->data[0], 3); | ||
| 950 | skb_pull(skb, 3); | ||
| 951 | hdr.priority = ((tmp >> 2) & 0x0f); | ||
| 952 | hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) | | ||
| 953 | (hdr.flow_lbl[0] & 0x0f); | ||
| 954 | break; | ||
| 955 | /* | ||
| 956 | * Traffic class carried in-line | ||
| 957 | * ECN + DSCP (1 byte), Flow Label is elided | ||
| 958 | */ | ||
| 959 | case 2: /* 10b */ | ||
| 960 | if (lowpan_fetch_skb_u8(skb, &tmp)) | ||
| 961 | goto drop; | ||
| 962 | |||
| 963 | hdr.priority = ((tmp >> 2) & 0x0f); | ||
| 964 | hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30); | ||
| 965 | break; | ||
| 966 | /* | ||
| 967 | * Flow Label carried in-line | ||
| 968 | * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided | ||
| 969 | */ | ||
| 970 | case 1: /* 01b */ | ||
| 971 | if (lowpan_fetch_skb_u8(skb, &tmp)) | ||
| 972 | goto drop; | ||
| 973 | |||
| 974 | hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30); | ||
| 975 | memcpy(&hdr.flow_lbl[1], &skb->data[0], 2); | ||
| 976 | skb_pull(skb, 2); | ||
| 977 | break; | ||
| 978 | /* Traffic Class and Flow Label are elided */ | ||
| 979 | case 3: /* 11b */ | ||
| 980 | break; | ||
| 981 | default: | ||
| 982 | break; | ||
| 983 | } | ||
| 984 | |||
| 985 | /* Next Header */ | ||
| 986 | if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { | ||
| 987 | /* Next header is carried inline */ | ||
| 988 | if (lowpan_fetch_skb_u8(skb, &(hdr.nexthdr))) | ||
| 989 | goto drop; | ||
| 990 | |||
| 991 | pr_debug("NH flag is set, next header carried inline: %02x\n", | ||
| 992 | hdr.nexthdr); | ||
| 993 | } | ||
| 994 | |||
| 995 | /* Hop Limit */ | ||
| 996 | if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I) | ||
| 997 | hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03]; | ||
| 998 | else { | ||
| 999 | if (lowpan_fetch_skb_u8(skb, &(hdr.hop_limit))) | ||
| 1000 | goto drop; | ||
| 1001 | } | ||
| 1002 | |||
| 1003 | /* Extract SAM to the tmp variable */ | ||
| 1004 | tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03; | ||
| 1005 | |||
| 1006 | if (iphc1 & LOWPAN_IPHC_SAC) { | ||
| 1007 | /* Source address context based uncompression */ | ||
| 1008 | pr_debug("SAC bit is set. Handle context based source address.\n"); | ||
| 1009 | err = lowpan_uncompress_context_based_src_addr( | ||
| 1010 | skb, &hdr.saddr, tmp); | ||
| 1011 | } else { | ||
| 1012 | /* Source address uncompression */ | ||
| 1013 | pr_debug("source address stateless compression\n"); | ||
| 1014 | err = lowpan_uncompress_addr(skb, &hdr.saddr, tmp, _saddr); | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | /* Check on error of previous branch */ | ||
| 1018 | if (err) | ||
| 1019 | goto drop; | ||
| 1020 | |||
| 1021 | /* Extract DAM to the tmp variable */ | ||
| 1022 | tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03; | ||
| 1023 | |||
| 1024 | /* check for Multicast Compression */ | ||
| 1025 | if (iphc1 & LOWPAN_IPHC_M) { | ||
| 1026 | if (iphc1 & LOWPAN_IPHC_DAC) { | ||
| 1027 | pr_debug("dest: context-based mcast compression\n"); | ||
| 1028 | /* TODO: implement this */ | ||
| 1029 | } else { | ||
| 1030 | err = lowpan_uncompress_multicast_daddr( | ||
| 1031 | skb, &hdr.daddr, tmp); | ||
| 1032 | if (err) | ||
| 1033 | goto drop; | ||
| 1034 | } | ||
| 1035 | } else { | ||
| 1036 | pr_debug("dest: stateless compression\n"); | ||
| 1037 | err = lowpan_uncompress_addr(skb, &hdr.daddr, tmp, _daddr); | ||
| 1038 | if (err) | ||
| 1039 | goto drop; | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | /* UDP data uncompression */ | ||
| 1043 | if (iphc0 & LOWPAN_IPHC_NH_C) { | ||
| 1044 | struct udphdr uh; | ||
| 1045 | struct sk_buff *new; | ||
| 1046 | if (lowpan_uncompress_udp_header(skb, &uh)) | ||
| 1047 | goto drop; | ||
| 1048 | |||
| 1049 | /* | ||
| 1050 | * replace the compressed UDP head by the uncompressed UDP | ||
| 1051 | * header | ||
| 1052 | */ | ||
| 1053 | new = skb_copy_expand(skb, sizeof(struct udphdr), | ||
| 1054 | skb_tailroom(skb), GFP_ATOMIC); | ||
| 1055 | kfree_skb(skb); | ||
| 1056 | |||
| 1057 | if (!new) | ||
| 1058 | return -ENOMEM; | ||
| 1059 | |||
| 1060 | skb = new; | ||
| 1061 | |||
| 1062 | skb_push(skb, sizeof(struct udphdr)); | ||
| 1063 | skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr)); | ||
| 1064 | |||
| 1065 | lowpan_raw_dump_table(__func__, "raw UDP header dump", | ||
| 1066 | (u8 *)&uh, sizeof(uh)); | ||
| 1067 | |||
| 1068 | hdr.nexthdr = UIP_PROTO_UDP; | ||
| 1069 | } | ||
| 1070 | |||
| 1071 | /* Not fragmented package */ | ||
| 1072 | hdr.payload_len = htons(skb->len); | ||
| 1073 | |||
| 1074 | pr_debug("skb headroom size = %d, data length = %d\n", | ||
| 1075 | skb_headroom(skb), skb->len); | ||
| 1076 | |||
| 1077 | pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n\t" | ||
| 1078 | "nexthdr = 0x%02x\n\thop_lim = %d\n", hdr.version, | ||
| 1079 | ntohs(hdr.payload_len), hdr.nexthdr, hdr.hop_limit); | ||
| 1080 | |||
| 1081 | lowpan_raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, | ||
| 1082 | sizeof(hdr)); | ||
| 1083 | return lowpan_skb_deliver(skb, &hdr); | ||
| 1084 | 369 | ||
| 1085 | unlock_and_drop: | 370 | unlock_and_drop: |
| 1086 | spin_unlock_bh(&flist_lock); | 371 | spin_unlock_bh(&flist_lock); |
| @@ -1112,7 +397,7 @@ lowpan_fragment_xmit(struct sk_buff *skb, u8 *head, | |||
| 1112 | hlen = (type == LOWPAN_DISPATCH_FRAG1) ? | 397 | hlen = (type == LOWPAN_DISPATCH_FRAG1) ? |
| 1113 | LOWPAN_FRAG1_HEAD_SIZE : LOWPAN_FRAGN_HEAD_SIZE; | 398 | LOWPAN_FRAG1_HEAD_SIZE : LOWPAN_FRAGN_HEAD_SIZE; |
| 1114 | 399 | ||
| 1115 | lowpan_raw_dump_inline(__func__, "6lowpan fragment header", head, hlen); | 400 | raw_dump_inline(__func__, "6lowpan fragment header", head, hlen); |
| 1116 | 401 | ||
| 1117 | frag = netdev_alloc_skb(skb->dev, | 402 | frag = netdev_alloc_skb(skb->dev, |
| 1118 | hlen + mlen + plen + IEEE802154_MFR_SIZE); | 403 | hlen + mlen + plen + IEEE802154_MFR_SIZE); |
| @@ -1132,8 +417,7 @@ lowpan_fragment_xmit(struct sk_buff *skb, u8 *head, | |||
| 1132 | skb_copy_to_linear_data_offset(frag, mlen + hlen, | 417 | skb_copy_to_linear_data_offset(frag, mlen + hlen, |
| 1133 | skb_network_header(skb) + offset, plen); | 418 | skb_network_header(skb) + offset, plen); |
| 1134 | 419 | ||
| 1135 | lowpan_raw_dump_table(__func__, " raw fragment dump", frag->data, | 420 | raw_dump_table(__func__, " raw fragment dump", frag->data, frag->len); |
| 1136 | frag->len); | ||
| 1137 | 421 | ||
| 1138 | return dev_queue_xmit(frag); | 422 | return dev_queue_xmit(frag); |
| 1139 | } | 423 | } |
| @@ -1316,7 +600,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, | |||
| 1316 | /* Pull off the 1-byte of 6lowpan header. */ | 600 | /* Pull off the 1-byte of 6lowpan header. */ |
| 1317 | skb_pull(local_skb, 1); | 601 | skb_pull(local_skb, 1); |
| 1318 | 602 | ||
| 1319 | lowpan_give_skb_to_devices(local_skb); | 603 | lowpan_give_skb_to_devices(local_skb, NULL); |
| 1320 | 604 | ||
| 1321 | kfree_skb(local_skb); | 605 | kfree_skb(local_skb); |
| 1322 | kfree_skb(skb); | 606 | kfree_skb(skb); |
| @@ -1328,7 +612,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, | |||
| 1328 | local_skb = skb_clone(skb, GFP_ATOMIC); | 612 | local_skb = skb_clone(skb, GFP_ATOMIC); |
| 1329 | if (!local_skb) | 613 | if (!local_skb) |
| 1330 | goto drop; | 614 | goto drop; |
| 1331 | lowpan_process_data(local_skb); | 615 | process_data(local_skb); |
| 1332 | 616 | ||
| 1333 | kfree_skb(skb); | 617 | kfree_skb(skb); |
| 1334 | break; | 618 | break; |
diff --git a/net/ieee802154/6lowpan.h b/net/ieee802154/6lowpan.h index 2869c0526dad..2b835db3bda8 100644 --- a/net/ieee802154/6lowpan.h +++ b/net/ieee802154/6lowpan.h | |||
| @@ -231,6 +231,61 @@ | |||
| 231 | #define LOWPAN_NHC_UDP_CS_P_10 0xF2 /* source = 0xF0 + 8bit inline, | 231 | #define LOWPAN_NHC_UDP_CS_P_10 0xF2 /* source = 0xF0 + 8bit inline, |
| 232 | dest = 16 bit inline */ | 232 | dest = 16 bit inline */ |
| 233 | #define LOWPAN_NHC_UDP_CS_P_11 0xF3 /* source & dest = 0xF0B + 4bit inline */ | 233 | #define LOWPAN_NHC_UDP_CS_P_11 0xF3 /* source & dest = 0xF0B + 4bit inline */ |
| 234 | #define LOWPAN_NHC_UDP_CS_C 0x04 /* checksum elided */ | ||
| 235 | |||
| 236 | #ifdef DEBUG | ||
| 237 | /* print data in line */ | ||
| 238 | static inline void raw_dump_inline(const char *caller, char *msg, | ||
| 239 | unsigned char *buf, int len) | ||
| 240 | { | ||
| 241 | if (msg) | ||
| 242 | pr_debug("%s():%s: ", caller, msg); | ||
| 243 | |||
| 244 | print_hex_dump_debug("", DUMP_PREFIX_NONE, 16, 1, buf, len, false); | ||
| 245 | } | ||
| 246 | |||
| 247 | /* print data in a table format: | ||
| 248 | * | ||
| 249 | * addr: xx xx xx xx xx xx | ||
| 250 | * addr: xx xx xx xx xx xx | ||
| 251 | * ... | ||
| 252 | */ | ||
| 253 | static inline void raw_dump_table(const char *caller, char *msg, | ||
| 254 | unsigned char *buf, int len) | ||
| 255 | { | ||
| 256 | if (msg) | ||
| 257 | pr_debug("%s():%s:\n", caller, msg); | ||
| 258 | |||
| 259 | print_hex_dump_debug("\t", DUMP_PREFIX_OFFSET, 16, 1, buf, len, false); | ||
| 260 | } | ||
| 261 | #else | ||
| 262 | static inline void raw_dump_table(const char *caller, char *msg, | ||
| 263 | unsigned char *buf, int len) { } | ||
| 264 | static inline void raw_dump_inline(const char *caller, char *msg, | ||
| 265 | unsigned char *buf, int len) { } | ||
| 266 | #endif | ||
| 267 | |||
| 268 | static inline int lowpan_fetch_skb_u8(struct sk_buff *skb, u8 *val) | ||
| 269 | { | ||
| 270 | if (unlikely(!pskb_may_pull(skb, 1))) | ||
| 271 | return -EINVAL; | ||
| 272 | |||
| 273 | *val = skb->data[0]; | ||
| 274 | skb_pull(skb, 1); | ||
| 275 | |||
| 276 | return 0; | ||
| 277 | } | ||
| 278 | |||
| 279 | static inline int lowpan_fetch_skb_u16(struct sk_buff *skb, u16 *val) | ||
| 280 | { | ||
| 281 | if (unlikely(!pskb_may_pull(skb, 2))) | ||
| 282 | return -EINVAL; | ||
| 283 | |||
| 284 | *val = (skb->data[0] << 8) | skb->data[1]; | ||
| 285 | skb_pull(skb, 2); | ||
| 286 | |||
| 287 | return 0; | ||
| 288 | } | ||
| 234 | 289 | ||
| 235 | static inline bool lowpan_fetch_skb(struct sk_buff *skb, | 290 | static inline bool lowpan_fetch_skb(struct sk_buff *skb, |
| 236 | void *data, const unsigned int len) | 291 | void *data, const unsigned int len) |
| @@ -244,4 +299,21 @@ static inline bool lowpan_fetch_skb(struct sk_buff *skb, | |||
| 244 | return false; | 299 | return false; |
| 245 | } | 300 | } |
| 246 | 301 | ||
| 302 | static inline void lowpan_push_hc_data(u8 **hc_ptr, const void *data, | ||
| 303 | const size_t len) | ||
| 304 | { | ||
| 305 | memcpy(*hc_ptr, data, len); | ||
| 306 | *hc_ptr += len; | ||
| 307 | } | ||
| 308 | |||
| 309 | typedef int (*skb_delivery_cb)(struct sk_buff *skb, struct net_device *dev); | ||
| 310 | |||
| 311 | int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | ||
| 312 | const u8 *saddr, const u8 saddr_type, const u8 saddr_len, | ||
| 313 | const u8 *daddr, const u8 daddr_type, const u8 daddr_len, | ||
| 314 | u8 iphc0, u8 iphc1, skb_delivery_cb skb_deliver); | ||
| 315 | int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, | ||
| 316 | unsigned short type, const void *_daddr, | ||
| 317 | const void *_saddr, unsigned int len); | ||
| 318 | |||
| 247 | #endif /* __6LOWPAN_H__ */ | 319 | #endif /* __6LOWPAN_H__ */ |
diff --git a/net/ieee802154/6lowpan_iphc.c b/net/ieee802154/6lowpan_iphc.c new file mode 100644 index 000000000000..11840f9e46da --- /dev/null +++ b/net/ieee802154/6lowpan_iphc.c | |||
| @@ -0,0 +1,799 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2011, Siemens AG | ||
| 3 | * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com> | ||
| 4 | */ | ||
| 5 | |||
| 6 | /* | ||
| 7 | * Based on patches from Jon Smirl <jonsmirl@gmail.com> | ||
| 8 | * Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 | ||
| 12 | * as published by the Free Software Foundation. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License along | ||
| 20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 21 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 22 | */ | ||
| 23 | |||
| 24 | /* Jon's code is based on 6lowpan implementation for Contiki which is: | ||
| 25 | * Copyright (c) 2008, Swedish Institute of Computer Science. | ||
| 26 | * All rights reserved. | ||
| 27 | * | ||
| 28 | * Redistribution and use in source and binary forms, with or without | ||
| 29 | * modification, are permitted provided that the following conditions | ||
| 30 | * are met: | ||
| 31 | * 1. Redistributions of source code must retain the above copyright | ||
| 32 | * notice, this list of conditions and the following disclaimer. | ||
| 33 | * 2. Redistributions in binary form must reproduce the above copyright | ||
| 34 | * notice, this list of conditions and the following disclaimer in the | ||
| 35 | * documentation and/or other materials provided with the distribution. | ||
| 36 | * 3. Neither the name of the Institute nor the names of its contributors | ||
| 37 | * may be used to endorse or promote products derived from this software | ||
| 38 | * without specific prior written permission. | ||
| 39 | * | ||
| 40 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND | ||
| 41 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 42 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 43 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE | ||
| 44 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 45 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 46 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 47 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| 48 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
| 49 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
| 50 | * SUCH DAMAGE. | ||
| 51 | */ | ||
| 52 | |||
| 53 | #include <linux/bitops.h> | ||
| 54 | #include <linux/if_arp.h> | ||
| 55 | #include <linux/netdevice.h> | ||
| 56 | #include <net/ipv6.h> | ||
| 57 | #include <net/af_ieee802154.h> | ||
| 58 | |||
| 59 | #include "6lowpan.h" | ||
| 60 | |||
| 61 | /* | ||
| 62 | * Uncompress address function for source and | ||
| 63 | * destination address(non-multicast). | ||
| 64 | * | ||
| 65 | * address_mode is sam value or dam value. | ||
| 66 | */ | ||
| 67 | static int uncompress_addr(struct sk_buff *skb, | ||
| 68 | struct in6_addr *ipaddr, const u8 address_mode, | ||
| 69 | const u8 *lladdr, const u8 addr_type, | ||
| 70 | const u8 addr_len) | ||
| 71 | { | ||
| 72 | bool fail; | ||
| 73 | |||
| 74 | switch (address_mode) { | ||
| 75 | case LOWPAN_IPHC_ADDR_00: | ||
| 76 | /* for global link addresses */ | ||
| 77 | fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16); | ||
| 78 | break; | ||
| 79 | case LOWPAN_IPHC_ADDR_01: | ||
| 80 | /* fe:80::XXXX:XXXX:XXXX:XXXX */ | ||
| 81 | ipaddr->s6_addr[0] = 0xFE; | ||
| 82 | ipaddr->s6_addr[1] = 0x80; | ||
| 83 | fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8); | ||
| 84 | break; | ||
| 85 | case LOWPAN_IPHC_ADDR_02: | ||
| 86 | /* fe:80::ff:fe00:XXXX */ | ||
| 87 | ipaddr->s6_addr[0] = 0xFE; | ||
| 88 | ipaddr->s6_addr[1] = 0x80; | ||
| 89 | ipaddr->s6_addr[11] = 0xFF; | ||
| 90 | ipaddr->s6_addr[12] = 0xFE; | ||
| 91 | fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2); | ||
| 92 | break; | ||
| 93 | case LOWPAN_IPHC_ADDR_03: | ||
| 94 | fail = false; | ||
| 95 | switch (addr_type) { | ||
| 96 | case IEEE802154_ADDR_LONG: | ||
| 97 | /* fe:80::XXXX:XXXX:XXXX:XXXX | ||
| 98 | * \_________________/ | ||
| 99 | * hwaddr | ||
| 100 | */ | ||
| 101 | ipaddr->s6_addr[0] = 0xFE; | ||
| 102 | ipaddr->s6_addr[1] = 0x80; | ||
| 103 | memcpy(&ipaddr->s6_addr[8], lladdr, addr_len); | ||
| 104 | /* second bit-flip (Universe/Local) | ||
| 105 | * is done according RFC2464 | ||
| 106 | */ | ||
| 107 | ipaddr->s6_addr[8] ^= 0x02; | ||
| 108 | break; | ||
| 109 | case IEEE802154_ADDR_SHORT: | ||
| 110 | /* fe:80::ff:fe00:XXXX | ||
| 111 | * \__/ | ||
| 112 | * short_addr | ||
| 113 | * | ||
| 114 | * Universe/Local bit is zero. | ||
| 115 | */ | ||
| 116 | ipaddr->s6_addr[0] = 0xFE; | ||
| 117 | ipaddr->s6_addr[1] = 0x80; | ||
| 118 | ipaddr->s6_addr[11] = 0xFF; | ||
| 119 | ipaddr->s6_addr[12] = 0xFE; | ||
| 120 | ipaddr->s6_addr16[7] = htons(*((u16 *)lladdr)); | ||
| 121 | break; | ||
| 122 | default: | ||
| 123 | pr_debug("Invalid addr_type set\n"); | ||
| 124 | return -EINVAL; | ||
| 125 | } | ||
| 126 | break; | ||
| 127 | default: | ||
| 128 | pr_debug("Invalid address mode value: 0x%x\n", address_mode); | ||
| 129 | return -EINVAL; | ||
| 130 | } | ||
| 131 | |||
| 132 | if (fail) { | ||
| 133 | pr_debug("Failed to fetch skb data\n"); | ||
| 134 | return -EIO; | ||
| 135 | } | ||
| 136 | |||
| 137 | raw_dump_inline(NULL, "Reconstructed ipv6 addr is", | ||
| 138 | ipaddr->s6_addr, 16); | ||
| 139 | |||
| 140 | return 0; | ||
| 141 | } | ||
| 142 | |||
| 143 | /* | ||
| 144 | * Uncompress address function for source context | ||
| 145 | * based address(non-multicast). | ||
| 146 | */ | ||
| 147 | static int uncompress_context_based_src_addr(struct sk_buff *skb, | ||
| 148 | struct in6_addr *ipaddr, | ||
| 149 | const u8 sam) | ||
| 150 | { | ||
| 151 | switch (sam) { | ||
| 152 | case LOWPAN_IPHC_ADDR_00: | ||
| 153 | /* unspec address :: | ||
| 154 | * Do nothing, address is already :: | ||
| 155 | */ | ||
| 156 | break; | ||
| 157 | case LOWPAN_IPHC_ADDR_01: | ||
| 158 | /* TODO */ | ||
| 159 | case LOWPAN_IPHC_ADDR_02: | ||
| 160 | /* TODO */ | ||
| 161 | case LOWPAN_IPHC_ADDR_03: | ||
| 162 | /* TODO */ | ||
| 163 | netdev_warn(skb->dev, "SAM value 0x%x not supported\n", sam); | ||
| 164 | return -EINVAL; | ||
| 165 | default: | ||
| 166 | pr_debug("Invalid sam value: 0x%x\n", sam); | ||
| 167 | return -EINVAL; | ||
| 168 | } | ||
| 169 | |||
| 170 | raw_dump_inline(NULL, | ||
| 171 | "Reconstructed context based ipv6 src addr is", | ||
| 172 | ipaddr->s6_addr, 16); | ||
| 173 | |||
| 174 | return 0; | ||
| 175 | } | ||
| 176 | |||
| 177 | static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr, | ||
| 178 | struct net_device *dev, skb_delivery_cb deliver_skb) | ||
| 179 | { | ||
| 180 | struct sk_buff *new; | ||
| 181 | int stat; | ||
| 182 | |||
| 183 | new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb), | ||
| 184 | GFP_ATOMIC); | ||
| 185 | kfree_skb(skb); | ||
| 186 | |||
| 187 | if (!new) | ||
| 188 | return -ENOMEM; | ||
| 189 | |||
| 190 | skb_push(new, sizeof(struct ipv6hdr)); | ||
| 191 | skb_reset_network_header(new); | ||
| 192 | skb_copy_to_linear_data(new, hdr, sizeof(struct ipv6hdr)); | ||
| 193 | |||
| 194 | new->protocol = htons(ETH_P_IPV6); | ||
| 195 | new->pkt_type = PACKET_HOST; | ||
| 196 | new->dev = dev; | ||
| 197 | |||
| 198 | raw_dump_table(__func__, "raw skb data dump before receiving", | ||
| 199 | new->data, new->len); | ||
| 200 | |||
| 201 | stat = deliver_skb(new, dev); | ||
| 202 | |||
| 203 | kfree_skb(new); | ||
| 204 | |||
| 205 | return stat; | ||
| 206 | } | ||
| 207 | |||
| 208 | /* Uncompress function for multicast destination address, | ||
| 209 | * when M bit is set. | ||
| 210 | */ | ||
| 211 | static int | ||
| 212 | lowpan_uncompress_multicast_daddr(struct sk_buff *skb, | ||
| 213 | struct in6_addr *ipaddr, | ||
| 214 | const u8 dam) | ||
| 215 | { | ||
| 216 | bool fail; | ||
| 217 | |||
| 218 | switch (dam) { | ||
| 219 | case LOWPAN_IPHC_DAM_00: | ||
| 220 | /* 00: 128 bits. The full address | ||
| 221 | * is carried in-line. | ||
| 222 | */ | ||
| 223 | fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16); | ||
| 224 | break; | ||
| 225 | case LOWPAN_IPHC_DAM_01: | ||
| 226 | /* 01: 48 bits. The address takes | ||
| 227 | * the form ffXX::00XX:XXXX:XXXX. | ||
| 228 | */ | ||
| 229 | ipaddr->s6_addr[0] = 0xFF; | ||
| 230 | fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1); | ||
| 231 | fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5); | ||
| 232 | break; | ||
| 233 | case LOWPAN_IPHC_DAM_10: | ||
| 234 | /* 10: 32 bits. The address takes | ||
| 235 | * the form ffXX::00XX:XXXX. | ||
| 236 | */ | ||
| 237 | ipaddr->s6_addr[0] = 0xFF; | ||
| 238 | fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1); | ||
| 239 | fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3); | ||
| 240 | break; | ||
| 241 | case LOWPAN_IPHC_DAM_11: | ||
| 242 | /* 11: 8 bits. The address takes | ||
| 243 | * the form ff02::00XX. | ||
| 244 | */ | ||
| 245 | ipaddr->s6_addr[0] = 0xFF; | ||
| 246 | ipaddr->s6_addr[1] = 0x02; | ||
| 247 | fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1); | ||
| 248 | break; | ||
| 249 | default: | ||
| 250 | pr_debug("DAM value has a wrong value: 0x%x\n", dam); | ||
| 251 | return -EINVAL; | ||
| 252 | } | ||
| 253 | |||
| 254 | if (fail) { | ||
| 255 | pr_debug("Failed to fetch skb data\n"); | ||
| 256 | return -EIO; | ||
| 257 | } | ||
| 258 | |||
| 259 | raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is", | ||
| 260 | ipaddr->s6_addr, 16); | ||
| 261 | |||
| 262 | return 0; | ||
| 263 | } | ||
| 264 | |||
| 265 | static int | ||
| 266 | uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh) | ||
| 267 | { | ||
| 268 | bool fail; | ||
| 269 | u8 tmp = 0, val = 0; | ||
| 270 | |||
| 271 | if (!uh) | ||
| 272 | goto err; | ||
| 273 | |||
| 274 | fail = lowpan_fetch_skb(skb, &tmp, 1); | ||
| 275 | |||
| 276 | if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) { | ||
| 277 | pr_debug("UDP header uncompression\n"); | ||
| 278 | switch (tmp & LOWPAN_NHC_UDP_CS_P_11) { | ||
| 279 | case LOWPAN_NHC_UDP_CS_P_00: | ||
| 280 | fail |= lowpan_fetch_skb(skb, &uh->source, 2); | ||
| 281 | fail |= lowpan_fetch_skb(skb, &uh->dest, 2); | ||
| 282 | break; | ||
| 283 | case LOWPAN_NHC_UDP_CS_P_01: | ||
| 284 | fail |= lowpan_fetch_skb(skb, &uh->source, 2); | ||
| 285 | fail |= lowpan_fetch_skb(skb, &val, 1); | ||
| 286 | uh->dest = htons(val + LOWPAN_NHC_UDP_8BIT_PORT); | ||
| 287 | break; | ||
| 288 | case LOWPAN_NHC_UDP_CS_P_10: | ||
| 289 | fail |= lowpan_fetch_skb(skb, &val, 1); | ||
| 290 | uh->source = htons(val + LOWPAN_NHC_UDP_8BIT_PORT); | ||
| 291 | fail |= lowpan_fetch_skb(skb, &uh->dest, 2); | ||
| 292 | break; | ||
| 293 | case LOWPAN_NHC_UDP_CS_P_11: | ||
| 294 | fail |= lowpan_fetch_skb(skb, &val, 1); | ||
| 295 | uh->source = htons(LOWPAN_NHC_UDP_4BIT_PORT + | ||
| 296 | (val >> 4)); | ||
| 297 | uh->dest = htons(LOWPAN_NHC_UDP_4BIT_PORT + | ||
| 298 | (val & 0x0f)); | ||
| 299 | break; | ||
| 300 | default: | ||
| 301 | pr_debug("ERROR: unknown UDP format\n"); | ||
| 302 | goto err; | ||
| 303 | break; | ||
| 304 | } | ||
| 305 | |||
| 306 | pr_debug("uncompressed UDP ports: src = %d, dst = %d\n", | ||
| 307 | ntohs(uh->source), ntohs(uh->dest)); | ||
| 308 | |||
| 309 | /* checksum */ | ||
| 310 | if (tmp & LOWPAN_NHC_UDP_CS_C) { | ||
| 311 | pr_debug_ratelimited("checksum elided currently not supported\n"); | ||
| 312 | goto err; | ||
| 313 | } else { | ||
| 314 | fail |= lowpan_fetch_skb(skb, &uh->check, 2); | ||
| 315 | } | ||
| 316 | |||
| 317 | /* | ||
| 318 | * UDP lenght needs to be infered from the lower layers | ||
| 319 | * here, we obtain the hint from the remaining size of the | ||
| 320 | * frame | ||
| 321 | */ | ||
| 322 | uh->len = htons(skb->len + sizeof(struct udphdr)); | ||
| 323 | pr_debug("uncompressed UDP length: src = %d", ntohs(uh->len)); | ||
| 324 | } else { | ||
| 325 | pr_debug("ERROR: unsupported NH format\n"); | ||
| 326 | goto err; | ||
| 327 | } | ||
| 328 | |||
| 329 | if (fail) | ||
| 330 | goto err; | ||
| 331 | |||
| 332 | return 0; | ||
| 333 | err: | ||
| 334 | return -EINVAL; | ||
| 335 | } | ||
| 336 | |||
| 337 | /* TTL uncompression values */ | ||
| 338 | static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 }; | ||
| 339 | |||
| 340 | int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | ||
| 341 | const u8 *saddr, const u8 saddr_type, const u8 saddr_len, | ||
| 342 | const u8 *daddr, const u8 daddr_type, const u8 daddr_len, | ||
| 343 | u8 iphc0, u8 iphc1, skb_delivery_cb deliver_skb) | ||
| 344 | { | ||
| 345 | struct ipv6hdr hdr = {}; | ||
| 346 | u8 tmp, num_context = 0; | ||
| 347 | int err; | ||
| 348 | |||
| 349 | raw_dump_table(__func__, "raw skb data dump uncompressed", | ||
| 350 | skb->data, skb->len); | ||
| 351 | |||
| 352 | /* another if the CID flag is set */ | ||
| 353 | if (iphc1 & LOWPAN_IPHC_CID) { | ||
| 354 | pr_debug("CID flag is set, increase header with one\n"); | ||
| 355 | if (lowpan_fetch_skb_u8(skb, &num_context)) | ||
| 356 | goto drop; | ||
| 357 | } | ||
| 358 | |||
| 359 | hdr.version = 6; | ||
| 360 | |||
| 361 | /* Traffic Class and Flow Label */ | ||
| 362 | switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) { | ||
| 363 | /* | ||
| 364 | * Traffic Class and FLow Label carried in-line | ||
| 365 | * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes) | ||
| 366 | */ | ||
| 367 | case 0: /* 00b */ | ||
| 368 | if (lowpan_fetch_skb_u8(skb, &tmp)) | ||
| 369 | goto drop; | ||
| 370 | |||
| 371 | memcpy(&hdr.flow_lbl, &skb->data[0], 3); | ||
| 372 | skb_pull(skb, 3); | ||
| 373 | hdr.priority = ((tmp >> 2) & 0x0f); | ||
| 374 | hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) | | ||
| 375 | (hdr.flow_lbl[0] & 0x0f); | ||
| 376 | break; | ||
| 377 | /* | ||
| 378 | * Traffic class carried in-line | ||
| 379 | * ECN + DSCP (1 byte), Flow Label is elided | ||
| 380 | */ | ||
| 381 | case 2: /* 10b */ | ||
| 382 | if (lowpan_fetch_skb_u8(skb, &tmp)) | ||
| 383 | goto drop; | ||
| 384 | |||
| 385 | hdr.priority = ((tmp >> 2) & 0x0f); | ||
| 386 | hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30); | ||
| 387 | break; | ||
| 388 | /* | ||
| 389 | * Flow Label carried in-line | ||
| 390 | * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided | ||
| 391 | */ | ||
| 392 | case 1: /* 01b */ | ||
| 393 | if (lowpan_fetch_skb_u8(skb, &tmp)) | ||
| 394 | goto drop; | ||
| 395 | |||
| 396 | hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30); | ||
| 397 | memcpy(&hdr.flow_lbl[1], &skb->data[0], 2); | ||
| 398 | skb_pull(skb, 2); | ||
| 399 | break; | ||
| 400 | /* Traffic Class and Flow Label are elided */ | ||
| 401 | case 3: /* 11b */ | ||
| 402 | break; | ||
| 403 | default: | ||
| 404 | break; | ||
| 405 | } | ||
| 406 | |||
| 407 | /* Next Header */ | ||
| 408 | if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { | ||
| 409 | /* Next header is carried inline */ | ||
| 410 | if (lowpan_fetch_skb_u8(skb, &(hdr.nexthdr))) | ||
| 411 | goto drop; | ||
| 412 | |||
| 413 | pr_debug("NH flag is set, next header carried inline: %02x\n", | ||
| 414 | hdr.nexthdr); | ||
| 415 | } | ||
| 416 | |||
| 417 | /* Hop Limit */ | ||
| 418 | if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I) | ||
| 419 | hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03]; | ||
| 420 | else { | ||
| 421 | if (lowpan_fetch_skb_u8(skb, &(hdr.hop_limit))) | ||
| 422 | goto drop; | ||
| 423 | } | ||
| 424 | |||
| 425 | /* Extract SAM to the tmp variable */ | ||
| 426 | tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03; | ||
| 427 | |||
| 428 | if (iphc1 & LOWPAN_IPHC_SAC) { | ||
| 429 | /* Source address context based uncompression */ | ||
| 430 | pr_debug("SAC bit is set. Handle context based source address.\n"); | ||
| 431 | err = uncompress_context_based_src_addr( | ||
| 432 | skb, &hdr.saddr, tmp); | ||
| 433 | } else { | ||
| 434 | /* Source address uncompression */ | ||
| 435 | pr_debug("source address stateless compression\n"); | ||
| 436 | err = uncompress_addr(skb, &hdr.saddr, tmp, saddr, | ||
| 437 | saddr_type, saddr_len); | ||
| 438 | } | ||
| 439 | |||
| 440 | /* Check on error of previous branch */ | ||
| 441 | if (err) | ||
| 442 | goto drop; | ||
| 443 | |||
| 444 | /* Extract DAM to the tmp variable */ | ||
| 445 | tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03; | ||
| 446 | |||
| 447 | /* check for Multicast Compression */ | ||
| 448 | if (iphc1 & LOWPAN_IPHC_M) { | ||
| 449 | if (iphc1 & LOWPAN_IPHC_DAC) { | ||
| 450 | pr_debug("dest: context-based mcast compression\n"); | ||
| 451 | /* TODO: implement this */ | ||
| 452 | } else { | ||
| 453 | err = lowpan_uncompress_multicast_daddr( | ||
| 454 | skb, &hdr.daddr, tmp); | ||
| 455 | if (err) | ||
| 456 | goto drop; | ||
| 457 | } | ||
| 458 | } else { | ||
| 459 | err = uncompress_addr(skb, &hdr.daddr, tmp, daddr, | ||
| 460 | daddr_type, daddr_len); | ||
| 461 | pr_debug("dest: stateless compression mode %d dest %pI6c\n", | ||
| 462 | tmp, &hdr.daddr); | ||
| 463 | if (err) | ||
| 464 | goto drop; | ||
| 465 | } | ||
| 466 | |||
| 467 | /* UDP data uncompression */ | ||
| 468 | if (iphc0 & LOWPAN_IPHC_NH_C) { | ||
| 469 | struct udphdr uh; | ||
| 470 | struct sk_buff *new; | ||
| 471 | if (uncompress_udp_header(skb, &uh)) | ||
| 472 | goto drop; | ||
| 473 | |||
| 474 | /* | ||
| 475 | * replace the compressed UDP head by the uncompressed UDP | ||
| 476 | * header | ||
| 477 | */ | ||
| 478 | new = skb_copy_expand(skb, sizeof(struct udphdr), | ||
| 479 | skb_tailroom(skb), GFP_ATOMIC); | ||
| 480 | kfree_skb(skb); | ||
| 481 | |||
| 482 | if (!new) | ||
| 483 | return -ENOMEM; | ||
| 484 | |||
| 485 | skb = new; | ||
| 486 | |||
| 487 | skb_push(skb, sizeof(struct udphdr)); | ||
| 488 | skb_reset_transport_header(skb); | ||
| 489 | skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr)); | ||
| 490 | |||
| 491 | raw_dump_table(__func__, "raw UDP header dump", | ||
| 492 | (u8 *)&uh, sizeof(uh)); | ||
| 493 | |||
| 494 | hdr.nexthdr = UIP_PROTO_UDP; | ||
| 495 | } | ||
| 496 | |||
| 497 | hdr.payload_len = htons(skb->len); | ||
| 498 | |||
| 499 | pr_debug("skb headroom size = %d, data length = %d\n", | ||
| 500 | skb_headroom(skb), skb->len); | ||
| 501 | |||
| 502 | pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n\t" | ||
| 503 | "nexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n", | ||
| 504 | hdr.version, ntohs(hdr.payload_len), hdr.nexthdr, | ||
| 505 | hdr.hop_limit, &hdr.daddr); | ||
| 506 | |||
| 507 | raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, | ||
| 508 | sizeof(hdr)); | ||
| 509 | |||
| 510 | return skb_deliver(skb, &hdr, dev, deliver_skb); | ||
| 511 | |||
| 512 | drop: | ||
| 513 | kfree_skb(skb); | ||
| 514 | return -EINVAL; | ||
| 515 | } | ||
| 516 | EXPORT_SYMBOL_GPL(lowpan_process_data); | ||
| 517 | |||
| 518 | static u8 lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift, | ||
| 519 | const struct in6_addr *ipaddr, | ||
| 520 | const unsigned char *lladdr) | ||
| 521 | { | ||
| 522 | u8 val = 0; | ||
| 523 | |||
| 524 | if (is_addr_mac_addr_based(ipaddr, lladdr)) { | ||
| 525 | val = 3; /* 0-bits */ | ||
| 526 | pr_debug("address compression 0 bits\n"); | ||
| 527 | } else if (lowpan_is_iid_16_bit_compressable(ipaddr)) { | ||
| 528 | /* compress IID to 16 bits xxxx::XXXX */ | ||
| 529 | memcpy(*hc06_ptr, &ipaddr->s6_addr16[7], 2); | ||
| 530 | *hc06_ptr += 2; | ||
| 531 | val = 2; /* 16-bits */ | ||
| 532 | raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)", | ||
| 533 | *hc06_ptr - 2, 2); | ||
| 534 | } else { | ||
| 535 | /* do not compress IID => xxxx::IID */ | ||
| 536 | memcpy(*hc06_ptr, &ipaddr->s6_addr16[4], 8); | ||
| 537 | *hc06_ptr += 8; | ||
| 538 | val = 1; /* 64-bits */ | ||
| 539 | raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)", | ||
| 540 | *hc06_ptr - 8, 8); | ||
| 541 | } | ||
| 542 | |||
| 543 | return rol8(val, shift); | ||
| 544 | } | ||
| 545 | |||
| 546 | static void compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb) | ||
| 547 | { | ||
| 548 | struct udphdr *uh = udp_hdr(skb); | ||
| 549 | u8 tmp; | ||
| 550 | |||
| 551 | if (((ntohs(uh->source) & LOWPAN_NHC_UDP_4BIT_MASK) == | ||
| 552 | LOWPAN_NHC_UDP_4BIT_PORT) && | ||
| 553 | ((ntohs(uh->dest) & LOWPAN_NHC_UDP_4BIT_MASK) == | ||
| 554 | LOWPAN_NHC_UDP_4BIT_PORT)) { | ||
| 555 | pr_debug("UDP header: both ports compression to 4 bits\n"); | ||
| 556 | /* compression value */ | ||
| 557 | tmp = LOWPAN_NHC_UDP_CS_P_11; | ||
| 558 | lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); | ||
| 559 | /* source and destination port */ | ||
| 560 | tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_4BIT_PORT + | ||
| 561 | ((ntohs(uh->source) - LOWPAN_NHC_UDP_4BIT_PORT) << 4); | ||
| 562 | lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); | ||
| 563 | } else if ((ntohs(uh->dest) & LOWPAN_NHC_UDP_8BIT_MASK) == | ||
| 564 | LOWPAN_NHC_UDP_8BIT_PORT) { | ||
| 565 | pr_debug("UDP header: remove 8 bits of dest\n"); | ||
| 566 | /* compression value */ | ||
| 567 | tmp = LOWPAN_NHC_UDP_CS_P_01; | ||
| 568 | lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); | ||
| 569 | /* source port */ | ||
| 570 | lowpan_push_hc_data(hc06_ptr, &uh->source, sizeof(uh->source)); | ||
| 571 | /* destination port */ | ||
| 572 | tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_8BIT_PORT; | ||
| 573 | lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); | ||
| 574 | } else if ((ntohs(uh->source) & LOWPAN_NHC_UDP_8BIT_MASK) == | ||
| 575 | LOWPAN_NHC_UDP_8BIT_PORT) { | ||
| 576 | pr_debug("UDP header: remove 8 bits of source\n"); | ||
| 577 | /* compression value */ | ||
| 578 | tmp = LOWPAN_NHC_UDP_CS_P_10; | ||
| 579 | lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); | ||
| 580 | /* source port */ | ||
| 581 | tmp = ntohs(uh->source) - LOWPAN_NHC_UDP_8BIT_PORT; | ||
| 582 | lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); | ||
| 583 | /* destination port */ | ||
| 584 | lowpan_push_hc_data(hc06_ptr, &uh->dest, sizeof(uh->dest)); | ||
| 585 | } else { | ||
| 586 | pr_debug("UDP header: can't compress\n"); | ||
| 587 | /* compression value */ | ||
| 588 | tmp = LOWPAN_NHC_UDP_CS_P_00; | ||
| 589 | lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); | ||
| 590 | /* source port */ | ||
| 591 | lowpan_push_hc_data(hc06_ptr, &uh->source, sizeof(uh->source)); | ||
| 592 | /* destination port */ | ||
| 593 | lowpan_push_hc_data(hc06_ptr, &uh->dest, sizeof(uh->dest)); | ||
| 594 | } | ||
| 595 | |||
| 596 | /* checksum is always inline */ | ||
| 597 | lowpan_push_hc_data(hc06_ptr, &uh->check, sizeof(uh->check)); | ||
| 598 | |||
| 599 | /* skip the UDP header */ | ||
| 600 | skb_pull(skb, sizeof(struct udphdr)); | ||
| 601 | } | ||
| 602 | |||
| 603 | int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, | ||
| 604 | unsigned short type, const void *_daddr, | ||
| 605 | const void *_saddr, unsigned int len) | ||
| 606 | { | ||
| 607 | u8 tmp, iphc0, iphc1, *hc06_ptr; | ||
| 608 | struct ipv6hdr *hdr; | ||
| 609 | u8 head[100] = {}; | ||
| 610 | |||
| 611 | if (type != ETH_P_IPV6) | ||
| 612 | return -EINVAL; | ||
| 613 | |||
| 614 | hdr = ipv6_hdr(skb); | ||
| 615 | hc06_ptr = head + 2; | ||
| 616 | |||
| 617 | pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n" | ||
| 618 | "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n", | ||
| 619 | hdr->version, ntohs(hdr->payload_len), hdr->nexthdr, | ||
| 620 | hdr->hop_limit, &hdr->daddr); | ||
| 621 | |||
| 622 | raw_dump_table(__func__, "raw skb network header dump", | ||
| 623 | skb_network_header(skb), sizeof(struct ipv6hdr)); | ||
| 624 | |||
| 625 | /* | ||
| 626 | * As we copy some bit-length fields, in the IPHC encoding bytes, | ||
| 627 | * we sometimes use |= | ||
| 628 | * If the field is 0, and the current bit value in memory is 1, | ||
| 629 | * this does not work. We therefore reset the IPHC encoding here | ||
| 630 | */ | ||
| 631 | iphc0 = LOWPAN_DISPATCH_IPHC; | ||
| 632 | iphc1 = 0; | ||
| 633 | |||
| 634 | /* TODO: context lookup */ | ||
| 635 | |||
| 636 | raw_dump_inline(__func__, "saddr", | ||
| 637 | (unsigned char *)_saddr, IEEE802154_ADDR_LEN); | ||
| 638 | raw_dump_inline(__func__, "daddr", | ||
| 639 | (unsigned char *)_daddr, IEEE802154_ADDR_LEN); | ||
| 640 | |||
| 641 | raw_dump_table(__func__, | ||
| 642 | "sending raw skb network uncompressed packet", | ||
| 643 | skb->data, skb->len); | ||
| 644 | |||
| 645 | /* | ||
| 646 | * Traffic class, flow label | ||
| 647 | * If flow label is 0, compress it. If traffic class is 0, compress it | ||
| 648 | * We have to process both in the same time as the offset of traffic | ||
| 649 | * class depends on the presence of version and flow label | ||
| 650 | */ | ||
| 651 | |||
| 652 | /* hc06 format of TC is ECN | DSCP , original one is DSCP | ECN */ | ||
| 653 | tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4); | ||
| 654 | tmp = ((tmp & 0x03) << 6) | (tmp >> 2); | ||
| 655 | |||
| 656 | if (((hdr->flow_lbl[0] & 0x0F) == 0) && | ||
| 657 | (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) { | ||
| 658 | /* flow label can be compressed */ | ||
| 659 | iphc0 |= LOWPAN_IPHC_FL_C; | ||
| 660 | if ((hdr->priority == 0) && | ||
| 661 | ((hdr->flow_lbl[0] & 0xF0) == 0)) { | ||
| 662 | /* compress (elide) all */ | ||
| 663 | iphc0 |= LOWPAN_IPHC_TC_C; | ||
| 664 | } else { | ||
| 665 | /* compress only the flow label */ | ||
| 666 | *hc06_ptr = tmp; | ||
| 667 | hc06_ptr += 1; | ||
| 668 | } | ||
| 669 | } else { | ||
| 670 | /* Flow label cannot be compressed */ | ||
| 671 | if ((hdr->priority == 0) && | ||
| 672 | ((hdr->flow_lbl[0] & 0xF0) == 0)) { | ||
| 673 | /* compress only traffic class */ | ||
| 674 | iphc0 |= LOWPAN_IPHC_TC_C; | ||
| 675 | *hc06_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F); | ||
| 676 | memcpy(hc06_ptr + 1, &hdr->flow_lbl[1], 2); | ||
| 677 | hc06_ptr += 3; | ||
| 678 | } else { | ||
| 679 | /* compress nothing */ | ||
| 680 | memcpy(hc06_ptr, &hdr, 4); | ||
| 681 | /* replace the top byte with new ECN | DSCP format */ | ||
| 682 | *hc06_ptr = tmp; | ||
| 683 | hc06_ptr += 4; | ||
| 684 | } | ||
| 685 | } | ||
| 686 | |||
| 687 | /* NOTE: payload length is always compressed */ | ||
| 688 | |||
| 689 | /* Next Header is compress if UDP */ | ||
| 690 | if (hdr->nexthdr == UIP_PROTO_UDP) | ||
| 691 | iphc0 |= LOWPAN_IPHC_NH_C; | ||
| 692 | |||
| 693 | if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { | ||
| 694 | *hc06_ptr = hdr->nexthdr; | ||
| 695 | hc06_ptr += 1; | ||
| 696 | } | ||
| 697 | |||
| 698 | /* | ||
| 699 | * Hop limit | ||
| 700 | * if 1: compress, encoding is 01 | ||
| 701 | * if 64: compress, encoding is 10 | ||
| 702 | * if 255: compress, encoding is 11 | ||
| 703 | * else do not compress | ||
| 704 | */ | ||
| 705 | switch (hdr->hop_limit) { | ||
| 706 | case 1: | ||
| 707 | iphc0 |= LOWPAN_IPHC_TTL_1; | ||
| 708 | break; | ||
| 709 | case 64: | ||
| 710 | iphc0 |= LOWPAN_IPHC_TTL_64; | ||
| 711 | break; | ||
| 712 | case 255: | ||
| 713 | iphc0 |= LOWPAN_IPHC_TTL_255; | ||
| 714 | break; | ||
| 715 | default: | ||
| 716 | *hc06_ptr = hdr->hop_limit; | ||
| 717 | hc06_ptr += 1; | ||
| 718 | break; | ||
| 719 | } | ||
| 720 | |||
| 721 | /* source address compression */ | ||
| 722 | if (is_addr_unspecified(&hdr->saddr)) { | ||
| 723 | pr_debug("source address is unspecified, setting SAC\n"); | ||
| 724 | iphc1 |= LOWPAN_IPHC_SAC; | ||
| 725 | /* TODO: context lookup */ | ||
| 726 | } else if (is_addr_link_local(&hdr->saddr)) { | ||
| 727 | iphc1 |= lowpan_compress_addr_64(&hc06_ptr, | ||
| 728 | LOWPAN_IPHC_SAM_BIT, &hdr->saddr, _saddr); | ||
| 729 | pr_debug("source address unicast link-local %pI6c " | ||
| 730 | "iphc1 0x%02x\n", &hdr->saddr, iphc1); | ||
| 731 | } else { | ||
| 732 | pr_debug("send the full source address\n"); | ||
| 733 | memcpy(hc06_ptr, &hdr->saddr.s6_addr16[0], 16); | ||
| 734 | hc06_ptr += 16; | ||
| 735 | } | ||
| 736 | |||
| 737 | /* destination address compression */ | ||
| 738 | if (is_addr_mcast(&hdr->daddr)) { | ||
| 739 | pr_debug("destination address is multicast: "); | ||
| 740 | iphc1 |= LOWPAN_IPHC_M; | ||
| 741 | if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) { | ||
| 742 | pr_debug("compressed to 1 octet\n"); | ||
| 743 | iphc1 |= LOWPAN_IPHC_DAM_11; | ||
| 744 | /* use last byte */ | ||
| 745 | *hc06_ptr = hdr->daddr.s6_addr[15]; | ||
| 746 | hc06_ptr += 1; | ||
| 747 | } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) { | ||
| 748 | pr_debug("compressed to 4 octets\n"); | ||
| 749 | iphc1 |= LOWPAN_IPHC_DAM_10; | ||
| 750 | /* second byte + the last three */ | ||
| 751 | *hc06_ptr = hdr->daddr.s6_addr[1]; | ||
| 752 | memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[13], 3); | ||
| 753 | hc06_ptr += 4; | ||
| 754 | } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) { | ||
| 755 | pr_debug("compressed to 6 octets\n"); | ||
| 756 | iphc1 |= LOWPAN_IPHC_DAM_01; | ||
| 757 | /* second byte + the last five */ | ||
| 758 | *hc06_ptr = hdr->daddr.s6_addr[1]; | ||
| 759 | memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[11], 5); | ||
| 760 | hc06_ptr += 6; | ||
| 761 | } else { | ||
| 762 | pr_debug("using full address\n"); | ||
| 763 | iphc1 |= LOWPAN_IPHC_DAM_00; | ||
| 764 | memcpy(hc06_ptr, &hdr->daddr.s6_addr[0], 16); | ||
| 765 | hc06_ptr += 16; | ||
| 766 | } | ||
| 767 | } else { | ||
| 768 | /* TODO: context lookup */ | ||
| 769 | if (is_addr_link_local(&hdr->daddr)) { | ||
| 770 | iphc1 |= lowpan_compress_addr_64(&hc06_ptr, | ||
| 771 | LOWPAN_IPHC_DAM_BIT, &hdr->daddr, _daddr); | ||
| 772 | pr_debug("dest address unicast link-local %pI6c " | ||
| 773 | "iphc1 0x%02x\n", &hdr->daddr, iphc1); | ||
| 774 | } else { | ||
| 775 | pr_debug("dest address unicast %pI6c\n", &hdr->daddr); | ||
| 776 | memcpy(hc06_ptr, &hdr->daddr.s6_addr16[0], 16); | ||
| 777 | hc06_ptr += 16; | ||
| 778 | } | ||
| 779 | } | ||
| 780 | |||
| 781 | /* UDP header compression */ | ||
| 782 | if (hdr->nexthdr == UIP_PROTO_UDP) | ||
| 783 | compress_udp_header(&hc06_ptr, skb); | ||
| 784 | |||
| 785 | head[0] = iphc0; | ||
| 786 | head[1] = iphc1; | ||
| 787 | |||
| 788 | skb_pull(skb, sizeof(struct ipv6hdr)); | ||
| 789 | skb_reset_transport_header(skb); | ||
| 790 | memcpy(skb_push(skb, hc06_ptr - head), head, hc06_ptr - head); | ||
| 791 | skb_reset_network_header(skb); | ||
| 792 | |||
| 793 | pr_debug("header len %d skb %u\n", (int)(hc06_ptr - head), skb->len); | ||
| 794 | |||
| 795 | raw_dump_table(__func__, "raw skb data dump compressed", | ||
| 796 | skb->data, skb->len); | ||
| 797 | return 0; | ||
| 798 | } | ||
| 799 | EXPORT_SYMBOL_GPL(lowpan_header_compress); | ||
diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile index d7716d64c6bb..951a83ee8af4 100644 --- a/net/ieee802154/Makefile +++ b/net/ieee802154/Makefile | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | obj-$(CONFIG_IEEE802154) += ieee802154.o af_802154.o | 1 | obj-$(CONFIG_IEEE802154) += ieee802154.o af_802154.o |
| 2 | obj-$(CONFIG_IEEE802154_6LOWPAN) += 6lowpan.o | 2 | obj-$(CONFIG_IEEE802154_6LOWPAN) += 6lowpan.o 6lowpan_iphc.o |
| 3 | 3 | ||
| 4 | ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o | 4 | ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o |
| 5 | af_802154-y := af_ieee802154.o raw.o dgram.o | 5 | af_802154-y := af_ieee802154.o raw.o dgram.o |
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 07a5ed374262..d3929a69f008 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c | |||
| @@ -113,7 +113,7 @@ static inline struct dst_entry *tunnel_dst_get(struct ip_tunnel *t) | |||
| 113 | return dst; | 113 | return dst; |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | struct dst_entry *tunnel_dst_check(struct ip_tunnel *t, u32 cookie) | 116 | static struct dst_entry *tunnel_dst_check(struct ip_tunnel *t, u32 cookie) |
| 117 | { | 117 | { |
| 118 | struct dst_entry *dst = tunnel_dst_get(t); | 118 | struct dst_entry *dst = tunnel_dst_get(t); |
| 119 | 119 | ||
diff --git a/net/ipv4/netfilter/nf_tables_arp.c b/net/ipv4/netfilter/nf_tables_arp.c index 3e67ef1c676f..19412a4063fb 100644 --- a/net/ipv4/netfilter/nf_tables_arp.c +++ b/net/ipv4/netfilter/nf_tables_arp.c | |||
| @@ -14,10 +14,30 @@ | |||
| 14 | #include <linux/netfilter_arp.h> | 14 | #include <linux/netfilter_arp.h> |
| 15 | #include <net/netfilter/nf_tables.h> | 15 | #include <net/netfilter/nf_tables.h> |
| 16 | 16 | ||
| 17 | static unsigned int | ||
| 18 | nft_do_chain_arp(const struct nf_hook_ops *ops, | ||
| 19 | struct sk_buff *skb, | ||
| 20 | const struct net_device *in, | ||
| 21 | const struct net_device *out, | ||
| 22 | int (*okfn)(struct sk_buff *)) | ||
| 23 | { | ||
| 24 | struct nft_pktinfo pkt; | ||
| 25 | |||
| 26 | nft_set_pktinfo(&pkt, ops, skb, in, out); | ||
| 27 | |||
| 28 | return nft_do_chain(&pkt, ops); | ||
| 29 | } | ||
| 30 | |||
| 17 | static struct nft_af_info nft_af_arp __read_mostly = { | 31 | static struct nft_af_info nft_af_arp __read_mostly = { |
| 18 | .family = NFPROTO_ARP, | 32 | .family = NFPROTO_ARP, |
| 19 | .nhooks = NF_ARP_NUMHOOKS, | 33 | .nhooks = NF_ARP_NUMHOOKS, |
| 20 | .owner = THIS_MODULE, | 34 | .owner = THIS_MODULE, |
| 35 | .nops = 1, | ||
| 36 | .hooks = { | ||
| 37 | [NF_ARP_IN] = nft_do_chain_arp, | ||
| 38 | [NF_ARP_OUT] = nft_do_chain_arp, | ||
| 39 | [NF_ARP_FORWARD] = nft_do_chain_arp, | ||
| 40 | }, | ||
| 21 | }; | 41 | }; |
| 22 | 42 | ||
| 23 | static int nf_tables_arp_init_net(struct net *net) | 43 | static int nf_tables_arp_init_net(struct net *net) |
| @@ -48,32 +68,14 @@ static struct pernet_operations nf_tables_arp_net_ops = { | |||
| 48 | .exit = nf_tables_arp_exit_net, | 68 | .exit = nf_tables_arp_exit_net, |
| 49 | }; | 69 | }; |
| 50 | 70 | ||
| 51 | static unsigned int | 71 | static const struct nf_chain_type filter_arp = { |
| 52 | nft_do_chain_arp(const struct nf_hook_ops *ops, | ||
| 53 | struct sk_buff *skb, | ||
| 54 | const struct net_device *in, | ||
| 55 | const struct net_device *out, | ||
| 56 | int (*okfn)(struct sk_buff *)) | ||
| 57 | { | ||
| 58 | struct nft_pktinfo pkt; | ||
| 59 | |||
| 60 | nft_set_pktinfo(&pkt, ops, skb, in, out); | ||
| 61 | |||
| 62 | return nft_do_chain_pktinfo(&pkt, ops); | ||
| 63 | } | ||
| 64 | |||
| 65 | static struct nf_chain_type filter_arp = { | ||
| 66 | .family = NFPROTO_ARP, | ||
| 67 | .name = "filter", | 72 | .name = "filter", |
| 68 | .type = NFT_CHAIN_T_DEFAULT, | 73 | .type = NFT_CHAIN_T_DEFAULT, |
| 74 | .family = NFPROTO_ARP, | ||
| 75 | .owner = THIS_MODULE, | ||
| 69 | .hook_mask = (1 << NF_ARP_IN) | | 76 | .hook_mask = (1 << NF_ARP_IN) | |
| 70 | (1 << NF_ARP_OUT) | | 77 | (1 << NF_ARP_OUT) | |
| 71 | (1 << NF_ARP_FORWARD), | 78 | (1 << NF_ARP_FORWARD), |
| 72 | .fn = { | ||
| 73 | [NF_ARP_IN] = nft_do_chain_arp, | ||
| 74 | [NF_ARP_OUT] = nft_do_chain_arp, | ||
| 75 | [NF_ARP_FORWARD] = nft_do_chain_arp, | ||
| 76 | }, | ||
| 77 | }; | 79 | }; |
| 78 | 80 | ||
| 79 | static int __init nf_tables_arp_init(void) | 81 | static int __init nf_tables_arp_init(void) |
diff --git a/net/ipv4/netfilter/nf_tables_ipv4.c b/net/ipv4/netfilter/nf_tables_ipv4.c index 0f4cbfeb19bd..6820c8c40842 100644 --- a/net/ipv4/netfilter/nf_tables_ipv4.c +++ b/net/ipv4/netfilter/nf_tables_ipv4.c | |||
| @@ -18,14 +18,25 @@ | |||
| 18 | #include <net/ip.h> | 18 | #include <net/ip.h> |
| 19 | #include <net/netfilter/nf_tables_ipv4.h> | 19 | #include <net/netfilter/nf_tables_ipv4.h> |
| 20 | 20 | ||
| 21 | static unsigned int nft_do_chain_ipv4(const struct nf_hook_ops *ops, | ||
| 22 | struct sk_buff *skb, | ||
| 23 | const struct net_device *in, | ||
| 24 | const struct net_device *out, | ||
| 25 | int (*okfn)(struct sk_buff *)) | ||
| 26 | { | ||
| 27 | struct nft_pktinfo pkt; | ||
| 28 | |||
| 29 | nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out); | ||
| 30 | |||
| 31 | return nft_do_chain(&pkt, ops); | ||
| 32 | } | ||
| 33 | |||
| 21 | static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops, | 34 | static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops, |
| 22 | struct sk_buff *skb, | 35 | struct sk_buff *skb, |
| 23 | const struct net_device *in, | 36 | const struct net_device *in, |
| 24 | const struct net_device *out, | 37 | const struct net_device *out, |
| 25 | int (*okfn)(struct sk_buff *)) | 38 | int (*okfn)(struct sk_buff *)) |
| 26 | { | 39 | { |
| 27 | struct nft_pktinfo pkt; | ||
| 28 | |||
| 29 | if (unlikely(skb->len < sizeof(struct iphdr) || | 40 | if (unlikely(skb->len < sizeof(struct iphdr) || |
| 30 | ip_hdr(skb)->ihl < sizeof(struct iphdr) / 4)) { | 41 | ip_hdr(skb)->ihl < sizeof(struct iphdr) / 4)) { |
| 31 | if (net_ratelimit()) | 42 | if (net_ratelimit()) |
| @@ -33,19 +44,24 @@ static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops, | |||
| 33 | "packet\n"); | 44 | "packet\n"); |
| 34 | return NF_ACCEPT; | 45 | return NF_ACCEPT; |
| 35 | } | 46 | } |
| 36 | nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out); | ||
| 37 | 47 | ||
| 38 | return nft_do_chain_pktinfo(&pkt, ops); | 48 | return nft_do_chain_ipv4(ops, skb, in, out, okfn); |
| 39 | } | 49 | } |
| 40 | 50 | ||
| 41 | static struct nft_af_info nft_af_ipv4 __read_mostly = { | 51 | struct nft_af_info nft_af_ipv4 __read_mostly = { |
| 42 | .family = NFPROTO_IPV4, | 52 | .family = NFPROTO_IPV4, |
| 43 | .nhooks = NF_INET_NUMHOOKS, | 53 | .nhooks = NF_INET_NUMHOOKS, |
| 44 | .owner = THIS_MODULE, | 54 | .owner = THIS_MODULE, |
| 55 | .nops = 1, | ||
| 45 | .hooks = { | 56 | .hooks = { |
| 57 | [NF_INET_LOCAL_IN] = nft_do_chain_ipv4, | ||
| 46 | [NF_INET_LOCAL_OUT] = nft_ipv4_output, | 58 | [NF_INET_LOCAL_OUT] = nft_ipv4_output, |
| 59 | [NF_INET_FORWARD] = nft_do_chain_ipv4, | ||
| 60 | [NF_INET_PRE_ROUTING] = nft_do_chain_ipv4, | ||
| 61 | [NF_INET_POST_ROUTING] = nft_do_chain_ipv4, | ||
| 47 | }, | 62 | }, |
| 48 | }; | 63 | }; |
| 64 | EXPORT_SYMBOL_GPL(nft_af_ipv4); | ||
| 49 | 65 | ||
| 50 | static int nf_tables_ipv4_init_net(struct net *net) | 66 | static int nf_tables_ipv4_init_net(struct net *net) |
| 51 | { | 67 | { |
| @@ -75,42 +91,28 @@ static struct pernet_operations nf_tables_ipv4_net_ops = { | |||
| 75 | .exit = nf_tables_ipv4_exit_net, | 91 | .exit = nf_tables_ipv4_exit_net, |
| 76 | }; | 92 | }; |
| 77 | 93 | ||
| 78 | static unsigned int | 94 | static const struct nf_chain_type filter_ipv4 = { |
| 79 | nft_do_chain_ipv4(const struct nf_hook_ops *ops, | ||
| 80 | struct sk_buff *skb, | ||
| 81 | const struct net_device *in, | ||
| 82 | const struct net_device *out, | ||
| 83 | int (*okfn)(struct sk_buff *)) | ||
| 84 | { | ||
| 85 | struct nft_pktinfo pkt; | ||
| 86 | |||
| 87 | nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out); | ||
| 88 | |||
| 89 | return nft_do_chain_pktinfo(&pkt, ops); | ||
| 90 | } | ||
| 91 | |||
| 92 | static struct nf_chain_type filter_ipv4 = { | ||
| 93 | .family = NFPROTO_IPV4, | ||
| 94 | .name = "filter", | 95 | .name = "filter", |
| 95 | .type = NFT_CHAIN_T_DEFAULT, | 96 | .type = NFT_CHAIN_T_DEFAULT, |
| 97 | .family = NFPROTO_IPV4, | ||
| 98 | .owner = THIS_MODULE, | ||
| 96 | .hook_mask = (1 << NF_INET_LOCAL_IN) | | 99 | .hook_mask = (1 << NF_INET_LOCAL_IN) | |
| 97 | (1 << NF_INET_LOCAL_OUT) | | 100 | (1 << NF_INET_LOCAL_OUT) | |
| 98 | (1 << NF_INET_FORWARD) | | 101 | (1 << NF_INET_FORWARD) | |
| 99 | (1 << NF_INET_PRE_ROUTING) | | 102 | (1 << NF_INET_PRE_ROUTING) | |
| 100 | (1 << NF_INET_POST_ROUTING), | 103 | (1 << NF_INET_POST_ROUTING), |
| 101 | .fn = { | ||
| 102 | [NF_INET_LOCAL_IN] = nft_do_chain_ipv4, | ||
| 103 | [NF_INET_LOCAL_OUT] = nft_ipv4_output, | ||
| 104 | [NF_INET_FORWARD] = nft_do_chain_ipv4, | ||
| 105 | [NF_INET_PRE_ROUTING] = nft_do_chain_ipv4, | ||
| 106 | [NF_INET_POST_ROUTING] = nft_do_chain_ipv4, | ||
| 107 | }, | ||
| 108 | }; | 104 | }; |
| 109 | 105 | ||
| 110 | static int __init nf_tables_ipv4_init(void) | 106 | static int __init nf_tables_ipv4_init(void) |
| 111 | { | 107 | { |
| 108 | int ret; | ||
| 109 | |||
| 112 | nft_register_chain_type(&filter_ipv4); | 110 | nft_register_chain_type(&filter_ipv4); |
| 113 | return register_pernet_subsys(&nf_tables_ipv4_net_ops); | 111 | ret = register_pernet_subsys(&nf_tables_ipv4_net_ops); |
| 112 | if (ret < 0) | ||
| 113 | nft_unregister_chain_type(&filter_ipv4); | ||
| 114 | |||
| 115 | return ret; | ||
| 114 | } | 116 | } |
| 115 | 117 | ||
| 116 | static void __exit nf_tables_ipv4_exit(void) | 118 | static void __exit nf_tables_ipv4_exit(void) |
diff --git a/net/ipv4/netfilter/nft_chain_nat_ipv4.c b/net/ipv4/netfilter/nft_chain_nat_ipv4.c index cf2c792cd971..b5b256d45e67 100644 --- a/net/ipv4/netfilter/nft_chain_nat_ipv4.c +++ b/net/ipv4/netfilter/nft_chain_nat_ipv4.c | |||
| @@ -75,7 +75,7 @@ static unsigned int nf_nat_fn(const struct nf_hook_ops *ops, | |||
| 75 | 75 | ||
| 76 | nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out); | 76 | nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out); |
| 77 | 77 | ||
| 78 | ret = nft_do_chain_pktinfo(&pkt, ops); | 78 | ret = nft_do_chain(&pkt, ops); |
| 79 | if (ret != NF_ACCEPT) | 79 | if (ret != NF_ACCEPT) |
| 80 | return ret; | 80 | return ret; |
| 81 | if (!nf_nat_initialized(ct, maniptype)) { | 81 | if (!nf_nat_initialized(ct, maniptype)) { |
| @@ -164,21 +164,21 @@ static unsigned int nf_nat_output(const struct nf_hook_ops *ops, | |||
| 164 | return ret; | 164 | return ret; |
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | static struct nf_chain_type nft_chain_nat_ipv4 = { | 167 | static const struct nf_chain_type nft_chain_nat_ipv4 = { |
| 168 | .family = NFPROTO_IPV4, | ||
| 169 | .name = "nat", | 168 | .name = "nat", |
| 170 | .type = NFT_CHAIN_T_NAT, | 169 | .type = NFT_CHAIN_T_NAT, |
| 170 | .family = NFPROTO_IPV4, | ||
| 171 | .owner = THIS_MODULE, | ||
| 171 | .hook_mask = (1 << NF_INET_PRE_ROUTING) | | 172 | .hook_mask = (1 << NF_INET_PRE_ROUTING) | |
| 172 | (1 << NF_INET_POST_ROUTING) | | 173 | (1 << NF_INET_POST_ROUTING) | |
| 173 | (1 << NF_INET_LOCAL_OUT) | | 174 | (1 << NF_INET_LOCAL_OUT) | |
| 174 | (1 << NF_INET_LOCAL_IN), | 175 | (1 << NF_INET_LOCAL_IN), |
| 175 | .fn = { | 176 | .hooks = { |
| 176 | [NF_INET_PRE_ROUTING] = nf_nat_prerouting, | 177 | [NF_INET_PRE_ROUTING] = nf_nat_prerouting, |
| 177 | [NF_INET_POST_ROUTING] = nf_nat_postrouting, | 178 | [NF_INET_POST_ROUTING] = nf_nat_postrouting, |
| 178 | [NF_INET_LOCAL_OUT] = nf_nat_output, | 179 | [NF_INET_LOCAL_OUT] = nf_nat_output, |
| 179 | [NF_INET_LOCAL_IN] = nf_nat_fn, | 180 | [NF_INET_LOCAL_IN] = nf_nat_fn, |
| 180 | }, | 181 | }, |
| 181 | .me = THIS_MODULE, | ||
| 182 | }; | 182 | }; |
| 183 | 183 | ||
| 184 | static int __init nft_chain_nat_init(void) | 184 | static int __init nft_chain_nat_init(void) |
diff --git a/net/ipv4/netfilter/nft_chain_route_ipv4.c b/net/ipv4/netfilter/nft_chain_route_ipv4.c index 4e6bf9a3d7aa..125b66766c0a 100644 --- a/net/ipv4/netfilter/nft_chain_route_ipv4.c +++ b/net/ipv4/netfilter/nft_chain_route_ipv4.c | |||
| @@ -47,7 +47,7 @@ static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops, | |||
| 47 | daddr = iph->daddr; | 47 | daddr = iph->daddr; |
| 48 | tos = iph->tos; | 48 | tos = iph->tos; |
| 49 | 49 | ||
| 50 | ret = nft_do_chain_pktinfo(&pkt, ops); | 50 | ret = nft_do_chain(&pkt, ops); |
| 51 | if (ret != NF_DROP && ret != NF_QUEUE) { | 51 | if (ret != NF_DROP && ret != NF_QUEUE) { |
| 52 | iph = ip_hdr(skb); | 52 | iph = ip_hdr(skb); |
| 53 | 53 | ||
| @@ -61,15 +61,15 @@ static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops, | |||
| 61 | return ret; | 61 | return ret; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | static struct nf_chain_type nft_chain_route_ipv4 = { | 64 | static const struct nf_chain_type nft_chain_route_ipv4 = { |
| 65 | .family = NFPROTO_IPV4, | ||
| 66 | .name = "route", | 65 | .name = "route", |
| 67 | .type = NFT_CHAIN_T_ROUTE, | 66 | .type = NFT_CHAIN_T_ROUTE, |
| 67 | .family = NFPROTO_IPV4, | ||
| 68 | .owner = THIS_MODULE, | ||
| 68 | .hook_mask = (1 << NF_INET_LOCAL_OUT), | 69 | .hook_mask = (1 << NF_INET_LOCAL_OUT), |
| 69 | .fn = { | 70 | .hooks = { |
| 70 | [NF_INET_LOCAL_OUT] = nf_route_table_hook, | 71 | [NF_INET_LOCAL_OUT] = nf_route_table_hook, |
| 71 | }, | 72 | }, |
| 72 | .me = THIS_MODULE, | ||
| 73 | }; | 73 | }; |
| 74 | 74 | ||
| 75 | static int __init nft_chain_route_init(void) | 75 | static int __init nft_chain_route_init(void) |
diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index 06493736fbc8..699a42faab9c 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c | |||
| @@ -31,7 +31,8 @@ struct tcp_fastopen_metrics { | |||
| 31 | 31 | ||
| 32 | struct tcp_metrics_block { | 32 | struct tcp_metrics_block { |
| 33 | struct tcp_metrics_block __rcu *tcpm_next; | 33 | struct tcp_metrics_block __rcu *tcpm_next; |
| 34 | struct inetpeer_addr tcpm_addr; | 34 | struct inetpeer_addr tcpm_saddr; |
| 35 | struct inetpeer_addr tcpm_daddr; | ||
| 35 | unsigned long tcpm_stamp; | 36 | unsigned long tcpm_stamp; |
| 36 | u32 tcpm_ts; | 37 | u32 tcpm_ts; |
| 37 | u32 tcpm_ts_stamp; | 38 | u32 tcpm_ts_stamp; |
| @@ -131,7 +132,8 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm, struct dst_entry *dst, | |||
| 131 | } | 132 | } |
| 132 | 133 | ||
| 133 | static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst, | 134 | static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst, |
| 134 | struct inetpeer_addr *addr, | 135 | struct inetpeer_addr *saddr, |
| 136 | struct inetpeer_addr *daddr, | ||
| 135 | unsigned int hash, | 137 | unsigned int hash, |
| 136 | bool reclaim) | 138 | bool reclaim) |
| 137 | { | 139 | { |
| @@ -155,7 +157,8 @@ static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst, | |||
| 155 | if (!tm) | 157 | if (!tm) |
| 156 | goto out_unlock; | 158 | goto out_unlock; |
| 157 | } | 159 | } |
| 158 | tm->tcpm_addr = *addr; | 160 | tm->tcpm_saddr = *saddr; |
| 161 | tm->tcpm_daddr = *daddr; | ||
| 159 | 162 | ||
| 160 | tcpm_suck_dst(tm, dst, true); | 163 | tcpm_suck_dst(tm, dst, true); |
| 161 | 164 | ||
| @@ -189,7 +192,8 @@ static struct tcp_metrics_block *tcp_get_encode(struct tcp_metrics_block *tm, in | |||
| 189 | return NULL; | 192 | return NULL; |
| 190 | } | 193 | } |
| 191 | 194 | ||
| 192 | static struct tcp_metrics_block *__tcp_get_metrics(const struct inetpeer_addr *addr, | 195 | static struct tcp_metrics_block *__tcp_get_metrics(const struct inetpeer_addr *saddr, |
| 196 | const struct inetpeer_addr *daddr, | ||
| 193 | struct net *net, unsigned int hash) | 197 | struct net *net, unsigned int hash) |
| 194 | { | 198 | { |
| 195 | struct tcp_metrics_block *tm; | 199 | struct tcp_metrics_block *tm; |
| @@ -197,7 +201,8 @@ static struct tcp_metrics_block *__tcp_get_metrics(const struct inetpeer_addr *a | |||
| 197 | 201 | ||
| 198 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; | 202 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; |
| 199 | tm = rcu_dereference(tm->tcpm_next)) { | 203 | tm = rcu_dereference(tm->tcpm_next)) { |
| 200 | if (addr_same(&tm->tcpm_addr, addr)) | 204 | if (addr_same(&tm->tcpm_saddr, saddr) && |
| 205 | addr_same(&tm->tcpm_daddr, daddr)) | ||
| 201 | break; | 206 | break; |
| 202 | depth++; | 207 | depth++; |
| 203 | } | 208 | } |
| @@ -208,19 +213,22 @@ static struct tcp_metrics_block *__tcp_get_metrics_req(struct request_sock *req, | |||
| 208 | struct dst_entry *dst) | 213 | struct dst_entry *dst) |
| 209 | { | 214 | { |
| 210 | struct tcp_metrics_block *tm; | 215 | struct tcp_metrics_block *tm; |
| 211 | struct inetpeer_addr addr; | 216 | struct inetpeer_addr saddr, daddr; |
| 212 | unsigned int hash; | 217 | unsigned int hash; |
| 213 | struct net *net; | 218 | struct net *net; |
| 214 | 219 | ||
| 215 | addr.family = req->rsk_ops->family; | 220 | saddr.family = req->rsk_ops->family; |
| 216 | switch (addr.family) { | 221 | daddr.family = req->rsk_ops->family; |
| 222 | switch (daddr.family) { | ||
| 217 | case AF_INET: | 223 | case AF_INET: |
| 218 | addr.addr.a4 = inet_rsk(req)->ir_rmt_addr; | 224 | saddr.addr.a4 = inet_rsk(req)->ir_loc_addr; |
| 219 | hash = (__force unsigned int) addr.addr.a4; | 225 | daddr.addr.a4 = inet_rsk(req)->ir_rmt_addr; |
| 226 | hash = (__force unsigned int) daddr.addr.a4; | ||
| 220 | break; | 227 | break; |
| 221 | #if IS_ENABLED(CONFIG_IPV6) | 228 | #if IS_ENABLED(CONFIG_IPV6) |
| 222 | case AF_INET6: | 229 | case AF_INET6: |
| 223 | *(struct in6_addr *)addr.addr.a6 = inet_rsk(req)->ir_v6_rmt_addr; | 230 | *(struct in6_addr *)saddr.addr.a6 = inet_rsk(req)->ir_v6_loc_addr; |
| 231 | *(struct in6_addr *)daddr.addr.a6 = inet_rsk(req)->ir_v6_rmt_addr; | ||
| 224 | hash = ipv6_addr_hash(&inet_rsk(req)->ir_v6_rmt_addr); | 232 | hash = ipv6_addr_hash(&inet_rsk(req)->ir_v6_rmt_addr); |
| 225 | break; | 233 | break; |
| 226 | #endif | 234 | #endif |
| @@ -233,7 +241,8 @@ static struct tcp_metrics_block *__tcp_get_metrics_req(struct request_sock *req, | |||
| 233 | 241 | ||
| 234 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; | 242 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; |
| 235 | tm = rcu_dereference(tm->tcpm_next)) { | 243 | tm = rcu_dereference(tm->tcpm_next)) { |
| 236 | if (addr_same(&tm->tcpm_addr, &addr)) | 244 | if (addr_same(&tm->tcpm_saddr, &saddr) && |
| 245 | addr_same(&tm->tcpm_daddr, &daddr)) | ||
| 237 | break; | 246 | break; |
| 238 | } | 247 | } |
| 239 | tcpm_check_stamp(tm, dst); | 248 | tcpm_check_stamp(tm, dst); |
| @@ -243,19 +252,22 @@ static struct tcp_metrics_block *__tcp_get_metrics_req(struct request_sock *req, | |||
| 243 | static struct tcp_metrics_block *__tcp_get_metrics_tw(struct inet_timewait_sock *tw) | 252 | static struct tcp_metrics_block *__tcp_get_metrics_tw(struct inet_timewait_sock *tw) |
| 244 | { | 253 | { |
| 245 | struct tcp_metrics_block *tm; | 254 | struct tcp_metrics_block *tm; |
| 246 | struct inetpeer_addr addr; | 255 | struct inetpeer_addr saddr, daddr; |
| 247 | unsigned int hash; | 256 | unsigned int hash; |
| 248 | struct net *net; | 257 | struct net *net; |
| 249 | 258 | ||
| 250 | addr.family = tw->tw_family; | 259 | saddr.family = tw->tw_family; |
| 251 | switch (addr.family) { | 260 | daddr.family = tw->tw_family; |
| 261 | switch (daddr.family) { | ||
| 252 | case AF_INET: | 262 | case AF_INET: |
| 253 | addr.addr.a4 = tw->tw_daddr; | 263 | saddr.addr.a4 = tw->tw_rcv_saddr; |
| 254 | hash = (__force unsigned int) addr.addr.a4; | 264 | daddr.addr.a4 = tw->tw_daddr; |
| 265 | hash = (__force unsigned int) daddr.addr.a4; | ||
| 255 | break; | 266 | break; |
| 256 | #if IS_ENABLED(CONFIG_IPV6) | 267 | #if IS_ENABLED(CONFIG_IPV6) |
| 257 | case AF_INET6: | 268 | case AF_INET6: |
| 258 | *(struct in6_addr *)addr.addr.a6 = tw->tw_v6_daddr; | 269 | *(struct in6_addr *)saddr.addr.a6 = tw->tw_v6_rcv_saddr; |
| 270 | *(struct in6_addr *)daddr.addr.a6 = tw->tw_v6_daddr; | ||
| 259 | hash = ipv6_addr_hash(&tw->tw_v6_daddr); | 271 | hash = ipv6_addr_hash(&tw->tw_v6_daddr); |
| 260 | break; | 272 | break; |
| 261 | #endif | 273 | #endif |
| @@ -268,7 +280,8 @@ static struct tcp_metrics_block *__tcp_get_metrics_tw(struct inet_timewait_sock | |||
| 268 | 280 | ||
| 269 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; | 281 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; |
| 270 | tm = rcu_dereference(tm->tcpm_next)) { | 282 | tm = rcu_dereference(tm->tcpm_next)) { |
| 271 | if (addr_same(&tm->tcpm_addr, &addr)) | 283 | if (addr_same(&tm->tcpm_saddr, &saddr) && |
| 284 | addr_same(&tm->tcpm_daddr, &daddr)) | ||
| 272 | break; | 285 | break; |
| 273 | } | 286 | } |
| 274 | return tm; | 287 | return tm; |
| @@ -279,20 +292,23 @@ static struct tcp_metrics_block *tcp_get_metrics(struct sock *sk, | |||
| 279 | bool create) | 292 | bool create) |
| 280 | { | 293 | { |
| 281 | struct tcp_metrics_block *tm; | 294 | struct tcp_metrics_block *tm; |
| 282 | struct inetpeer_addr addr; | 295 | struct inetpeer_addr saddr, daddr; |
| 283 | unsigned int hash; | 296 | unsigned int hash; |
| 284 | struct net *net; | 297 | struct net *net; |
| 285 | bool reclaim; | 298 | bool reclaim; |
| 286 | 299 | ||
| 287 | addr.family = sk->sk_family; | 300 | saddr.family = sk->sk_family; |
| 288 | switch (addr.family) { | 301 | daddr.family = sk->sk_family; |
| 302 | switch (daddr.family) { | ||
| 289 | case AF_INET: | 303 | case AF_INET: |
| 290 | addr.addr.a4 = inet_sk(sk)->inet_daddr; | 304 | saddr.addr.a4 = inet_sk(sk)->inet_saddr; |
| 291 | hash = (__force unsigned int) addr.addr.a4; | 305 | daddr.addr.a4 = inet_sk(sk)->inet_daddr; |
| 306 | hash = (__force unsigned int) daddr.addr.a4; | ||
| 292 | break; | 307 | break; |
| 293 | #if IS_ENABLED(CONFIG_IPV6) | 308 | #if IS_ENABLED(CONFIG_IPV6) |
| 294 | case AF_INET6: | 309 | case AF_INET6: |
| 295 | *(struct in6_addr *)addr.addr.a6 = sk->sk_v6_daddr; | 310 | *(struct in6_addr *)saddr.addr.a6 = sk->sk_v6_rcv_saddr; |
| 311 | *(struct in6_addr *)daddr.addr.a6 = sk->sk_v6_daddr; | ||
| 296 | hash = ipv6_addr_hash(&sk->sk_v6_daddr); | 312 | hash = ipv6_addr_hash(&sk->sk_v6_daddr); |
| 297 | break; | 313 | break; |
| 298 | #endif | 314 | #endif |
| @@ -303,14 +319,14 @@ static struct tcp_metrics_block *tcp_get_metrics(struct sock *sk, | |||
| 303 | net = dev_net(dst->dev); | 319 | net = dev_net(dst->dev); |
| 304 | hash = hash_32(hash, net->ipv4.tcp_metrics_hash_log); | 320 | hash = hash_32(hash, net->ipv4.tcp_metrics_hash_log); |
| 305 | 321 | ||
| 306 | tm = __tcp_get_metrics(&addr, net, hash); | 322 | tm = __tcp_get_metrics(&saddr, &daddr, net, hash); |
| 307 | reclaim = false; | 323 | reclaim = false; |
| 308 | if (tm == TCP_METRICS_RECLAIM_PTR) { | 324 | if (tm == TCP_METRICS_RECLAIM_PTR) { |
| 309 | reclaim = true; | 325 | reclaim = true; |
| 310 | tm = NULL; | 326 | tm = NULL; |
| 311 | } | 327 | } |
| 312 | if (!tm && create) | 328 | if (!tm && create) |
| 313 | tm = tcpm_new(dst, &addr, hash, reclaim); | 329 | tm = tcpm_new(dst, &saddr, &daddr, hash, reclaim); |
| 314 | else | 330 | else |
| 315 | tcpm_check_stamp(tm, dst); | 331 | tcpm_check_stamp(tm, dst); |
| 316 | 332 | ||
| @@ -724,15 +740,21 @@ static int tcp_metrics_fill_info(struct sk_buff *msg, | |||
| 724 | struct nlattr *nest; | 740 | struct nlattr *nest; |
| 725 | int i; | 741 | int i; |
| 726 | 742 | ||
| 727 | switch (tm->tcpm_addr.family) { | 743 | switch (tm->tcpm_daddr.family) { |
| 728 | case AF_INET: | 744 | case AF_INET: |
| 729 | if (nla_put_be32(msg, TCP_METRICS_ATTR_ADDR_IPV4, | 745 | if (nla_put_be32(msg, TCP_METRICS_ATTR_ADDR_IPV4, |
| 730 | tm->tcpm_addr.addr.a4) < 0) | 746 | tm->tcpm_daddr.addr.a4) < 0) |
| 747 | goto nla_put_failure; | ||
| 748 | if (nla_put_be32(msg, TCP_METRICS_ATTR_SADDR_IPV4, | ||
| 749 | tm->tcpm_saddr.addr.a4) < 0) | ||
| 731 | goto nla_put_failure; | 750 | goto nla_put_failure; |
| 732 | break; | 751 | break; |
| 733 | case AF_INET6: | 752 | case AF_INET6: |
| 734 | if (nla_put(msg, TCP_METRICS_ATTR_ADDR_IPV6, 16, | 753 | if (nla_put(msg, TCP_METRICS_ATTR_ADDR_IPV6, 16, |
| 735 | tm->tcpm_addr.addr.a6) < 0) | 754 | tm->tcpm_daddr.addr.a6) < 0) |
| 755 | goto nla_put_failure; | ||
| 756 | if (nla_put(msg, TCP_METRICS_ATTR_SADDR_IPV6, 16, | ||
| 757 | tm->tcpm_saddr.addr.a6) < 0) | ||
| 736 | goto nla_put_failure; | 758 | goto nla_put_failure; |
| 737 | break; | 759 | break; |
| 738 | default: | 760 | default: |
| @@ -855,44 +877,66 @@ done: | |||
| 855 | return skb->len; | 877 | return skb->len; |
| 856 | } | 878 | } |
| 857 | 879 | ||
| 858 | static int parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr, | 880 | static int __parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr, |
| 859 | unsigned int *hash, int optional) | 881 | unsigned int *hash, int optional, int v4, int v6) |
| 860 | { | 882 | { |
| 861 | struct nlattr *a; | 883 | struct nlattr *a; |
| 862 | 884 | ||
| 863 | a = info->attrs[TCP_METRICS_ATTR_ADDR_IPV4]; | 885 | a = info->attrs[v4]; |
| 864 | if (a) { | 886 | if (a) { |
| 865 | addr->family = AF_INET; | 887 | addr->family = AF_INET; |
| 866 | addr->addr.a4 = nla_get_be32(a); | 888 | addr->addr.a4 = nla_get_be32(a); |
| 867 | *hash = (__force unsigned int) addr->addr.a4; | 889 | if (hash) |
| 890 | *hash = (__force unsigned int) addr->addr.a4; | ||
| 868 | return 0; | 891 | return 0; |
| 869 | } | 892 | } |
| 870 | a = info->attrs[TCP_METRICS_ATTR_ADDR_IPV6]; | 893 | a = info->attrs[v6]; |
| 871 | if (a) { | 894 | if (a) { |
| 872 | if (nla_len(a) != sizeof(struct in6_addr)) | 895 | if (nla_len(a) != sizeof(struct in6_addr)) |
| 873 | return -EINVAL; | 896 | return -EINVAL; |
| 874 | addr->family = AF_INET6; | 897 | addr->family = AF_INET6; |
| 875 | memcpy(addr->addr.a6, nla_data(a), sizeof(addr->addr.a6)); | 898 | memcpy(addr->addr.a6, nla_data(a), sizeof(addr->addr.a6)); |
| 876 | *hash = ipv6_addr_hash((struct in6_addr *) addr->addr.a6); | 899 | if (hash) |
| 900 | *hash = ipv6_addr_hash((struct in6_addr *) addr->addr.a6); | ||
| 877 | return 0; | 901 | return 0; |
| 878 | } | 902 | } |
| 879 | return optional ? 1 : -EAFNOSUPPORT; | 903 | return optional ? 1 : -EAFNOSUPPORT; |
| 880 | } | 904 | } |
| 881 | 905 | ||
| 906 | static int parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr, | ||
| 907 | unsigned int *hash, int optional) | ||
| 908 | { | ||
| 909 | return __parse_nl_addr(info, addr, hash, optional, | ||
| 910 | TCP_METRICS_ATTR_ADDR_IPV4, | ||
| 911 | TCP_METRICS_ATTR_ADDR_IPV6); | ||
| 912 | } | ||
| 913 | |||
| 914 | static int parse_nl_saddr(struct genl_info *info, struct inetpeer_addr *addr) | ||
| 915 | { | ||
| 916 | return __parse_nl_addr(info, addr, NULL, 0, | ||
| 917 | TCP_METRICS_ATTR_SADDR_IPV4, | ||
| 918 | TCP_METRICS_ATTR_SADDR_IPV6); | ||
| 919 | } | ||
| 920 | |||
| 882 | static int tcp_metrics_nl_cmd_get(struct sk_buff *skb, struct genl_info *info) | 921 | static int tcp_metrics_nl_cmd_get(struct sk_buff *skb, struct genl_info *info) |
| 883 | { | 922 | { |
| 884 | struct tcp_metrics_block *tm; | 923 | struct tcp_metrics_block *tm; |
| 885 | struct inetpeer_addr addr; | 924 | struct inetpeer_addr saddr, daddr; |
| 886 | unsigned int hash; | 925 | unsigned int hash; |
| 887 | struct sk_buff *msg; | 926 | struct sk_buff *msg; |
| 888 | struct net *net = genl_info_net(info); | 927 | struct net *net = genl_info_net(info); |
| 889 | void *reply; | 928 | void *reply; |
| 890 | int ret; | 929 | int ret; |
| 930 | bool src = true; | ||
| 891 | 931 | ||
| 892 | ret = parse_nl_addr(info, &addr, &hash, 0); | 932 | ret = parse_nl_addr(info, &daddr, &hash, 0); |
| 893 | if (ret < 0) | 933 | if (ret < 0) |
| 894 | return ret; | 934 | return ret; |
| 895 | 935 | ||
| 936 | ret = parse_nl_saddr(info, &saddr); | ||
| 937 | if (ret < 0) | ||
| 938 | src = false; | ||
| 939 | |||
| 896 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 940 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
| 897 | if (!msg) | 941 | if (!msg) |
| 898 | return -ENOMEM; | 942 | return -ENOMEM; |
| @@ -907,7 +951,8 @@ static int tcp_metrics_nl_cmd_get(struct sk_buff *skb, struct genl_info *info) | |||
| 907 | rcu_read_lock(); | 951 | rcu_read_lock(); |
| 908 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; | 952 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; |
| 909 | tm = rcu_dereference(tm->tcpm_next)) { | 953 | tm = rcu_dereference(tm->tcpm_next)) { |
| 910 | if (addr_same(&tm->tcpm_addr, &addr)) { | 954 | if (addr_same(&tm->tcpm_daddr, &daddr) && |
| 955 | (!src || addr_same(&tm->tcpm_saddr, &saddr))) { | ||
| 911 | ret = tcp_metrics_fill_info(msg, tm); | 956 | ret = tcp_metrics_fill_info(msg, tm); |
| 912 | break; | 957 | break; |
| 913 | } | 958 | } |
| @@ -960,34 +1005,44 @@ static int tcp_metrics_flush_all(struct net *net) | |||
| 960 | static int tcp_metrics_nl_cmd_del(struct sk_buff *skb, struct genl_info *info) | 1005 | static int tcp_metrics_nl_cmd_del(struct sk_buff *skb, struct genl_info *info) |
| 961 | { | 1006 | { |
| 962 | struct tcpm_hash_bucket *hb; | 1007 | struct tcpm_hash_bucket *hb; |
| 963 | struct tcp_metrics_block *tm; | 1008 | struct tcp_metrics_block *tm, *tmlist = NULL; |
| 964 | struct tcp_metrics_block __rcu **pp; | 1009 | struct tcp_metrics_block __rcu **pp; |
| 965 | struct inetpeer_addr addr; | 1010 | struct inetpeer_addr saddr, daddr; |
| 966 | unsigned int hash; | 1011 | unsigned int hash; |
| 967 | struct net *net = genl_info_net(info); | 1012 | struct net *net = genl_info_net(info); |
| 968 | int ret; | 1013 | int ret; |
| 1014 | bool src = true; | ||
| 969 | 1015 | ||
| 970 | ret = parse_nl_addr(info, &addr, &hash, 1); | 1016 | ret = parse_nl_addr(info, &daddr, &hash, 1); |
| 971 | if (ret < 0) | 1017 | if (ret < 0) |
| 972 | return ret; | 1018 | return ret; |
| 973 | if (ret > 0) | 1019 | if (ret > 0) |
| 974 | return tcp_metrics_flush_all(net); | 1020 | return tcp_metrics_flush_all(net); |
| 1021 | ret = parse_nl_saddr(info, &saddr); | ||
| 1022 | if (ret < 0) | ||
| 1023 | src = false; | ||
| 975 | 1024 | ||
| 976 | hash = hash_32(hash, net->ipv4.tcp_metrics_hash_log); | 1025 | hash = hash_32(hash, net->ipv4.tcp_metrics_hash_log); |
| 977 | hb = net->ipv4.tcp_metrics_hash + hash; | 1026 | hb = net->ipv4.tcp_metrics_hash + hash; |
| 978 | pp = &hb->chain; | 1027 | pp = &hb->chain; |
| 979 | spin_lock_bh(&tcp_metrics_lock); | 1028 | spin_lock_bh(&tcp_metrics_lock); |
| 980 | for (tm = deref_locked_genl(*pp); tm; | 1029 | for (tm = deref_locked_genl(*pp); tm; tm = deref_locked_genl(*pp)) { |
| 981 | pp = &tm->tcpm_next, tm = deref_locked_genl(*pp)) { | 1030 | if (addr_same(&tm->tcpm_daddr, &daddr) && |
| 982 | if (addr_same(&tm->tcpm_addr, &addr)) { | 1031 | (!src || addr_same(&tm->tcpm_saddr, &saddr))) { |
| 983 | *pp = tm->tcpm_next; | 1032 | *pp = tm->tcpm_next; |
| 984 | break; | 1033 | tm->tcpm_next = tmlist; |
| 1034 | tmlist = tm; | ||
| 1035 | } else { | ||
| 1036 | pp = &tm->tcpm_next; | ||
| 985 | } | 1037 | } |
| 986 | } | 1038 | } |
| 987 | spin_unlock_bh(&tcp_metrics_lock); | 1039 | spin_unlock_bh(&tcp_metrics_lock); |
| 988 | if (!tm) | 1040 | if (!tmlist) |
| 989 | return -ESRCH; | 1041 | return -ESRCH; |
| 990 | kfree_rcu(tm, rcu_head); | 1042 | for (tm = tmlist; tm; tm = tmlist) { |
| 1043 | tmlist = tm->tcpm_next; | ||
| 1044 | kfree_rcu(tm, rcu_head); | ||
| 1045 | } | ||
| 991 | return 0; | 1046 | return 0; |
| 992 | } | 1047 | } |
| 993 | 1048 | ||
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 31f75ea9cb60..a9fa6c1feed5 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -1822,6 +1822,7 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) | |||
| 1822 | return addrconf_ifid_sit(eui, dev); | 1822 | return addrconf_ifid_sit(eui, dev); |
| 1823 | case ARPHRD_IPGRE: | 1823 | case ARPHRD_IPGRE: |
| 1824 | return addrconf_ifid_gre(eui, dev); | 1824 | return addrconf_ifid_gre(eui, dev); |
| 1825 | case ARPHRD_6LOWPAN: | ||
| 1825 | case ARPHRD_IEEE802154: | 1826 | case ARPHRD_IEEE802154: |
| 1826 | return addrconf_ifid_eui64(eui, dev); | 1827 | return addrconf_ifid_eui64(eui, dev); |
| 1827 | case ARPHRD_IEEE1394: | 1828 | case ARPHRD_IEEE1394: |
| @@ -2677,7 +2678,8 @@ static void addrconf_dev_config(struct net_device *dev) | |||
| 2677 | (dev->type != ARPHRD_INFINIBAND) && | 2678 | (dev->type != ARPHRD_INFINIBAND) && |
| 2678 | (dev->type != ARPHRD_IEEE802154) && | 2679 | (dev->type != ARPHRD_IEEE802154) && |
| 2679 | (dev->type != ARPHRD_IEEE1394) && | 2680 | (dev->type != ARPHRD_IEEE1394) && |
| 2680 | (dev->type != ARPHRD_TUNNEL6)) { | 2681 | (dev->type != ARPHRD_TUNNEL6) && |
| 2682 | (dev->type != ARPHRD_6LOWPAN)) { | ||
| 2681 | /* Alas, we support only Ethernet autoconfiguration. */ | 2683 | /* Alas, we support only Ethernet autoconfiguration. */ |
| 2682 | return; | 2684 | return; |
| 2683 | } | 2685 | } |
diff --git a/net/ipv6/netfilter/nf_tables_ipv6.c b/net/ipv6/netfilter/nf_tables_ipv6.c index d77db8a13505..0d812b31277d 100644 --- a/net/ipv6/netfilter/nf_tables_ipv6.c +++ b/net/ipv6/netfilter/nf_tables_ipv6.c | |||
| @@ -16,34 +16,51 @@ | |||
| 16 | #include <net/netfilter/nf_tables.h> | 16 | #include <net/netfilter/nf_tables.h> |
| 17 | #include <net/netfilter/nf_tables_ipv6.h> | 17 | #include <net/netfilter/nf_tables_ipv6.h> |
| 18 | 18 | ||
| 19 | static unsigned int nft_do_chain_ipv6(const struct nf_hook_ops *ops, | ||
| 20 | struct sk_buff *skb, | ||
| 21 | const struct net_device *in, | ||
| 22 | const struct net_device *out, | ||
| 23 | int (*okfn)(struct sk_buff *)) | ||
| 24 | { | ||
| 25 | struct nft_pktinfo pkt; | ||
| 26 | |||
| 27 | /* malformed packet, drop it */ | ||
| 28 | if (nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out) < 0) | ||
| 29 | return NF_DROP; | ||
| 30 | |||
| 31 | return nft_do_chain(&pkt, ops); | ||
| 32 | } | ||
| 33 | |||
| 19 | static unsigned int nft_ipv6_output(const struct nf_hook_ops *ops, | 34 | static unsigned int nft_ipv6_output(const struct nf_hook_ops *ops, |
| 20 | struct sk_buff *skb, | 35 | struct sk_buff *skb, |
| 21 | const struct net_device *in, | 36 | const struct net_device *in, |
| 22 | const struct net_device *out, | 37 | const struct net_device *out, |
| 23 | int (*okfn)(struct sk_buff *)) | 38 | int (*okfn)(struct sk_buff *)) |
| 24 | { | 39 | { |
| 25 | struct nft_pktinfo pkt; | ||
| 26 | |||
| 27 | if (unlikely(skb->len < sizeof(struct ipv6hdr))) { | 40 | if (unlikely(skb->len < sizeof(struct ipv6hdr))) { |
| 28 | if (net_ratelimit()) | 41 | if (net_ratelimit()) |
| 29 | pr_info("nf_tables_ipv6: ignoring short SOCK_RAW " | 42 | pr_info("nf_tables_ipv6: ignoring short SOCK_RAW " |
| 30 | "packet\n"); | 43 | "packet\n"); |
| 31 | return NF_ACCEPT; | 44 | return NF_ACCEPT; |
| 32 | } | 45 | } |
| 33 | if (nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out) < 0) | ||
| 34 | return NF_DROP; | ||
| 35 | 46 | ||
| 36 | return nft_do_chain_pktinfo(&pkt, ops); | 47 | return nft_do_chain_ipv6(ops, skb, in, out, okfn); |
| 37 | } | 48 | } |
| 38 | 49 | ||
| 39 | static struct nft_af_info nft_af_ipv6 __read_mostly = { | 50 | struct nft_af_info nft_af_ipv6 __read_mostly = { |
| 40 | .family = NFPROTO_IPV6, | 51 | .family = NFPROTO_IPV6, |
| 41 | .nhooks = NF_INET_NUMHOOKS, | 52 | .nhooks = NF_INET_NUMHOOKS, |
| 42 | .owner = THIS_MODULE, | 53 | .owner = THIS_MODULE, |
| 54 | .nops = 1, | ||
| 43 | .hooks = { | 55 | .hooks = { |
| 56 | [NF_INET_LOCAL_IN] = nft_do_chain_ipv6, | ||
| 44 | [NF_INET_LOCAL_OUT] = nft_ipv6_output, | 57 | [NF_INET_LOCAL_OUT] = nft_ipv6_output, |
| 58 | [NF_INET_FORWARD] = nft_do_chain_ipv6, | ||
| 59 | [NF_INET_PRE_ROUTING] = nft_do_chain_ipv6, | ||
| 60 | [NF_INET_POST_ROUTING] = nft_do_chain_ipv6, | ||
| 45 | }, | 61 | }, |
| 46 | }; | 62 | }; |
| 63 | EXPORT_SYMBOL_GPL(nft_af_ipv6); | ||
| 47 | 64 | ||
| 48 | static int nf_tables_ipv6_init_net(struct net *net) | 65 | static int nf_tables_ipv6_init_net(struct net *net) |
| 49 | { | 66 | { |
| @@ -73,44 +90,28 @@ static struct pernet_operations nf_tables_ipv6_net_ops = { | |||
| 73 | .exit = nf_tables_ipv6_exit_net, | 90 | .exit = nf_tables_ipv6_exit_net, |
| 74 | }; | 91 | }; |
| 75 | 92 | ||
| 76 | static unsigned int | 93 | static const struct nf_chain_type filter_ipv6 = { |
| 77 | nft_do_chain_ipv6(const struct nf_hook_ops *ops, | ||
| 78 | struct sk_buff *skb, | ||
| 79 | const struct net_device *in, | ||
| 80 | const struct net_device *out, | ||
| 81 | int (*okfn)(struct sk_buff *)) | ||
| 82 | { | ||
| 83 | struct nft_pktinfo pkt; | ||
| 84 | |||
| 85 | /* malformed packet, drop it */ | ||
| 86 | if (nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out) < 0) | ||
| 87 | return NF_DROP; | ||
| 88 | |||
| 89 | return nft_do_chain_pktinfo(&pkt, ops); | ||
| 90 | } | ||
| 91 | |||
| 92 | static struct nf_chain_type filter_ipv6 = { | ||
| 93 | .family = NFPROTO_IPV6, | ||
| 94 | .name = "filter", | 94 | .name = "filter", |
| 95 | .type = NFT_CHAIN_T_DEFAULT, | 95 | .type = NFT_CHAIN_T_DEFAULT, |
| 96 | .family = NFPROTO_IPV6, | ||
| 97 | .owner = THIS_MODULE, | ||
| 96 | .hook_mask = (1 << NF_INET_LOCAL_IN) | | 98 | .hook_mask = (1 << NF_INET_LOCAL_IN) | |
| 97 | (1 << NF_INET_LOCAL_OUT) | | 99 | (1 << NF_INET_LOCAL_OUT) | |
| 98 | (1 << NF_INET_FORWARD) | | 100 | (1 << NF_INET_FORWARD) | |
| 99 | (1 << NF_INET_PRE_ROUTING) | | 101 | (1 << NF_INET_PRE_ROUTING) | |
| 100 | (1 << NF_INET_POST_ROUTING), | 102 | (1 << NF_INET_POST_ROUTING), |
| 101 | .fn = { | ||
| 102 | [NF_INET_LOCAL_IN] = nft_do_chain_ipv6, | ||
| 103 | [NF_INET_LOCAL_OUT] = nft_ipv6_output, | ||
| 104 | [NF_INET_FORWARD] = nft_do_chain_ipv6, | ||
| 105 | [NF_INET_PRE_ROUTING] = nft_do_chain_ipv6, | ||
| 106 | [NF_INET_POST_ROUTING] = nft_do_chain_ipv6, | ||
| 107 | }, | ||
| 108 | }; | 103 | }; |
| 109 | 104 | ||
| 110 | static int __init nf_tables_ipv6_init(void) | 105 | static int __init nf_tables_ipv6_init(void) |
| 111 | { | 106 | { |
| 107 | int ret; | ||
| 108 | |||
| 112 | nft_register_chain_type(&filter_ipv6); | 109 | nft_register_chain_type(&filter_ipv6); |
| 113 | return register_pernet_subsys(&nf_tables_ipv6_net_ops); | 110 | ret = register_pernet_subsys(&nf_tables_ipv6_net_ops); |
| 111 | if (ret < 0) | ||
| 112 | nft_unregister_chain_type(&filter_ipv6); | ||
| 113 | |||
| 114 | return ret; | ||
| 114 | } | 115 | } |
| 115 | 116 | ||
| 116 | static void __exit nf_tables_ipv6_exit(void) | 117 | static void __exit nf_tables_ipv6_exit(void) |
diff --git a/net/ipv6/netfilter/nft_chain_nat_ipv6.c b/net/ipv6/netfilter/nft_chain_nat_ipv6.c index e86dcd70dc76..9c3297a768fd 100644 --- a/net/ipv6/netfilter/nft_chain_nat_ipv6.c +++ b/net/ipv6/netfilter/nft_chain_nat_ipv6.c | |||
| @@ -79,7 +79,7 @@ static unsigned int nf_nat_ipv6_fn(const struct nf_hook_ops *ops, | |||
| 79 | 79 | ||
| 80 | nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out); | 80 | nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out); |
| 81 | 81 | ||
| 82 | ret = nft_do_chain_pktinfo(&pkt, ops); | 82 | ret = nft_do_chain(&pkt, ops); |
| 83 | if (ret != NF_ACCEPT) | 83 | if (ret != NF_ACCEPT) |
| 84 | return ret; | 84 | return ret; |
| 85 | if (!nf_nat_initialized(ct, maniptype)) { | 85 | if (!nf_nat_initialized(ct, maniptype)) { |
| @@ -170,21 +170,21 @@ static unsigned int nf_nat_ipv6_output(const struct nf_hook_ops *ops, | |||
| 170 | return ret; | 170 | return ret; |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | static struct nf_chain_type nft_chain_nat_ipv6 = { | 173 | static const struct nf_chain_type nft_chain_nat_ipv6 = { |
| 174 | .family = NFPROTO_IPV6, | ||
| 175 | .name = "nat", | 174 | .name = "nat", |
| 176 | .type = NFT_CHAIN_T_NAT, | 175 | .type = NFT_CHAIN_T_NAT, |
| 176 | .family = NFPROTO_IPV6, | ||
| 177 | .owner = THIS_MODULE, | ||
| 177 | .hook_mask = (1 << NF_INET_PRE_ROUTING) | | 178 | .hook_mask = (1 << NF_INET_PRE_ROUTING) | |
| 178 | (1 << NF_INET_POST_ROUTING) | | 179 | (1 << NF_INET_POST_ROUTING) | |
| 179 | (1 << NF_INET_LOCAL_OUT) | | 180 | (1 << NF_INET_LOCAL_OUT) | |
| 180 | (1 << NF_INET_LOCAL_IN), | 181 | (1 << NF_INET_LOCAL_IN), |
| 181 | .fn = { | 182 | .hooks = { |
| 182 | [NF_INET_PRE_ROUTING] = nf_nat_ipv6_prerouting, | 183 | [NF_INET_PRE_ROUTING] = nf_nat_ipv6_prerouting, |
| 183 | [NF_INET_POST_ROUTING] = nf_nat_ipv6_postrouting, | 184 | [NF_INET_POST_ROUTING] = nf_nat_ipv6_postrouting, |
| 184 | [NF_INET_LOCAL_OUT] = nf_nat_ipv6_output, | 185 | [NF_INET_LOCAL_OUT] = nf_nat_ipv6_output, |
| 185 | [NF_INET_LOCAL_IN] = nf_nat_ipv6_fn, | 186 | [NF_INET_LOCAL_IN] = nf_nat_ipv6_fn, |
| 186 | }, | 187 | }, |
| 187 | .me = THIS_MODULE, | ||
| 188 | }; | 188 | }; |
| 189 | 189 | ||
| 190 | static int __init nft_chain_nat_ipv6_init(void) | 190 | static int __init nft_chain_nat_ipv6_init(void) |
diff --git a/net/ipv6/netfilter/nft_chain_route_ipv6.c b/net/ipv6/netfilter/nft_chain_route_ipv6.c index 3fe40f0456ad..42031299585e 100644 --- a/net/ipv6/netfilter/nft_chain_route_ipv6.c +++ b/net/ipv6/netfilter/nft_chain_route_ipv6.c | |||
| @@ -47,7 +47,7 @@ static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops, | |||
| 47 | /* flowlabel and prio (includes version, which shouldn't change either */ | 47 | /* flowlabel and prio (includes version, which shouldn't change either */ |
| 48 | flowlabel = *((u32 *)ipv6_hdr(skb)); | 48 | flowlabel = *((u32 *)ipv6_hdr(skb)); |
| 49 | 49 | ||
| 50 | ret = nft_do_chain_pktinfo(&pkt, ops); | 50 | ret = nft_do_chain(&pkt, ops); |
| 51 | if (ret != NF_DROP && ret != NF_QUEUE && | 51 | if (ret != NF_DROP && ret != NF_QUEUE && |
| 52 | (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) || | 52 | (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) || |
| 53 | memcmp(&ipv6_hdr(skb)->daddr, &daddr, sizeof(daddr)) || | 53 | memcmp(&ipv6_hdr(skb)->daddr, &daddr, sizeof(daddr)) || |
| @@ -59,15 +59,15 @@ static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops, | |||
| 59 | return ret; | 59 | return ret; |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | static struct nf_chain_type nft_chain_route_ipv6 = { | 62 | static const struct nf_chain_type nft_chain_route_ipv6 = { |
| 63 | .family = NFPROTO_IPV6, | ||
| 64 | .name = "route", | 63 | .name = "route", |
| 65 | .type = NFT_CHAIN_T_ROUTE, | 64 | .type = NFT_CHAIN_T_ROUTE, |
| 65 | .family = NFPROTO_IPV6, | ||
| 66 | .owner = THIS_MODULE, | ||
| 66 | .hook_mask = (1 << NF_INET_LOCAL_OUT), | 67 | .hook_mask = (1 << NF_INET_LOCAL_OUT), |
| 67 | .fn = { | 68 | .hooks = { |
| 68 | [NF_INET_LOCAL_OUT] = nf_route_table_hook, | 69 | [NF_INET_LOCAL_OUT] = nf_route_table_hook, |
| 69 | }, | 70 | }, |
| 70 | .me = THIS_MODULE, | ||
| 71 | }; | 71 | }; |
| 72 | 72 | ||
| 73 | static int __init nft_chain_route_init(void) | 73 | static int __init nft_chain_route_init(void) |
diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c index 537488cbf941..9b9009f99551 100644 --- a/net/mac80211/aes_cmac.c +++ b/net/mac80211/aes_cmac.c | |||
| @@ -111,7 +111,7 @@ void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, | |||
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | 113 | ||
| 114 | struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]) | 114 | struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[]) |
| 115 | { | 115 | { |
| 116 | struct crypto_cipher *tfm; | 116 | struct crypto_cipher *tfm; |
| 117 | 117 | ||
diff --git a/net/mac80211/aes_cmac.h b/net/mac80211/aes_cmac.h index 20785a647254..0ce6487af795 100644 --- a/net/mac80211/aes_cmac.h +++ b/net/mac80211/aes_cmac.h | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | #include <linux/crypto.h> | 12 | #include <linux/crypto.h> |
| 13 | 13 | ||
| 14 | struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]); | 14 | struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[]); |
| 15 | void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, | 15 | void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, |
| 16 | const u8 *data, size_t data_len, u8 *mic); | 16 | const u8 *data, size_t data_len, u8 *mic); |
| 17 | void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm); | 17 | void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm); |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index ac185286842d..09d2e58a2ba7 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
| @@ -828,6 +828,7 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, | |||
| 828 | if (cfg80211_chandef_identical(&local->monitor_chandef, chandef)) | 828 | if (cfg80211_chandef_identical(&local->monitor_chandef, chandef)) |
| 829 | return 0; | 829 | return 0; |
| 830 | 830 | ||
| 831 | mutex_lock(&local->mtx); | ||
| 831 | mutex_lock(&local->iflist_mtx); | 832 | mutex_lock(&local->iflist_mtx); |
| 832 | if (local->use_chanctx) { | 833 | if (local->use_chanctx) { |
| 833 | sdata = rcu_dereference_protected( | 834 | sdata = rcu_dereference_protected( |
| @@ -846,6 +847,7 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, | |||
| 846 | if (ret == 0) | 847 | if (ret == 0) |
| 847 | local->monitor_chandef = *chandef; | 848 | local->monitor_chandef = *chandef; |
| 848 | mutex_unlock(&local->iflist_mtx); | 849 | mutex_unlock(&local->iflist_mtx); |
| 850 | mutex_unlock(&local->mtx); | ||
| 849 | 851 | ||
| 850 | return ret; | 852 | return ret; |
| 851 | } | 853 | } |
| @@ -951,6 +953,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
| 951 | struct cfg80211_ap_settings *params) | 953 | struct cfg80211_ap_settings *params) |
| 952 | { | 954 | { |
| 953 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 955 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 956 | struct ieee80211_local *local = sdata->local; | ||
| 954 | struct beacon_data *old; | 957 | struct beacon_data *old; |
| 955 | struct ieee80211_sub_if_data *vlan; | 958 | struct ieee80211_sub_if_data *vlan; |
| 956 | u32 changed = BSS_CHANGED_BEACON_INT | | 959 | u32 changed = BSS_CHANGED_BEACON_INT | |
| @@ -969,8 +972,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
| 969 | sdata->needed_rx_chains = sdata->local->rx_chains; | 972 | sdata->needed_rx_chains = sdata->local->rx_chains; |
| 970 | sdata->radar_required = params->radar_required; | 973 | sdata->radar_required = params->radar_required; |
| 971 | 974 | ||
| 975 | mutex_lock(&local->mtx); | ||
| 972 | err = ieee80211_vif_use_channel(sdata, ¶ms->chandef, | 976 | err = ieee80211_vif_use_channel(sdata, ¶ms->chandef, |
| 973 | IEEE80211_CHANCTX_SHARED); | 977 | IEEE80211_CHANCTX_SHARED); |
| 978 | mutex_unlock(&local->mtx); | ||
| 974 | if (err) | 979 | if (err) |
| 975 | return err; | 980 | return err; |
| 976 | ieee80211_vif_copy_chanctx_to_vlans(sdata, false); | 981 | ieee80211_vif_copy_chanctx_to_vlans(sdata, false); |
| @@ -1121,7 +1126,9 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
| 1121 | skb_queue_purge(&sdata->u.ap.ps.bc_buf); | 1126 | skb_queue_purge(&sdata->u.ap.ps.bc_buf); |
| 1122 | 1127 | ||
| 1123 | ieee80211_vif_copy_chanctx_to_vlans(sdata, true); | 1128 | ieee80211_vif_copy_chanctx_to_vlans(sdata, true); |
| 1129 | mutex_lock(&local->mtx); | ||
| 1124 | ieee80211_vif_release_channel(sdata); | 1130 | ieee80211_vif_release_channel(sdata); |
| 1131 | mutex_unlock(&local->mtx); | ||
| 1125 | 1132 | ||
| 1126 | return 0; | 1133 | return 0; |
| 1127 | } | 1134 | } |
| @@ -1944,8 +1951,10 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev, | |||
| 1944 | sdata->smps_mode = IEEE80211_SMPS_OFF; | 1951 | sdata->smps_mode = IEEE80211_SMPS_OFF; |
| 1945 | sdata->needed_rx_chains = sdata->local->rx_chains; | 1952 | sdata->needed_rx_chains = sdata->local->rx_chains; |
| 1946 | 1953 | ||
| 1954 | mutex_lock(&sdata->local->mtx); | ||
| 1947 | err = ieee80211_vif_use_channel(sdata, &setup->chandef, | 1955 | err = ieee80211_vif_use_channel(sdata, &setup->chandef, |
| 1948 | IEEE80211_CHANCTX_SHARED); | 1956 | IEEE80211_CHANCTX_SHARED); |
| 1957 | mutex_unlock(&sdata->local->mtx); | ||
| 1949 | if (err) | 1958 | if (err) |
| 1950 | return err; | 1959 | return err; |
| 1951 | 1960 | ||
| @@ -1957,7 +1966,9 @@ static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev) | |||
| 1957 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1966 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 1958 | 1967 | ||
| 1959 | ieee80211_stop_mesh(sdata); | 1968 | ieee80211_stop_mesh(sdata); |
| 1969 | mutex_lock(&sdata->local->mtx); | ||
| 1960 | ieee80211_vif_release_channel(sdata); | 1970 | ieee80211_vif_release_channel(sdata); |
| 1971 | mutex_unlock(&sdata->local->mtx); | ||
| 1961 | 1972 | ||
| 1962 | return 0; | 1973 | return 0; |
| 1963 | } | 1974 | } |
| @@ -2895,26 +2906,29 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy, | |||
| 2895 | unsigned long timeout; | 2906 | unsigned long timeout; |
| 2896 | int err; | 2907 | int err; |
| 2897 | 2908 | ||
| 2898 | if (!list_empty(&local->roc_list) || local->scanning) | 2909 | mutex_lock(&local->mtx); |
| 2899 | return -EBUSY; | 2910 | if (!list_empty(&local->roc_list) || local->scanning) { |
| 2911 | err = -EBUSY; | ||
| 2912 | goto out_unlock; | ||
| 2913 | } | ||
| 2900 | 2914 | ||
| 2901 | /* whatever, but channel contexts should not complain about that one */ | 2915 | /* whatever, but channel contexts should not complain about that one */ |
| 2902 | sdata->smps_mode = IEEE80211_SMPS_OFF; | 2916 | sdata->smps_mode = IEEE80211_SMPS_OFF; |
| 2903 | sdata->needed_rx_chains = local->rx_chains; | 2917 | sdata->needed_rx_chains = local->rx_chains; |
| 2904 | sdata->radar_required = true; | 2918 | sdata->radar_required = true; |
| 2905 | 2919 | ||
| 2906 | mutex_lock(&local->iflist_mtx); | ||
| 2907 | err = ieee80211_vif_use_channel(sdata, chandef, | 2920 | err = ieee80211_vif_use_channel(sdata, chandef, |
| 2908 | IEEE80211_CHANCTX_SHARED); | 2921 | IEEE80211_CHANCTX_SHARED); |
| 2909 | mutex_unlock(&local->iflist_mtx); | ||
| 2910 | if (err) | 2922 | if (err) |
| 2911 | return err; | 2923 | goto out_unlock; |
| 2912 | 2924 | ||
| 2913 | timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS); | 2925 | timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS); |
| 2914 | ieee80211_queue_delayed_work(&sdata->local->hw, | 2926 | ieee80211_queue_delayed_work(&sdata->local->hw, |
| 2915 | &sdata->dfs_cac_timer_work, timeout); | 2927 | &sdata->dfs_cac_timer_work, timeout); |
| 2916 | 2928 | ||
| 2917 | return 0; | 2929 | out_unlock: |
| 2930 | mutex_unlock(&local->mtx); | ||
| 2931 | return err; | ||
| 2918 | } | 2932 | } |
| 2919 | 2933 | ||
| 2920 | static struct cfg80211_beacon_data * | 2934 | static struct cfg80211_beacon_data * |
| @@ -2990,7 +3004,9 @@ void ieee80211_csa_finalize_work(struct work_struct *work) | |||
| 2990 | goto unlock; | 3004 | goto unlock; |
| 2991 | 3005 | ||
| 2992 | sdata->radar_required = sdata->csa_radar_required; | 3006 | sdata->radar_required = sdata->csa_radar_required; |
| 3007 | mutex_lock(&local->mtx); | ||
| 2993 | err = ieee80211_vif_change_channel(sdata, &changed); | 3008 | err = ieee80211_vif_change_channel(sdata, &changed); |
| 3009 | mutex_unlock(&local->mtx); | ||
| 2994 | if (WARN_ON(err < 0)) | 3010 | if (WARN_ON(err < 0)) |
| 2995 | goto unlock; | 3011 | goto unlock; |
| 2996 | 3012 | ||
| @@ -3821,6 +3837,31 @@ static void ieee80211_set_wakeup(struct wiphy *wiphy, bool enabled) | |||
| 3821 | } | 3837 | } |
| 3822 | #endif | 3838 | #endif |
| 3823 | 3839 | ||
| 3840 | static int ieee80211_set_qos_map(struct wiphy *wiphy, | ||
| 3841 | struct net_device *dev, | ||
| 3842 | struct cfg80211_qos_map *qos_map) | ||
| 3843 | { | ||
| 3844 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 3845 | struct mac80211_qos_map *new_qos_map, *old_qos_map; | ||
| 3846 | |||
| 3847 | if (qos_map) { | ||
| 3848 | new_qos_map = kzalloc(sizeof(*new_qos_map), GFP_KERNEL); | ||
| 3849 | if (!new_qos_map) | ||
| 3850 | return -ENOMEM; | ||
| 3851 | memcpy(&new_qos_map->qos_map, qos_map, sizeof(*qos_map)); | ||
| 3852 | } else { | ||
| 3853 | /* A NULL qos_map was passed to disable QoS mapping */ | ||
| 3854 | new_qos_map = NULL; | ||
| 3855 | } | ||
| 3856 | |||
| 3857 | old_qos_map = rtnl_dereference(sdata->qos_map); | ||
| 3858 | rcu_assign_pointer(sdata->qos_map, new_qos_map); | ||
| 3859 | if (old_qos_map) | ||
| 3860 | kfree_rcu(old_qos_map, rcu_head); | ||
| 3861 | |||
| 3862 | return 0; | ||
| 3863 | } | ||
| 3864 | |||
| 3824 | struct cfg80211_ops mac80211_config_ops = { | 3865 | struct cfg80211_ops mac80211_config_ops = { |
| 3825 | .add_virtual_intf = ieee80211_add_iface, | 3866 | .add_virtual_intf = ieee80211_add_iface, |
| 3826 | .del_virtual_intf = ieee80211_del_iface, | 3867 | .del_virtual_intf = ieee80211_del_iface, |
| @@ -3900,4 +3941,5 @@ struct cfg80211_ops mac80211_config_ops = { | |||
| 3900 | .get_channel = ieee80211_cfg_get_channel, | 3941 | .get_channel = ieee80211_cfg_get_channel, |
| 3901 | .start_radar_detection = ieee80211_start_radar_detection, | 3942 | .start_radar_detection = ieee80211_start_radar_detection, |
| 3902 | .channel_switch = ieee80211_channel_switch, | 3943 | .channel_switch = ieee80211_channel_switch, |
| 3944 | .set_qos_map = ieee80211_set_qos_map, | ||
| 3903 | }; | 3945 | }; |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index a57d5d9466bc..f43613a97dd6 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
| @@ -232,8 +232,8 @@ ieee80211_new_chanctx(struct ieee80211_local *local, | |||
| 232 | if (!local->use_chanctx) | 232 | if (!local->use_chanctx) |
| 233 | local->hw.conf.radar_enabled = ctx->conf.radar_enabled; | 233 | local->hw.conf.radar_enabled = ctx->conf.radar_enabled; |
| 234 | 234 | ||
| 235 | /* acquire mutex to prevent idle from changing */ | 235 | /* we hold the mutex to prevent idle from changing */ |
| 236 | mutex_lock(&local->mtx); | 236 | lockdep_assert_held(&local->mtx); |
| 237 | /* turn idle off *before* setting channel -- some drivers need that */ | 237 | /* turn idle off *before* setting channel -- some drivers need that */ |
| 238 | changed = ieee80211_idle_off(local); | 238 | changed = ieee80211_idle_off(local); |
| 239 | if (changed) | 239 | if (changed) |
| @@ -246,19 +246,14 @@ ieee80211_new_chanctx(struct ieee80211_local *local, | |||
| 246 | err = drv_add_chanctx(local, ctx); | 246 | err = drv_add_chanctx(local, ctx); |
| 247 | if (err) { | 247 | if (err) { |
| 248 | kfree(ctx); | 248 | kfree(ctx); |
| 249 | ctx = ERR_PTR(err); | ||
| 250 | |||
| 251 | ieee80211_recalc_idle(local); | 249 | ieee80211_recalc_idle(local); |
| 252 | goto out; | 250 | return ERR_PTR(err); |
| 253 | } | 251 | } |
| 254 | } | 252 | } |
| 255 | 253 | ||
| 256 | /* and keep the mutex held until the new chanctx is on the list */ | 254 | /* and keep the mutex held until the new chanctx is on the list */ |
| 257 | list_add_rcu(&ctx->list, &local->chanctx_list); | 255 | list_add_rcu(&ctx->list, &local->chanctx_list); |
| 258 | 256 | ||
| 259 | out: | ||
| 260 | mutex_unlock(&local->mtx); | ||
| 261 | |||
| 262 | return ctx; | 257 | return ctx; |
| 263 | } | 258 | } |
| 264 | 259 | ||
| @@ -294,9 +289,7 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local, | |||
| 294 | /* throw a warning if this wasn't the only channel context. */ | 289 | /* throw a warning if this wasn't the only channel context. */ |
| 295 | WARN_ON(check_single_channel && !list_empty(&local->chanctx_list)); | 290 | WARN_ON(check_single_channel && !list_empty(&local->chanctx_list)); |
| 296 | 291 | ||
| 297 | mutex_lock(&local->mtx); | ||
| 298 | ieee80211_recalc_idle(local); | 292 | ieee80211_recalc_idle(local); |
| 299 | mutex_unlock(&local->mtx); | ||
| 300 | } | 293 | } |
| 301 | 294 | ||
| 302 | static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata, | 295 | static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata, |
| @@ -358,6 +351,31 @@ static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local, | |||
| 358 | ieee80211_change_chanctx(local, ctx, compat); | 351 | ieee80211_change_chanctx(local, ctx, compat); |
| 359 | } | 352 | } |
| 360 | 353 | ||
| 354 | static void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local, | ||
| 355 | struct ieee80211_chanctx *chanctx) | ||
| 356 | { | ||
| 357 | bool radar_enabled; | ||
| 358 | |||
| 359 | lockdep_assert_held(&local->chanctx_mtx); | ||
| 360 | /* for setting local->radar_detect_enabled */ | ||
| 361 | lockdep_assert_held(&local->mtx); | ||
| 362 | |||
| 363 | radar_enabled = ieee80211_is_radar_required(local); | ||
| 364 | |||
| 365 | if (radar_enabled == chanctx->conf.radar_enabled) | ||
| 366 | return; | ||
| 367 | |||
| 368 | chanctx->conf.radar_enabled = radar_enabled; | ||
| 369 | local->radar_detect_enabled = chanctx->conf.radar_enabled; | ||
| 370 | |||
| 371 | if (!local->use_chanctx) { | ||
| 372 | local->hw.conf.radar_enabled = chanctx->conf.radar_enabled; | ||
| 373 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
| 374 | } | ||
| 375 | |||
| 376 | drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RADAR); | ||
| 377 | } | ||
| 378 | |||
| 361 | static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata, | 379 | static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata, |
| 362 | struct ieee80211_chanctx *ctx) | 380 | struct ieee80211_chanctx *ctx) |
| 363 | { | 381 | { |
| @@ -404,29 +422,6 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata) | |||
| 404 | ieee80211_free_chanctx(local, ctx); | 422 | ieee80211_free_chanctx(local, ctx); |
| 405 | } | 423 | } |
| 406 | 424 | ||
| 407 | void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local, | ||
| 408 | struct ieee80211_chanctx *chanctx) | ||
| 409 | { | ||
| 410 | bool radar_enabled; | ||
| 411 | |||
| 412 | lockdep_assert_held(&local->chanctx_mtx); | ||
| 413 | |||
| 414 | radar_enabled = ieee80211_is_radar_required(local); | ||
| 415 | |||
| 416 | if (radar_enabled == chanctx->conf.radar_enabled) | ||
| 417 | return; | ||
| 418 | |||
| 419 | chanctx->conf.radar_enabled = radar_enabled; | ||
| 420 | local->radar_detect_enabled = chanctx->conf.radar_enabled; | ||
| 421 | |||
| 422 | if (!local->use_chanctx) { | ||
| 423 | local->hw.conf.radar_enabled = chanctx->conf.radar_enabled; | ||
| 424 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
| 425 | } | ||
| 426 | |||
| 427 | drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RADAR); | ||
| 428 | } | ||
| 429 | |||
| 430 | void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, | 425 | void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, |
| 431 | struct ieee80211_chanctx *chanctx) | 426 | struct ieee80211_chanctx *chanctx) |
| 432 | { | 427 | { |
| @@ -518,6 +513,8 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, | |||
| 518 | struct ieee80211_chanctx *ctx; | 513 | struct ieee80211_chanctx *ctx; |
| 519 | int ret; | 514 | int ret; |
| 520 | 515 | ||
| 516 | lockdep_assert_held(&local->mtx); | ||
| 517 | |||
| 521 | WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev)); | 518 | WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev)); |
| 522 | 519 | ||
| 523 | mutex_lock(&local->chanctx_mtx); | 520 | mutex_lock(&local->chanctx_mtx); |
| @@ -558,6 +555,8 @@ int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata, | |||
| 558 | int ret; | 555 | int ret; |
| 559 | u32 chanctx_changed = 0; | 556 | u32 chanctx_changed = 0; |
| 560 | 557 | ||
| 558 | lockdep_assert_held(&local->mtx); | ||
| 559 | |||
| 561 | /* should never be called if not performing a channel switch. */ | 560 | /* should never be called if not performing a channel switch. */ |
| 562 | if (WARN_ON(!sdata->vif.csa_active)) | 561 | if (WARN_ON(!sdata->vif.csa_active)) |
| 563 | return -EINVAL; | 562 | return -EINVAL; |
| @@ -655,6 +654,8 @@ void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata) | |||
| 655 | { | 654 | { |
| 656 | WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev)); | 655 | WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev)); |
| 657 | 656 | ||
| 657 | lockdep_assert_held(&sdata->local->mtx); | ||
| 658 | |||
| 658 | mutex_lock(&sdata->local->chanctx_mtx); | 659 | mutex_lock(&sdata->local->chanctx_mtx); |
| 659 | __ieee80211_vif_release_channel(sdata); | 660 | __ieee80211_vif_release_channel(sdata); |
| 660 | mutex_unlock(&sdata->local->chanctx_mtx); | 661 | mutex_unlock(&sdata->local->chanctx_mtx); |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index d6ba841437b6..771080ec7212 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
| @@ -293,14 +293,17 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
| 293 | radar_required = true; | 293 | radar_required = true; |
| 294 | } | 294 | } |
| 295 | 295 | ||
| 296 | mutex_lock(&local->mtx); | ||
| 296 | ieee80211_vif_release_channel(sdata); | 297 | ieee80211_vif_release_channel(sdata); |
| 297 | if (ieee80211_vif_use_channel(sdata, &chandef, | 298 | if (ieee80211_vif_use_channel(sdata, &chandef, |
| 298 | ifibss->fixed_channel ? | 299 | ifibss->fixed_channel ? |
| 299 | IEEE80211_CHANCTX_SHARED : | 300 | IEEE80211_CHANCTX_SHARED : |
| 300 | IEEE80211_CHANCTX_EXCLUSIVE)) { | 301 | IEEE80211_CHANCTX_EXCLUSIVE)) { |
| 301 | sdata_info(sdata, "Failed to join IBSS, no channel context\n"); | 302 | sdata_info(sdata, "Failed to join IBSS, no channel context\n"); |
| 303 | mutex_unlock(&local->mtx); | ||
| 302 | return; | 304 | return; |
| 303 | } | 305 | } |
| 306 | mutex_unlock(&local->mtx); | ||
| 304 | 307 | ||
| 305 | memcpy(ifibss->bssid, bssid, ETH_ALEN); | 308 | memcpy(ifibss->bssid, bssid, ETH_ALEN); |
| 306 | 309 | ||
| @@ -363,7 +366,9 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
| 363 | sdata->vif.bss_conf.ssid_len = 0; | 366 | sdata->vif.bss_conf.ssid_len = 0; |
| 364 | RCU_INIT_POINTER(ifibss->presp, NULL); | 367 | RCU_INIT_POINTER(ifibss->presp, NULL); |
| 365 | kfree_rcu(presp, rcu_head); | 368 | kfree_rcu(presp, rcu_head); |
| 369 | mutex_lock(&local->mtx); | ||
| 366 | ieee80211_vif_release_channel(sdata); | 370 | ieee80211_vif_release_channel(sdata); |
| 371 | mutex_unlock(&local->mtx); | ||
| 367 | sdata_info(sdata, "Failed to join IBSS, driver failure: %d\n", | 372 | sdata_info(sdata, "Failed to join IBSS, driver failure: %d\n", |
| 368 | err); | 373 | err); |
| 369 | return; | 374 | return; |
| @@ -747,7 +752,9 @@ static void ieee80211_ibss_disconnect(struct ieee80211_sub_if_data *sdata) | |||
| 747 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | | 752 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | |
| 748 | BSS_CHANGED_IBSS); | 753 | BSS_CHANGED_IBSS); |
| 749 | drv_leave_ibss(local, sdata); | 754 | drv_leave_ibss(local, sdata); |
| 755 | mutex_lock(&local->mtx); | ||
| 750 | ieee80211_vif_release_channel(sdata); | 756 | ieee80211_vif_release_channel(sdata); |
| 757 | mutex_unlock(&local->mtx); | ||
| 751 | } | 758 | } |
| 752 | 759 | ||
| 753 | static void ieee80211_csa_connection_drop_work(struct work_struct *work) | 760 | static void ieee80211_csa_connection_drop_work(struct work_struct *work) |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index fb5dbcb79a12..953b9e294547 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
| @@ -246,7 +246,8 @@ struct ps_data { | |||
| 246 | /* yes, this looks ugly, but guarantees that we can later use | 246 | /* yes, this looks ugly, but guarantees that we can later use |
| 247 | * bitmap_empty :) | 247 | * bitmap_empty :) |
| 248 | * NB: don't touch this bitmap, use sta_info_{set,clear}_tim_bit */ | 248 | * NB: don't touch this bitmap, use sta_info_{set,clear}_tim_bit */ |
| 249 | u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)]; | 249 | u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)] |
| 250 | __aligned(__alignof__(unsigned long)); | ||
| 250 | struct sk_buff_head bc_buf; | 251 | struct sk_buff_head bc_buf; |
| 251 | atomic_t num_sta_ps; /* number of stations in PS mode */ | 252 | atomic_t num_sta_ps; /* number of stations in PS mode */ |
| 252 | int dtim_count; | 253 | int dtim_count; |
| @@ -693,6 +694,11 @@ struct ieee80211_chanctx { | |||
| 693 | struct ieee80211_chanctx_conf conf; | 694 | struct ieee80211_chanctx_conf conf; |
| 694 | }; | 695 | }; |
| 695 | 696 | ||
| 697 | struct mac80211_qos_map { | ||
| 698 | struct cfg80211_qos_map qos_map; | ||
| 699 | struct rcu_head rcu_head; | ||
| 700 | }; | ||
| 701 | |||
| 696 | struct ieee80211_sub_if_data { | 702 | struct ieee80211_sub_if_data { |
| 697 | struct list_head list; | 703 | struct list_head list; |
| 698 | 704 | ||
| @@ -738,6 +744,7 @@ struct ieee80211_sub_if_data { | |||
| 738 | int encrypt_headroom; | 744 | int encrypt_headroom; |
| 739 | 745 | ||
| 740 | struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS]; | 746 | struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS]; |
| 747 | struct mac80211_qos_map __rcu *qos_map; | ||
| 741 | 748 | ||
| 742 | struct work_struct csa_finalize_work; | 749 | struct work_struct csa_finalize_work; |
| 743 | int csa_counter_offset_beacon; | 750 | int csa_counter_offset_beacon; |
| @@ -1775,8 +1782,6 @@ void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata, | |||
| 1775 | 1782 | ||
| 1776 | void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, | 1783 | void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, |
| 1777 | struct ieee80211_chanctx *chanctx); | 1784 | struct ieee80211_chanctx *chanctx); |
| 1778 | void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local, | ||
| 1779 | struct ieee80211_chanctx *chanctx); | ||
| 1780 | void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local, | 1785 | void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local, |
| 1781 | struct ieee80211_chanctx *ctx); | 1786 | struct ieee80211_chanctx *ctx); |
| 1782 | 1787 | ||
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index d624ed49a7d9..b2c83c0f06d0 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
| @@ -418,8 +418,10 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
| 418 | return ret; | 418 | return ret; |
| 419 | } | 419 | } |
| 420 | 420 | ||
| 421 | mutex_lock(&local->mtx); | ||
| 421 | ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, | 422 | ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, |
| 422 | IEEE80211_CHANCTX_EXCLUSIVE); | 423 | IEEE80211_CHANCTX_EXCLUSIVE); |
| 424 | mutex_unlock(&local->mtx); | ||
| 423 | if (ret) { | 425 | if (ret) { |
| 424 | drv_remove_interface(local, sdata); | 426 | drv_remove_interface(local, sdata); |
| 425 | kfree(sdata); | 427 | kfree(sdata); |
| @@ -456,7 +458,9 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | |||
| 456 | 458 | ||
| 457 | synchronize_net(); | 459 | synchronize_net(); |
| 458 | 460 | ||
| 461 | mutex_lock(&local->mtx); | ||
| 459 | ieee80211_vif_release_channel(sdata); | 462 | ieee80211_vif_release_channel(sdata); |
| 463 | mutex_unlock(&local->mtx); | ||
| 460 | 464 | ||
| 461 | drv_remove_interface(local, sdata); | 465 | drv_remove_interface(local, sdata); |
| 462 | 466 | ||
| @@ -826,9 +830,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
| 826 | if (sdata->wdev.cac_started) { | 830 | if (sdata->wdev.cac_started) { |
| 827 | chandef = sdata->vif.bss_conf.chandef; | 831 | chandef = sdata->vif.bss_conf.chandef; |
| 828 | WARN_ON(local->suspended); | 832 | WARN_ON(local->suspended); |
| 829 | mutex_lock(&local->iflist_mtx); | 833 | mutex_lock(&local->mtx); |
| 830 | ieee80211_vif_release_channel(sdata); | 834 | ieee80211_vif_release_channel(sdata); |
| 831 | mutex_unlock(&local->iflist_mtx); | 835 | mutex_unlock(&local->mtx); |
| 832 | cfg80211_cac_event(sdata->dev, &chandef, | 836 | cfg80211_cac_event(sdata->dev, &chandef, |
| 833 | NL80211_RADAR_CAC_ABORTED, | 837 | NL80211_RADAR_CAC_ABORTED, |
| 834 | GFP_KERNEL); | 838 | GFP_KERNEL); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 9c2c7ee2cc30..fc1d82465b3c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
| @@ -888,7 +888,9 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
| 888 | if (!ifmgd->associated) | 888 | if (!ifmgd->associated) |
| 889 | goto out; | 889 | goto out; |
| 890 | 890 | ||
| 891 | mutex_lock(&local->mtx); | ||
| 891 | ret = ieee80211_vif_change_channel(sdata, &changed); | 892 | ret = ieee80211_vif_change_channel(sdata, &changed); |
| 893 | mutex_unlock(&local->mtx); | ||
| 892 | if (ret) { | 894 | if (ret) { |
| 893 | sdata_info(sdata, | 895 | sdata_info(sdata, |
| 894 | "vif channel switch failed, disconnecting\n"); | 896 | "vif channel switch failed, disconnecting\n"); |
| @@ -1401,10 +1403,14 @@ void ieee80211_dfs_cac_timer_work(struct work_struct *work) | |||
| 1401 | dfs_cac_timer_work); | 1403 | dfs_cac_timer_work); |
| 1402 | struct cfg80211_chan_def chandef = sdata->vif.bss_conf.chandef; | 1404 | struct cfg80211_chan_def chandef = sdata->vif.bss_conf.chandef; |
| 1403 | 1405 | ||
| 1404 | ieee80211_vif_release_channel(sdata); | 1406 | mutex_lock(&sdata->local->mtx); |
| 1405 | cfg80211_cac_event(sdata->dev, &chandef, | 1407 | if (sdata->wdev.cac_started) { |
| 1406 | NL80211_RADAR_CAC_FINISHED, | 1408 | ieee80211_vif_release_channel(sdata); |
| 1407 | GFP_KERNEL); | 1409 | cfg80211_cac_event(sdata->dev, &chandef, |
| 1410 | NL80211_RADAR_CAC_FINISHED, | ||
| 1411 | GFP_KERNEL); | ||
| 1412 | } | ||
| 1413 | mutex_unlock(&sdata->local->mtx); | ||
| 1408 | } | 1414 | } |
| 1409 | 1415 | ||
| 1410 | /* MLME */ | 1416 | /* MLME */ |
| @@ -1747,7 +1753,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
| 1747 | ifmgd->have_beacon = false; | 1753 | ifmgd->have_beacon = false; |
| 1748 | 1754 | ||
| 1749 | ifmgd->flags = 0; | 1755 | ifmgd->flags = 0; |
| 1756 | mutex_lock(&local->mtx); | ||
| 1750 | ieee80211_vif_release_channel(sdata); | 1757 | ieee80211_vif_release_channel(sdata); |
| 1758 | mutex_unlock(&local->mtx); | ||
| 1751 | 1759 | ||
| 1752 | sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; | 1760 | sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; |
| 1753 | } | 1761 | } |
| @@ -2070,7 +2078,9 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata, | |||
| 2070 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); | 2078 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); |
| 2071 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); | 2079 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); |
| 2072 | sdata->u.mgd.flags = 0; | 2080 | sdata->u.mgd.flags = 0; |
| 2081 | mutex_lock(&sdata->local->mtx); | ||
| 2073 | ieee80211_vif_release_channel(sdata); | 2082 | ieee80211_vif_release_channel(sdata); |
| 2083 | mutex_unlock(&sdata->local->mtx); | ||
| 2074 | } | 2084 | } |
| 2075 | 2085 | ||
| 2076 | cfg80211_put_bss(sdata->local->hw.wiphy, auth_data->bss); | 2086 | cfg80211_put_bss(sdata->local->hw.wiphy, auth_data->bss); |
| @@ -2319,7 +2329,9 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata, | |||
| 2319 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); | 2329 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); |
| 2320 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); | 2330 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); |
| 2321 | sdata->u.mgd.flags = 0; | 2331 | sdata->u.mgd.flags = 0; |
| 2332 | mutex_lock(&sdata->local->mtx); | ||
| 2322 | ieee80211_vif_release_channel(sdata); | 2333 | ieee80211_vif_release_channel(sdata); |
| 2334 | mutex_unlock(&sdata->local->mtx); | ||
| 2323 | } | 2335 | } |
| 2324 | 2336 | ||
| 2325 | kfree(assoc_data); | 2337 | kfree(assoc_data); |
| @@ -3670,6 +3682,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
| 3670 | /* will change later if needed */ | 3682 | /* will change later if needed */ |
| 3671 | sdata->smps_mode = IEEE80211_SMPS_OFF; | 3683 | sdata->smps_mode = IEEE80211_SMPS_OFF; |
| 3672 | 3684 | ||
| 3685 | mutex_lock(&local->mtx); | ||
| 3673 | /* | 3686 | /* |
| 3674 | * If this fails (possibly due to channel context sharing | 3687 | * If this fails (possibly due to channel context sharing |
| 3675 | * on incompatible channels, e.g. 80+80 and 160 sharing the | 3688 | * on incompatible channels, e.g. 80+80 and 160 sharing the |
| @@ -3681,13 +3694,15 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
| 3681 | /* don't downgrade for 5 and 10 MHz channels, though. */ | 3694 | /* don't downgrade for 5 and 10 MHz channels, though. */ |
| 3682 | if (chandef.width == NL80211_CHAN_WIDTH_5 || | 3695 | if (chandef.width == NL80211_CHAN_WIDTH_5 || |
| 3683 | chandef.width == NL80211_CHAN_WIDTH_10) | 3696 | chandef.width == NL80211_CHAN_WIDTH_10) |
| 3684 | return ret; | 3697 | goto out; |
| 3685 | 3698 | ||
| 3686 | while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) { | 3699 | while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) { |
| 3687 | ifmgd->flags |= ieee80211_chandef_downgrade(&chandef); | 3700 | ifmgd->flags |= ieee80211_chandef_downgrade(&chandef); |
| 3688 | ret = ieee80211_vif_use_channel(sdata, &chandef, | 3701 | ret = ieee80211_vif_use_channel(sdata, &chandef, |
| 3689 | IEEE80211_CHANCTX_SHARED); | 3702 | IEEE80211_CHANCTX_SHARED); |
| 3690 | } | 3703 | } |
| 3704 | out: | ||
| 3705 | mutex_unlock(&local->mtx); | ||
| 3691 | return ret; | 3706 | return ret; |
| 3692 | } | 3707 | } |
| 3693 | 3708 | ||
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index d2f19f7e7091..f3d88b0c054c 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
| @@ -135,7 +135,7 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) | |||
| 135 | u32 usecs; | 135 | u32 usecs; |
| 136 | int i; | 136 | int i; |
| 137 | 137 | ||
| 138 | for (i=0; i < MAX_THR_RATES; i++) | 138 | for (i = 0; i < MAX_THR_RATES; i++) |
| 139 | tmp_tp_rate[i] = 0; | 139 | tmp_tp_rate[i] = 0; |
| 140 | 140 | ||
| 141 | for (i = 0; i < mi->n_rates; i++) { | 141 | for (i = 0; i < mi->n_rates; i++) { |
| @@ -190,7 +190,7 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) | |||
| 190 | * choose the maximum throughput rate as max_prob_rate | 190 | * choose the maximum throughput rate as max_prob_rate |
| 191 | * (2) if all success probabilities < 95%, the rate with | 191 | * (2) if all success probabilities < 95%, the rate with |
| 192 | * highest success probability is choosen as max_prob_rate */ | 192 | * highest success probability is choosen as max_prob_rate */ |
| 193 | if (mr->probability >= MINSTREL_FRAC(95,100)) { | 193 | if (mr->probability >= MINSTREL_FRAC(95, 100)) { |
| 194 | if (mr->cur_tp >= mi->r[tmp_prob_rate].cur_tp) | 194 | if (mr->cur_tp >= mi->r[tmp_prob_rate].cur_tp) |
| 195 | tmp_prob_rate = i; | 195 | tmp_prob_rate = i; |
| 196 | } else { | 196 | } else { |
| @@ -220,7 +220,7 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) | |||
| 220 | 220 | ||
| 221 | static void | 221 | static void |
| 222 | minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, | 222 | minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, |
| 223 | struct ieee80211_sta *sta, void *priv_sta, | 223 | struct ieee80211_sta *sta, void *priv_sta, |
| 224 | struct sk_buff *skb) | 224 | struct sk_buff *skb) |
| 225 | { | 225 | { |
| 226 | struct minstrel_priv *mp = priv; | 226 | struct minstrel_priv *mp = priv; |
| @@ -260,7 +260,7 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
| 260 | 260 | ||
| 261 | static inline unsigned int | 261 | static inline unsigned int |
| 262 | minstrel_get_retry_count(struct minstrel_rate *mr, | 262 | minstrel_get_retry_count(struct minstrel_rate *mr, |
| 263 | struct ieee80211_tx_info *info) | 263 | struct ieee80211_tx_info *info) |
| 264 | { | 264 | { |
| 265 | unsigned int retry = mr->adjusted_retry_count; | 265 | unsigned int retry = mr->adjusted_retry_count; |
| 266 | 266 | ||
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index d2ed18d82fe1..c1b5b73c5b91 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
| @@ -63,7 +63,7 @@ | |||
| 63 | 63 | ||
| 64 | #define CCK_DURATION(_bitrate, _short, _len) \ | 64 | #define CCK_DURATION(_bitrate, _short, _len) \ |
| 65 | (1000 * (10 /* SIFS */ + \ | 65 | (1000 * (10 /* SIFS */ + \ |
| 66 | (_short ? 72 + 24 : 144 + 48 ) + \ | 66 | (_short ? 72 + 24 : 144 + 48) + \ |
| 67 | (8 * (_len + 4) * 10) / (_bitrate))) | 67 | (8 * (_len + 4) * 10) / (_bitrate))) |
| 68 | 68 | ||
| 69 | #define CCK_ACK_DURATION(_bitrate, _short) \ | 69 | #define CCK_ACK_DURATION(_bitrate, _short) \ |
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 124b1fdc20d0..0ae207771a58 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c | |||
| @@ -186,7 +186,7 @@ void ieee80211_get_tkip_p1k_iv(struct ieee80211_key_conf *keyconf, | |||
| 186 | EXPORT_SYMBOL(ieee80211_get_tkip_p1k_iv); | 186 | EXPORT_SYMBOL(ieee80211_get_tkip_p1k_iv); |
| 187 | 187 | ||
| 188 | void ieee80211_get_tkip_rx_p1k(struct ieee80211_key_conf *keyconf, | 188 | void ieee80211_get_tkip_rx_p1k(struct ieee80211_key_conf *keyconf, |
| 189 | const u8 *ta, u32 iv32, u16 *p1k) | 189 | const u8 *ta, u32 iv32, u16 *p1k) |
| 190 | { | 190 | { |
| 191 | const u8 *tk = &keyconf->key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; | 191 | const u8 *tk = &keyconf->key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; |
| 192 | struct tkip_ctx ctx; | 192 | struct tkip_ctx ctx; |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 3a669d7ec7ad..da9366632f37 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
| @@ -553,7 +553,7 @@ TRACE_EVENT(drv_update_tkip_key, | |||
| 553 | 553 | ||
| 554 | TP_printk( | 554 | TP_printk( |
| 555 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " iv32:%#x", | 555 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " iv32:%#x", |
| 556 | LOCAL_PR_ARG,VIF_PR_ARG,STA_PR_ARG, __entry->iv32 | 556 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->iv32 |
| 557 | ) | 557 | ) |
| 558 | ); | 558 | ); |
| 559 | 559 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 2f0e176e7989..377cf974d97d 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
| @@ -2161,7 +2161,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
| 2161 | if (ieee80211_is_data_qos(fc)) { | 2161 | if (ieee80211_is_data_qos(fc)) { |
| 2162 | __le16 *qos_control; | 2162 | __le16 *qos_control; |
| 2163 | 2163 | ||
| 2164 | qos_control = (__le16*) skb_push(skb, 2); | 2164 | qos_control = (__le16 *) skb_push(skb, 2); |
| 2165 | memcpy(skb_push(skb, hdrlen - 2), &hdr, hdrlen - 2); | 2165 | memcpy(skb_push(skb, hdrlen - 2), &hdr, hdrlen - 2); |
| 2166 | /* | 2166 | /* |
| 2167 | * Maybe we could actually set some fields here, for now just | 2167 | * Maybe we could actually set some fields here, for now just |
| @@ -2323,7 +2323,7 @@ static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, | |||
| 2323 | if (atomic_read(&ps->num_sta_ps) > 0) | 2323 | if (atomic_read(&ps->num_sta_ps) > 0) |
| 2324 | /* in the hope that this is faster than | 2324 | /* in the hope that this is faster than |
| 2325 | * checking byte-for-byte */ | 2325 | * checking byte-for-byte */ |
| 2326 | have_bits = !bitmap_empty((unsigned long*)ps->tim, | 2326 | have_bits = !bitmap_empty((unsigned long *)ps->tim, |
| 2327 | IEEE80211_MAX_AID+1); | 2327 | IEEE80211_MAX_AID+1); |
| 2328 | 2328 | ||
| 2329 | if (ps->dtim_count == 0) | 2329 | if (ps->dtim_count == 0) |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 591b46b72462..df00f1978a77 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
| @@ -76,7 +76,7 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | |||
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | if (ieee80211_is_ctl(fc)) { | 78 | if (ieee80211_is_ctl(fc)) { |
| 79 | if(ieee80211_is_pspoll(fc)) | 79 | if (ieee80211_is_pspoll(fc)) |
| 80 | return hdr->addr1; | 80 | return hdr->addr1; |
| 81 | 81 | ||
| 82 | if (ieee80211_is_back_req(fc)) { | 82 | if (ieee80211_is_back_req(fc)) { |
| @@ -2315,9 +2315,14 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local) | |||
| 2315 | struct ieee80211_sub_if_data *sdata; | 2315 | struct ieee80211_sub_if_data *sdata; |
| 2316 | struct cfg80211_chan_def chandef; | 2316 | struct cfg80211_chan_def chandef; |
| 2317 | 2317 | ||
| 2318 | mutex_lock(&local->mtx); | ||
| 2318 | mutex_lock(&local->iflist_mtx); | 2319 | mutex_lock(&local->iflist_mtx); |
| 2319 | list_for_each_entry(sdata, &local->interfaces, list) { | 2320 | list_for_each_entry(sdata, &local->interfaces, list) { |
| 2320 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); | 2321 | /* it might be waiting for the local->mtx, but then |
| 2322 | * by the time it gets it, sdata->wdev.cac_started | ||
| 2323 | * will no longer be true | ||
| 2324 | */ | ||
| 2325 | cancel_delayed_work(&sdata->dfs_cac_timer_work); | ||
| 2321 | 2326 | ||
| 2322 | if (sdata->wdev.cac_started) { | 2327 | if (sdata->wdev.cac_started) { |
| 2323 | chandef = sdata->vif.bss_conf.chandef; | 2328 | chandef = sdata->vif.bss_conf.chandef; |
| @@ -2329,6 +2334,7 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local) | |||
| 2329 | } | 2334 | } |
| 2330 | } | 2335 | } |
| 2331 | mutex_unlock(&local->iflist_mtx); | 2336 | mutex_unlock(&local->iflist_mtx); |
| 2337 | mutex_unlock(&local->mtx); | ||
| 2332 | } | 2338 | } |
| 2333 | 2339 | ||
| 2334 | void ieee80211_dfs_radar_detected_work(struct work_struct *work) | 2340 | void ieee80211_dfs_radar_detected_work(struct work_struct *work) |
| @@ -2588,3 +2594,143 @@ int ieee80211_cs_headroom(struct ieee80211_local *local, | |||
| 2588 | 2594 | ||
| 2589 | return headroom; | 2595 | return headroom; |
| 2590 | } | 2596 | } |
| 2597 | |||
| 2598 | static bool | ||
| 2599 | ieee80211_extend_noa_desc(struct ieee80211_noa_data *data, u32 tsf, int i) | ||
| 2600 | { | ||
| 2601 | s32 end = data->desc[i].start + data->desc[i].duration - (tsf + 1); | ||
| 2602 | int skip; | ||
| 2603 | |||
| 2604 | if (end > 0) | ||
| 2605 | return false; | ||
| 2606 | |||
| 2607 | /* End time is in the past, check for repetitions */ | ||
| 2608 | skip = DIV_ROUND_UP(-end, data->desc[i].interval); | ||
| 2609 | if (data->count[i] < 255) { | ||
| 2610 | if (data->count[i] <= skip) { | ||
| 2611 | data->count[i] = 0; | ||
| 2612 | return false; | ||
| 2613 | } | ||
| 2614 | |||
| 2615 | data->count[i] -= skip; | ||
| 2616 | } | ||
| 2617 | |||
| 2618 | data->desc[i].start += skip * data->desc[i].interval; | ||
| 2619 | |||
| 2620 | return true; | ||
| 2621 | } | ||
| 2622 | |||
| 2623 | static bool | ||
| 2624 | ieee80211_extend_absent_time(struct ieee80211_noa_data *data, u32 tsf, | ||
| 2625 | s32 *offset) | ||
| 2626 | { | ||
| 2627 | bool ret = false; | ||
| 2628 | int i; | ||
| 2629 | |||
| 2630 | for (i = 0; i < IEEE80211_P2P_NOA_DESC_MAX; i++) { | ||
| 2631 | s32 cur; | ||
| 2632 | |||
| 2633 | if (!data->count[i]) | ||
| 2634 | continue; | ||
| 2635 | |||
| 2636 | if (ieee80211_extend_noa_desc(data, tsf + *offset, i)) | ||
| 2637 | ret = true; | ||
| 2638 | |||
| 2639 | cur = data->desc[i].start - tsf; | ||
| 2640 | if (cur > *offset) | ||
| 2641 | continue; | ||
| 2642 | |||
| 2643 | cur = data->desc[i].start + data->desc[i].duration - tsf; | ||
| 2644 | if (cur > *offset) | ||
| 2645 | *offset = cur; | ||
| 2646 | } | ||
| 2647 | |||
| 2648 | return ret; | ||
| 2649 | } | ||
| 2650 | |||
| 2651 | static u32 | ||
| 2652 | ieee80211_get_noa_absent_time(struct ieee80211_noa_data *data, u32 tsf) | ||
| 2653 | { | ||
| 2654 | s32 offset = 0; | ||
| 2655 | int tries = 0; | ||
| 2656 | /* | ||
| 2657 | * arbitrary limit, used to avoid infinite loops when combined NoA | ||
| 2658 | * descriptors cover the full time period. | ||
| 2659 | */ | ||
| 2660 | int max_tries = 5; | ||
| 2661 | |||
| 2662 | ieee80211_extend_absent_time(data, tsf, &offset); | ||
| 2663 | do { | ||
| 2664 | if (!ieee80211_extend_absent_time(data, tsf, &offset)) | ||
| 2665 | break; | ||
| 2666 | |||
| 2667 | tries++; | ||
| 2668 | } while (tries < max_tries); | ||
| 2669 | |||
| 2670 | return offset; | ||
| 2671 | } | ||
| 2672 | |||
| 2673 | void ieee80211_update_p2p_noa(struct ieee80211_noa_data *data, u32 tsf) | ||
| 2674 | { | ||
| 2675 | u32 next_offset = BIT(31) - 1; | ||
| 2676 | int i; | ||
| 2677 | |||
| 2678 | data->absent = 0; | ||
| 2679 | data->has_next_tsf = false; | ||
| 2680 | for (i = 0; i < IEEE80211_P2P_NOA_DESC_MAX; i++) { | ||
| 2681 | s32 start; | ||
| 2682 | |||
| 2683 | if (!data->count[i]) | ||
| 2684 | continue; | ||
| 2685 | |||
| 2686 | ieee80211_extend_noa_desc(data, tsf, i); | ||
| 2687 | start = data->desc[i].start - tsf; | ||
| 2688 | if (start <= 0) | ||
| 2689 | data->absent |= BIT(i); | ||
| 2690 | |||
| 2691 | if (next_offset > start) | ||
| 2692 | next_offset = start; | ||
| 2693 | |||
| 2694 | data->has_next_tsf = true; | ||
| 2695 | } | ||
| 2696 | |||
| 2697 | if (data->absent) | ||
| 2698 | next_offset = ieee80211_get_noa_absent_time(data, tsf); | ||
| 2699 | |||
| 2700 | data->next_tsf = tsf + next_offset; | ||
| 2701 | } | ||
| 2702 | EXPORT_SYMBOL(ieee80211_update_p2p_noa); | ||
| 2703 | |||
| 2704 | int ieee80211_parse_p2p_noa(const struct ieee80211_p2p_noa_attr *attr, | ||
| 2705 | struct ieee80211_noa_data *data, u32 tsf) | ||
| 2706 | { | ||
| 2707 | int ret = 0; | ||
| 2708 | int i; | ||
| 2709 | |||
| 2710 | memset(data, 0, sizeof(*data)); | ||
| 2711 | |||
| 2712 | for (i = 0; i < IEEE80211_P2P_NOA_DESC_MAX; i++) { | ||
| 2713 | const struct ieee80211_p2p_noa_desc *desc = &attr->desc[i]; | ||
| 2714 | |||
| 2715 | if (!desc->count || !desc->duration) | ||
| 2716 | continue; | ||
| 2717 | |||
| 2718 | data->count[i] = desc->count; | ||
| 2719 | data->desc[i].start = le32_to_cpu(desc->start_time); | ||
| 2720 | data->desc[i].duration = le32_to_cpu(desc->duration); | ||
| 2721 | data->desc[i].interval = le32_to_cpu(desc->interval); | ||
| 2722 | |||
| 2723 | if (data->count[i] > 1 && | ||
| 2724 | data->desc[i].interval < data->desc[i].duration) | ||
| 2725 | continue; | ||
| 2726 | |||
| 2727 | ieee80211_extend_noa_desc(data, tsf, i); | ||
| 2728 | ret++; | ||
| 2729 | } | ||
| 2730 | |||
| 2731 | if (ret) | ||
| 2732 | ieee80211_update_p2p_noa(data, tsf); | ||
| 2733 | |||
| 2734 | return ret; | ||
| 2735 | } | ||
| 2736 | EXPORT_SYMBOL(ieee80211_parse_p2p_noa); | ||
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index afba19cb6f87..21211c60ca98 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
| @@ -106,6 +106,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | |||
| 106 | struct sta_info *sta = NULL; | 106 | struct sta_info *sta = NULL; |
| 107 | const u8 *ra = NULL; | 107 | const u8 *ra = NULL; |
| 108 | bool qos = false; | 108 | bool qos = false; |
| 109 | struct mac80211_qos_map *qos_map; | ||
| 109 | 110 | ||
| 110 | if (local->hw.queues < IEEE80211_NUM_ACS || skb->len < 6) { | 111 | if (local->hw.queues < IEEE80211_NUM_ACS || skb->len < 6) { |
| 111 | skb->priority = 0; /* required for correct WPA/11i MIC */ | 112 | skb->priority = 0; /* required for correct WPA/11i MIC */ |
| @@ -155,7 +156,11 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | |||
| 155 | 156 | ||
| 156 | /* use the data classifier to determine what 802.1d tag the | 157 | /* use the data classifier to determine what 802.1d tag the |
| 157 | * data frame has */ | 158 | * data frame has */ |
| 158 | skb->priority = cfg80211_classify8021d(skb); | 159 | rcu_read_lock(); |
| 160 | qos_map = rcu_dereference(sdata->qos_map); | ||
| 161 | skb->priority = cfg80211_classify8021d(skb, qos_map ? | ||
| 162 | &qos_map->qos_map : NULL); | ||
| 163 | rcu_read_unlock(); | ||
| 159 | 164 | ||
| 160 | return ieee80211_downgrade_queue(sdata, skb); | 165 | return ieee80211_downgrade_queue(sdata, skb); |
| 161 | } | 166 | } |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index c3b3b26c4c4e..afe50c0f526f 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
| @@ -428,6 +428,14 @@ config NF_TABLES | |||
| 428 | 428 | ||
| 429 | To compile it as a module, choose M here. | 429 | To compile it as a module, choose M here. |
| 430 | 430 | ||
| 431 | config NF_TABLES_INET | ||
| 432 | depends on NF_TABLES | ||
| 433 | select NF_TABLES_IPV4 | ||
| 434 | select NF_TABLES_IPV6 | ||
| 435 | tristate "Netfilter nf_tables mixed IPv4/IPv6 tables support" | ||
| 436 | help | ||
| 437 | This option enables support for a mixed IPv4/IPv6 "inet" table. | ||
| 438 | |||
| 431 | config NFT_EXTHDR | 439 | config NFT_EXTHDR |
| 432 | depends on NF_TABLES | 440 | depends on NF_TABLES |
| 433 | tristate "Netfilter nf_tables IPv6 exthdr module" | 441 | tristate "Netfilter nf_tables IPv6 exthdr module" |
| @@ -1131,6 +1139,16 @@ config NETFILTER_XT_MATCH_IPVS | |||
| 1131 | 1139 | ||
| 1132 | If unsure, say N. | 1140 | If unsure, say N. |
| 1133 | 1141 | ||
| 1142 | config NETFILTER_XT_MATCH_L2TP | ||
| 1143 | tristate '"l2tp" match support' | ||
| 1144 | depends on NETFILTER_ADVANCED | ||
| 1145 | default L2TP | ||
| 1146 | ---help--- | ||
| 1147 | This option adds an "L2TP" match, which allows you to match against | ||
| 1148 | L2TP protocol header fields. | ||
| 1149 | |||
| 1150 | To compile it as a module, choose M here. If unsure, say N. | ||
| 1151 | |||
| 1134 | config NETFILTER_XT_MATCH_LENGTH | 1152 | config NETFILTER_XT_MATCH_LENGTH |
| 1135 | tristate '"length" match support' | 1153 | tristate '"length" match support' |
| 1136 | depends on NETFILTER_ADVANCED | 1154 | depends on NETFILTER_ADVANCED |
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 78b4e1c9c595..ee9c4de5f8ed 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
| @@ -70,6 +70,7 @@ nf_tables-objs += nft_immediate.o nft_cmp.o nft_lookup.o | |||
| 70 | nf_tables-objs += nft_bitwise.o nft_byteorder.o nft_payload.o | 70 | nf_tables-objs += nft_bitwise.o nft_byteorder.o nft_payload.o |
| 71 | 71 | ||
| 72 | obj-$(CONFIG_NF_TABLES) += nf_tables.o | 72 | obj-$(CONFIG_NF_TABLES) += nf_tables.o |
| 73 | obj-$(CONFIG_NF_TABLES_INET) += nf_tables_inet.o | ||
| 73 | obj-$(CONFIG_NFT_COMPAT) += nft_compat.o | 74 | obj-$(CONFIG_NFT_COMPAT) += nft_compat.o |
| 74 | obj-$(CONFIG_NFT_EXTHDR) += nft_exthdr.o | 75 | obj-$(CONFIG_NFT_EXTHDR) += nft_exthdr.o |
| 75 | obj-$(CONFIG_NFT_META) += nft_meta.o | 76 | obj-$(CONFIG_NFT_META) += nft_meta.o |
| @@ -137,6 +138,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_HL) += xt_hl.o | |||
| 137 | obj-$(CONFIG_NETFILTER_XT_MATCH_IPCOMP) += xt_ipcomp.o | 138 | obj-$(CONFIG_NETFILTER_XT_MATCH_IPCOMP) += xt_ipcomp.o |
| 138 | obj-$(CONFIG_NETFILTER_XT_MATCH_IPRANGE) += xt_iprange.o | 139 | obj-$(CONFIG_NETFILTER_XT_MATCH_IPRANGE) += xt_iprange.o |
| 139 | obj-$(CONFIG_NETFILTER_XT_MATCH_IPVS) += xt_ipvs.o | 140 | obj-$(CONFIG_NETFILTER_XT_MATCH_IPVS) += xt_ipvs.o |
| 141 | obj-$(CONFIG_NETFILTER_XT_MATCH_L2TP) += xt_l2tp.o | ||
| 140 | obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o | 142 | obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o |
| 141 | obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o | 143 | obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o |
| 142 | obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o | 144 | obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o |
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index a99b6c3427b0..cb372f96f10d 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c | |||
| @@ -428,7 +428,7 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb, | |||
| 428 | const char *msg; | 428 | const char *msg; |
| 429 | u_int8_t state; | 429 | u_int8_t state; |
| 430 | 430 | ||
| 431 | dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh); | 431 | dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh); |
| 432 | BUG_ON(dh == NULL); | 432 | BUG_ON(dh == NULL); |
| 433 | 433 | ||
| 434 | state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE]; | 434 | state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE]; |
| @@ -457,7 +457,7 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb, | |||
| 457 | out_invalid: | 457 | out_invalid: |
| 458 | if (LOG_INVALID(net, IPPROTO_DCCP)) | 458 | if (LOG_INVALID(net, IPPROTO_DCCP)) |
| 459 | nf_log_packet(net, nf_ct_l3num(ct), 0, skb, NULL, NULL, | 459 | nf_log_packet(net, nf_ct_l3num(ct), 0, skb, NULL, NULL, |
| 460 | NULL, msg); | 460 | NULL, "%s", msg); |
| 461 | return false; | 461 | return false; |
| 462 | } | 462 | } |
| 463 | 463 | ||
| @@ -486,7 +486,7 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, | |||
| 486 | u_int8_t type, old_state, new_state; | 486 | u_int8_t type, old_state, new_state; |
| 487 | enum ct_dccp_roles role; | 487 | enum ct_dccp_roles role; |
| 488 | 488 | ||
| 489 | dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh); | 489 | dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh); |
| 490 | BUG_ON(dh == NULL); | 490 | BUG_ON(dh == NULL); |
| 491 | type = dh->dccph_type; | 491 | type = dh->dccph_type; |
| 492 | 492 | ||
| @@ -577,7 +577,7 @@ static int dccp_error(struct net *net, struct nf_conn *tmpl, | |||
| 577 | unsigned int cscov; | 577 | unsigned int cscov; |
| 578 | const char *msg; | 578 | const char *msg; |
| 579 | 579 | ||
| 580 | dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh); | 580 | dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh); |
| 581 | if (dh == NULL) { | 581 | if (dh == NULL) { |
| 582 | msg = "nf_ct_dccp: short packet "; | 582 | msg = "nf_ct_dccp: short packet "; |
| 583 | goto out_invalid; | 583 | goto out_invalid; |
| @@ -614,7 +614,7 @@ static int dccp_error(struct net *net, struct nf_conn *tmpl, | |||
| 614 | 614 | ||
| 615 | out_invalid: | 615 | out_invalid: |
| 616 | if (LOG_INVALID(net, IPPROTO_DCCP)) | 616 | if (LOG_INVALID(net, IPPROTO_DCCP)) |
| 617 | nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, msg); | 617 | nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "%s", msg); |
| 618 | return -NF_ACCEPT; | 618 | return -NF_ACCEPT; |
| 619 | } | 619 | } |
| 620 | 620 | ||
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 1fcef1ec1dc1..36add31e08e7 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
| @@ -124,37 +124,43 @@ static inline u64 nf_tables_alloc_handle(struct nft_table *table) | |||
| 124 | return ++table->hgenerator; | 124 | return ++table->hgenerator; |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | static struct nf_chain_type *chain_type[AF_MAX][NFT_CHAIN_T_MAX]; | 127 | static const struct nf_chain_type *chain_type[AF_MAX][NFT_CHAIN_T_MAX]; |
| 128 | 128 | ||
| 129 | static int __nf_tables_chain_type_lookup(int family, const struct nlattr *nla) | 129 | static const struct nf_chain_type * |
| 130 | __nf_tables_chain_type_lookup(int family, const struct nlattr *nla) | ||
| 130 | { | 131 | { |
| 131 | int i; | 132 | int i; |
| 132 | 133 | ||
| 133 | for (i=0; i<NFT_CHAIN_T_MAX; i++) { | 134 | for (i = 0; i < NFT_CHAIN_T_MAX; i++) { |
| 134 | if (chain_type[family][i] != NULL && | 135 | if (chain_type[family][i] != NULL && |
| 135 | !nla_strcmp(nla, chain_type[family][i]->name)) | 136 | !nla_strcmp(nla, chain_type[family][i]->name)) |
| 136 | return i; | 137 | return chain_type[family][i]; |
| 137 | } | 138 | } |
| 138 | return -1; | 139 | return NULL; |
| 139 | } | 140 | } |
| 140 | 141 | ||
| 141 | static int nf_tables_chain_type_lookup(const struct nft_af_info *afi, | 142 | static const struct nf_chain_type * |
| 142 | const struct nlattr *nla, | 143 | nf_tables_chain_type_lookup(const struct nft_af_info *afi, |
| 143 | bool autoload) | 144 | const struct nlattr *nla, |
| 145 | bool autoload) | ||
| 144 | { | 146 | { |
| 145 | int type; | 147 | const struct nf_chain_type *type; |
| 146 | 148 | ||
| 147 | type = __nf_tables_chain_type_lookup(afi->family, nla); | 149 | type = __nf_tables_chain_type_lookup(afi->family, nla); |
| 150 | if (type != NULL) | ||
| 151 | return type; | ||
| 148 | #ifdef CONFIG_MODULES | 152 | #ifdef CONFIG_MODULES |
| 149 | if (type < 0 && autoload) { | 153 | if (autoload) { |
| 150 | nfnl_unlock(NFNL_SUBSYS_NFTABLES); | 154 | nfnl_unlock(NFNL_SUBSYS_NFTABLES); |
| 151 | request_module("nft-chain-%u-%*.s", afi->family, | 155 | request_module("nft-chain-%u-%*.s", afi->family, |
| 152 | nla_len(nla)-1, (const char *)nla_data(nla)); | 156 | nla_len(nla)-1, (const char *)nla_data(nla)); |
| 153 | nfnl_lock(NFNL_SUBSYS_NFTABLES); | 157 | nfnl_lock(NFNL_SUBSYS_NFTABLES); |
| 154 | type = __nf_tables_chain_type_lookup(afi->family, nla); | 158 | type = __nf_tables_chain_type_lookup(afi->family, nla); |
| 159 | if (type != NULL) | ||
| 160 | return ERR_PTR(-EAGAIN); | ||
| 155 | } | 161 | } |
| 156 | #endif | 162 | #endif |
| 157 | return type; | 163 | return ERR_PTR(-ENOENT); |
| 158 | } | 164 | } |
| 159 | 165 | ||
| 160 | static const struct nla_policy nft_table_policy[NFTA_TABLE_MAX + 1] = { | 166 | static const struct nla_policy nft_table_policy[NFTA_TABLE_MAX + 1] = { |
| @@ -307,7 +313,8 @@ err: | |||
| 307 | return err; | 313 | return err; |
| 308 | } | 314 | } |
| 309 | 315 | ||
| 310 | static int nf_tables_table_enable(struct nft_table *table) | 316 | static int nf_tables_table_enable(const struct nft_af_info *afi, |
| 317 | struct nft_table *table) | ||
| 311 | { | 318 | { |
| 312 | struct nft_chain *chain; | 319 | struct nft_chain *chain; |
| 313 | int err, i = 0; | 320 | int err, i = 0; |
| @@ -316,7 +323,7 @@ static int nf_tables_table_enable(struct nft_table *table) | |||
| 316 | if (!(chain->flags & NFT_BASE_CHAIN)) | 323 | if (!(chain->flags & NFT_BASE_CHAIN)) |
| 317 | continue; | 324 | continue; |
| 318 | 325 | ||
| 319 | err = nf_register_hook(&nft_base_chain(chain)->ops); | 326 | err = nf_register_hooks(nft_base_chain(chain)->ops, afi->nops); |
| 320 | if (err < 0) | 327 | if (err < 0) |
| 321 | goto err; | 328 | goto err; |
| 322 | 329 | ||
| @@ -331,18 +338,20 @@ err: | |||
| 331 | if (i-- <= 0) | 338 | if (i-- <= 0) |
| 332 | break; | 339 | break; |
| 333 | 340 | ||
| 334 | nf_unregister_hook(&nft_base_chain(chain)->ops); | 341 | nf_unregister_hooks(nft_base_chain(chain)->ops, afi->nops); |
| 335 | } | 342 | } |
| 336 | return err; | 343 | return err; |
| 337 | } | 344 | } |
| 338 | 345 | ||
| 339 | static int nf_tables_table_disable(struct nft_table *table) | 346 | static int nf_tables_table_disable(const struct nft_af_info *afi, |
| 347 | struct nft_table *table) | ||
| 340 | { | 348 | { |
| 341 | struct nft_chain *chain; | 349 | struct nft_chain *chain; |
| 342 | 350 | ||
| 343 | list_for_each_entry(chain, &table->chains, list) { | 351 | list_for_each_entry(chain, &table->chains, list) { |
| 344 | if (chain->flags & NFT_BASE_CHAIN) | 352 | if (chain->flags & NFT_BASE_CHAIN) |
| 345 | nf_unregister_hook(&nft_base_chain(chain)->ops); | 353 | nf_unregister_hooks(nft_base_chain(chain)->ops, |
| 354 | afi->nops); | ||
| 346 | } | 355 | } |
| 347 | 356 | ||
| 348 | return 0; | 357 | return 0; |
| @@ -357,7 +366,7 @@ static int nf_tables_updtable(struct sock *nlsk, struct sk_buff *skb, | |||
| 357 | int family = nfmsg->nfgen_family, ret = 0; | 366 | int family = nfmsg->nfgen_family, ret = 0; |
| 358 | 367 | ||
| 359 | if (nla[NFTA_TABLE_FLAGS]) { | 368 | if (nla[NFTA_TABLE_FLAGS]) { |
| 360 | __be32 flags; | 369 | u32 flags; |
| 361 | 370 | ||
| 362 | flags = ntohl(nla_get_be32(nla[NFTA_TABLE_FLAGS])); | 371 | flags = ntohl(nla_get_be32(nla[NFTA_TABLE_FLAGS])); |
| 363 | if (flags & ~NFT_TABLE_F_DORMANT) | 372 | if (flags & ~NFT_TABLE_F_DORMANT) |
| @@ -365,12 +374,12 @@ static int nf_tables_updtable(struct sock *nlsk, struct sk_buff *skb, | |||
| 365 | 374 | ||
| 366 | if ((flags & NFT_TABLE_F_DORMANT) && | 375 | if ((flags & NFT_TABLE_F_DORMANT) && |
| 367 | !(table->flags & NFT_TABLE_F_DORMANT)) { | 376 | !(table->flags & NFT_TABLE_F_DORMANT)) { |
| 368 | ret = nf_tables_table_disable(table); | 377 | ret = nf_tables_table_disable(afi, table); |
| 369 | if (ret >= 0) | 378 | if (ret >= 0) |
| 370 | table->flags |= NFT_TABLE_F_DORMANT; | 379 | table->flags |= NFT_TABLE_F_DORMANT; |
| 371 | } else if (!(flags & NFT_TABLE_F_DORMANT) && | 380 | } else if (!(flags & NFT_TABLE_F_DORMANT) && |
| 372 | table->flags & NFT_TABLE_F_DORMANT) { | 381 | table->flags & NFT_TABLE_F_DORMANT) { |
| 373 | ret = nf_tables_table_enable(table); | 382 | ret = nf_tables_table_enable(afi, table); |
| 374 | if (ret >= 0) | 383 | if (ret >= 0) |
| 375 | table->flags &= ~NFT_TABLE_F_DORMANT; | 384 | table->flags &= ~NFT_TABLE_F_DORMANT; |
| 376 | } | 385 | } |
| @@ -393,6 +402,7 @@ static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb, | |||
| 393 | struct nft_table *table; | 402 | struct nft_table *table; |
| 394 | struct net *net = sock_net(skb->sk); | 403 | struct net *net = sock_net(skb->sk); |
| 395 | int family = nfmsg->nfgen_family; | 404 | int family = nfmsg->nfgen_family; |
| 405 | u32 flags = 0; | ||
| 396 | 406 | ||
| 397 | afi = nf_tables_afinfo_lookup(net, family, true); | 407 | afi = nf_tables_afinfo_lookup(net, family, true); |
| 398 | if (IS_ERR(afi)) | 408 | if (IS_ERR(afi)) |
| @@ -414,25 +424,25 @@ static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb, | |||
| 414 | return nf_tables_updtable(nlsk, skb, nlh, nla, afi, table); | 424 | return nf_tables_updtable(nlsk, skb, nlh, nla, afi, table); |
| 415 | } | 425 | } |
| 416 | 426 | ||
| 427 | if (nla[NFTA_TABLE_FLAGS]) { | ||
| 428 | flags = ntohl(nla_get_be32(nla[NFTA_TABLE_FLAGS])); | ||
| 429 | if (flags & ~NFT_TABLE_F_DORMANT) | ||
| 430 | return -EINVAL; | ||
| 431 | } | ||
| 432 | |||
| 433 | if (!try_module_get(afi->owner)) | ||
| 434 | return -EAFNOSUPPORT; | ||
| 435 | |||
| 417 | table = kzalloc(sizeof(*table) + nla_len(name), GFP_KERNEL); | 436 | table = kzalloc(sizeof(*table) + nla_len(name), GFP_KERNEL); |
| 418 | if (table == NULL) | 437 | if (table == NULL) { |
| 438 | module_put(afi->owner); | ||
| 419 | return -ENOMEM; | 439 | return -ENOMEM; |
| 440 | } | ||
| 420 | 441 | ||
| 421 | nla_strlcpy(table->name, name, nla_len(name)); | 442 | nla_strlcpy(table->name, name, nla_len(name)); |
| 422 | INIT_LIST_HEAD(&table->chains); | 443 | INIT_LIST_HEAD(&table->chains); |
| 423 | INIT_LIST_HEAD(&table->sets); | 444 | INIT_LIST_HEAD(&table->sets); |
| 424 | 445 | table->flags = flags; | |
| 425 | if (nla[NFTA_TABLE_FLAGS]) { | ||
| 426 | __be32 flags; | ||
| 427 | |||
| 428 | flags = ntohl(nla_get_be32(nla[NFTA_TABLE_FLAGS])); | ||
| 429 | if (flags & ~NFT_TABLE_F_DORMANT) { | ||
| 430 | kfree(table); | ||
| 431 | return -EINVAL; | ||
| 432 | } | ||
| 433 | |||
| 434 | table->flags |= flags; | ||
| 435 | } | ||
| 436 | 446 | ||
| 437 | list_add_tail(&table->list, &afi->tables); | 447 | list_add_tail(&table->list, &afi->tables); |
| 438 | nf_tables_table_notify(skb, nlh, table, NFT_MSG_NEWTABLE, family); | 448 | nf_tables_table_notify(skb, nlh, table, NFT_MSG_NEWTABLE, family); |
| @@ -457,16 +467,17 @@ static int nf_tables_deltable(struct sock *nlsk, struct sk_buff *skb, | |||
| 457 | if (IS_ERR(table)) | 467 | if (IS_ERR(table)) |
| 458 | return PTR_ERR(table); | 468 | return PTR_ERR(table); |
| 459 | 469 | ||
| 460 | if (table->use) | 470 | if (!list_empty(&table->chains) || !list_empty(&table->sets)) |
| 461 | return -EBUSY; | 471 | return -EBUSY; |
| 462 | 472 | ||
| 463 | list_del(&table->list); | 473 | list_del(&table->list); |
| 464 | nf_tables_table_notify(skb, nlh, table, NFT_MSG_DELTABLE, family); | 474 | nf_tables_table_notify(skb, nlh, table, NFT_MSG_DELTABLE, family); |
| 465 | kfree(table); | 475 | kfree(table); |
| 476 | module_put(afi->owner); | ||
| 466 | return 0; | 477 | return 0; |
| 467 | } | 478 | } |
| 468 | 479 | ||
| 469 | int nft_register_chain_type(struct nf_chain_type *ctype) | 480 | int nft_register_chain_type(const struct nf_chain_type *ctype) |
| 470 | { | 481 | { |
| 471 | int err = 0; | 482 | int err = 0; |
| 472 | 483 | ||
| @@ -475,10 +486,6 @@ int nft_register_chain_type(struct nf_chain_type *ctype) | |||
| 475 | err = -EBUSY; | 486 | err = -EBUSY; |
| 476 | goto out; | 487 | goto out; |
| 477 | } | 488 | } |
| 478 | |||
| 479 | if (!try_module_get(ctype->me)) | ||
| 480 | goto out; | ||
| 481 | |||
| 482 | chain_type[ctype->family][ctype->type] = ctype; | 489 | chain_type[ctype->family][ctype->type] = ctype; |
| 483 | out: | 490 | out: |
| 484 | nfnl_unlock(NFNL_SUBSYS_NFTABLES); | 491 | nfnl_unlock(NFNL_SUBSYS_NFTABLES); |
| @@ -486,11 +493,10 @@ out: | |||
| 486 | } | 493 | } |
| 487 | EXPORT_SYMBOL_GPL(nft_register_chain_type); | 494 | EXPORT_SYMBOL_GPL(nft_register_chain_type); |
| 488 | 495 | ||
| 489 | void nft_unregister_chain_type(struct nf_chain_type *ctype) | 496 | void nft_unregister_chain_type(const struct nf_chain_type *ctype) |
| 490 | { | 497 | { |
| 491 | nfnl_lock(NFNL_SUBSYS_NFTABLES); | 498 | nfnl_lock(NFNL_SUBSYS_NFTABLES); |
| 492 | chain_type[ctype->family][ctype->type] = NULL; | 499 | chain_type[ctype->family][ctype->type] = NULL; |
| 493 | module_put(ctype->me); | ||
| 494 | nfnl_unlock(NFNL_SUBSYS_NFTABLES); | 500 | nfnl_unlock(NFNL_SUBSYS_NFTABLES); |
| 495 | } | 501 | } |
| 496 | EXPORT_SYMBOL_GPL(nft_unregister_chain_type); | 502 | EXPORT_SYMBOL_GPL(nft_unregister_chain_type); |
| @@ -598,7 +604,7 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, u32 portid, u32 seq, | |||
| 598 | 604 | ||
| 599 | if (chain->flags & NFT_BASE_CHAIN) { | 605 | if (chain->flags & NFT_BASE_CHAIN) { |
| 600 | const struct nft_base_chain *basechain = nft_base_chain(chain); | 606 | const struct nft_base_chain *basechain = nft_base_chain(chain); |
| 601 | const struct nf_hook_ops *ops = &basechain->ops; | 607 | const struct nf_hook_ops *ops = &basechain->ops[0]; |
| 602 | struct nlattr *nest; | 608 | struct nlattr *nest; |
| 603 | 609 | ||
| 604 | nest = nla_nest_start(skb, NFTA_CHAIN_HOOK); | 610 | nest = nla_nest_start(skb, NFTA_CHAIN_HOOK); |
| @@ -614,9 +620,8 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, u32 portid, u32 seq, | |||
| 614 | htonl(basechain->policy))) | 620 | htonl(basechain->policy))) |
| 615 | goto nla_put_failure; | 621 | goto nla_put_failure; |
| 616 | 622 | ||
| 617 | if (nla_put_string(skb, NFTA_CHAIN_TYPE, | 623 | if (nla_put_string(skb, NFTA_CHAIN_TYPE, basechain->type->name)) |
| 618 | chain_type[ops->pf][nft_base_chain(chain)->type]->name)) | 624 | goto nla_put_failure; |
| 619 | goto nla_put_failure; | ||
| 620 | 625 | ||
| 621 | if (nft_dump_stats(skb, nft_base_chain(chain)->stats)) | 626 | if (nft_dump_stats(skb, nft_base_chain(chain)->stats)) |
| 622 | goto nla_put_failure; | 627 | goto nla_put_failure; |
| @@ -757,22 +762,6 @@ err: | |||
| 757 | return err; | 762 | return err; |
| 758 | } | 763 | } |
| 759 | 764 | ||
| 760 | static int | ||
| 761 | nf_tables_chain_policy(struct nft_base_chain *chain, const struct nlattr *attr) | ||
| 762 | { | ||
| 763 | switch (ntohl(nla_get_be32(attr))) { | ||
| 764 | case NF_DROP: | ||
| 765 | chain->policy = NF_DROP; | ||
| 766 | break; | ||
| 767 | case NF_ACCEPT: | ||
| 768 | chain->policy = NF_ACCEPT; | ||
| 769 | break; | ||
| 770 | default: | ||
| 771 | return -EINVAL; | ||
| 772 | } | ||
| 773 | return 0; | ||
| 774 | } | ||
| 775 | |||
| 776 | static const struct nla_policy nft_counter_policy[NFTA_COUNTER_MAX + 1] = { | 765 | static const struct nla_policy nft_counter_policy[NFTA_COUNTER_MAX + 1] = { |
| 777 | [NFTA_COUNTER_PACKETS] = { .type = NLA_U64 }, | 766 | [NFTA_COUNTER_PACKETS] = { .type = NLA_U64 }, |
| 778 | [NFTA_COUNTER_BYTES] = { .type = NLA_U64 }, | 767 | [NFTA_COUNTER_BYTES] = { .type = NLA_U64 }, |
| @@ -831,7 +820,9 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, | |||
| 831 | struct nlattr *ha[NFTA_HOOK_MAX + 1]; | 820 | struct nlattr *ha[NFTA_HOOK_MAX + 1]; |
| 832 | struct net *net = sock_net(skb->sk); | 821 | struct net *net = sock_net(skb->sk); |
| 833 | int family = nfmsg->nfgen_family; | 822 | int family = nfmsg->nfgen_family; |
| 823 | u8 policy = NF_ACCEPT; | ||
| 834 | u64 handle = 0; | 824 | u64 handle = 0; |
| 825 | unsigned int i; | ||
| 835 | int err; | 826 | int err; |
| 836 | bool create; | 827 | bool create; |
| 837 | 828 | ||
| @@ -845,9 +836,6 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, | |||
| 845 | if (IS_ERR(table)) | 836 | if (IS_ERR(table)) |
| 846 | return PTR_ERR(table); | 837 | return PTR_ERR(table); |
| 847 | 838 | ||
| 848 | if (table->use == UINT_MAX) | ||
| 849 | return -EOVERFLOW; | ||
| 850 | |||
| 851 | chain = NULL; | 839 | chain = NULL; |
| 852 | name = nla[NFTA_CHAIN_NAME]; | 840 | name = nla[NFTA_CHAIN_NAME]; |
| 853 | 841 | ||
| @@ -865,6 +853,22 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, | |||
| 865 | } | 853 | } |
| 866 | } | 854 | } |
| 867 | 855 | ||
| 856 | if (nla[NFTA_CHAIN_POLICY]) { | ||
| 857 | if ((chain != NULL && | ||
| 858 | !(chain->flags & NFT_BASE_CHAIN)) || | ||
| 859 | nla[NFTA_CHAIN_HOOK] == NULL) | ||
| 860 | return -EOPNOTSUPP; | ||
| 861 | |||
| 862 | policy = nla_get_be32(nla[NFTA_CHAIN_POLICY]); | ||
| 863 | switch (policy) { | ||
| 864 | case NF_DROP: | ||
| 865 | case NF_ACCEPT: | ||
| 866 | break; | ||
| 867 | default: | ||
| 868 | return -EINVAL; | ||
| 869 | } | ||
| 870 | } | ||
| 871 | |||
| 868 | if (chain != NULL) { | 872 | if (chain != NULL) { |
| 869 | if (nlh->nlmsg_flags & NLM_F_EXCL) | 873 | if (nlh->nlmsg_flags & NLM_F_EXCL) |
| 870 | return -EEXIST; | 874 | return -EEXIST; |
| @@ -875,16 +879,6 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, | |||
| 875 | !IS_ERR(nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME]))) | 879 | !IS_ERR(nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME]))) |
| 876 | return -EEXIST; | 880 | return -EEXIST; |
| 877 | 881 | ||
| 878 | if (nla[NFTA_CHAIN_POLICY]) { | ||
| 879 | if (!(chain->flags & NFT_BASE_CHAIN)) | ||
| 880 | return -EOPNOTSUPP; | ||
| 881 | |||
| 882 | err = nf_tables_chain_policy(nft_base_chain(chain), | ||
| 883 | nla[NFTA_CHAIN_POLICY]); | ||
| 884 | if (err < 0) | ||
| 885 | return err; | ||
| 886 | } | ||
| 887 | |||
| 888 | if (nla[NFTA_CHAIN_COUNTERS]) { | 882 | if (nla[NFTA_CHAIN_COUNTERS]) { |
| 889 | if (!(chain->flags & NFT_BASE_CHAIN)) | 883 | if (!(chain->flags & NFT_BASE_CHAIN)) |
| 890 | return -EOPNOTSUPP; | 884 | return -EOPNOTSUPP; |
| @@ -895,24 +889,31 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, | |||
| 895 | return err; | 889 | return err; |
| 896 | } | 890 | } |
| 897 | 891 | ||
| 892 | if (nla[NFTA_CHAIN_POLICY]) | ||
| 893 | nft_base_chain(chain)->policy = policy; | ||
| 894 | |||
| 898 | if (nla[NFTA_CHAIN_HANDLE] && name) | 895 | if (nla[NFTA_CHAIN_HANDLE] && name) |
| 899 | nla_strlcpy(chain->name, name, NFT_CHAIN_MAXNAMELEN); | 896 | nla_strlcpy(chain->name, name, NFT_CHAIN_MAXNAMELEN); |
| 900 | 897 | ||
| 901 | goto notify; | 898 | goto notify; |
| 902 | } | 899 | } |
| 903 | 900 | ||
| 901 | if (table->use == UINT_MAX) | ||
| 902 | return -EOVERFLOW; | ||
| 903 | |||
| 904 | if (nla[NFTA_CHAIN_HOOK]) { | 904 | if (nla[NFTA_CHAIN_HOOK]) { |
| 905 | const struct nf_chain_type *type; | ||
| 905 | struct nf_hook_ops *ops; | 906 | struct nf_hook_ops *ops; |
| 906 | nf_hookfn *hookfn; | 907 | nf_hookfn *hookfn; |
| 907 | u32 hooknum; | 908 | u32 hooknum, priority; |
| 908 | int type = NFT_CHAIN_T_DEFAULT; | ||
| 909 | 909 | ||
| 910 | type = chain_type[family][NFT_CHAIN_T_DEFAULT]; | ||
| 910 | if (nla[NFTA_CHAIN_TYPE]) { | 911 | if (nla[NFTA_CHAIN_TYPE]) { |
| 911 | type = nf_tables_chain_type_lookup(afi, | 912 | type = nf_tables_chain_type_lookup(afi, |
| 912 | nla[NFTA_CHAIN_TYPE], | 913 | nla[NFTA_CHAIN_TYPE], |
| 913 | create); | 914 | create); |
| 914 | if (type < 0) | 915 | if (IS_ERR(type)) |
| 915 | return -ENOENT; | 916 | return PTR_ERR(type); |
| 916 | } | 917 | } |
| 917 | 918 | ||
| 918 | err = nla_parse_nested(ha, NFTA_HOOK_MAX, nla[NFTA_CHAIN_HOOK], | 919 | err = nla_parse_nested(ha, NFTA_HOOK_MAX, nla[NFTA_CHAIN_HOOK], |
| @@ -926,46 +927,23 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, | |||
| 926 | hooknum = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM])); | 927 | hooknum = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM])); |
| 927 | if (hooknum >= afi->nhooks) | 928 | if (hooknum >= afi->nhooks) |
| 928 | return -EINVAL; | 929 | return -EINVAL; |
| 930 | priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY])); | ||
| 929 | 931 | ||
| 930 | hookfn = chain_type[family][type]->fn[hooknum]; | 932 | if (!(type->hook_mask & (1 << hooknum))) |
| 931 | if (hookfn == NULL) | ||
| 932 | return -EOPNOTSUPP; | 933 | return -EOPNOTSUPP; |
| 934 | if (!try_module_get(type->owner)) | ||
| 935 | return -ENOENT; | ||
| 936 | hookfn = type->hooks[hooknum]; | ||
| 933 | 937 | ||
| 934 | basechain = kzalloc(sizeof(*basechain), GFP_KERNEL); | 938 | basechain = kzalloc(sizeof(*basechain), GFP_KERNEL); |
| 935 | if (basechain == NULL) | 939 | if (basechain == NULL) |
| 936 | return -ENOMEM; | 940 | return -ENOMEM; |
| 937 | 941 | ||
| 938 | basechain->type = type; | ||
| 939 | chain = &basechain->chain; | ||
| 940 | |||
| 941 | ops = &basechain->ops; | ||
| 942 | ops->pf = family; | ||
| 943 | ops->owner = afi->owner; | ||
| 944 | ops->hooknum = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM])); | ||
| 945 | ops->priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY])); | ||
| 946 | ops->priv = chain; | ||
| 947 | ops->hook = hookfn; | ||
| 948 | if (afi->hooks[ops->hooknum]) | ||
| 949 | ops->hook = afi->hooks[ops->hooknum]; | ||
| 950 | |||
| 951 | chain->flags |= NFT_BASE_CHAIN; | ||
| 952 | |||
| 953 | if (nla[NFTA_CHAIN_POLICY]) { | ||
| 954 | err = nf_tables_chain_policy(basechain, | ||
| 955 | nla[NFTA_CHAIN_POLICY]); | ||
| 956 | if (err < 0) { | ||
| 957 | free_percpu(basechain->stats); | ||
| 958 | kfree(basechain); | ||
| 959 | return err; | ||
| 960 | } | ||
| 961 | } else | ||
| 962 | basechain->policy = NF_ACCEPT; | ||
| 963 | |||
| 964 | if (nla[NFTA_CHAIN_COUNTERS]) { | 942 | if (nla[NFTA_CHAIN_COUNTERS]) { |
| 965 | err = nf_tables_counters(basechain, | 943 | err = nf_tables_counters(basechain, |
| 966 | nla[NFTA_CHAIN_COUNTERS]); | 944 | nla[NFTA_CHAIN_COUNTERS]); |
| 967 | if (err < 0) { | 945 | if (err < 0) { |
| 968 | free_percpu(basechain->stats); | 946 | module_put(type->owner); |
| 969 | kfree(basechain); | 947 | kfree(basechain); |
| 970 | return err; | 948 | return err; |
| 971 | } | 949 | } |
| @@ -973,12 +951,33 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, | |||
| 973 | struct nft_stats __percpu *newstats; | 951 | struct nft_stats __percpu *newstats; |
| 974 | 952 | ||
| 975 | newstats = alloc_percpu(struct nft_stats); | 953 | newstats = alloc_percpu(struct nft_stats); |
| 976 | if (newstats == NULL) | 954 | if (newstats == NULL) { |
| 955 | module_put(type->owner); | ||
| 956 | kfree(basechain); | ||
| 977 | return -ENOMEM; | 957 | return -ENOMEM; |
| 958 | } | ||
| 959 | rcu_assign_pointer(basechain->stats, newstats); | ||
| 960 | } | ||
| 978 | 961 | ||
| 979 | rcu_assign_pointer(nft_base_chain(chain)->stats, | 962 | basechain->type = type; |
| 980 | newstats); | 963 | chain = &basechain->chain; |
| 964 | |||
| 965 | for (i = 0; i < afi->nops; i++) { | ||
| 966 | ops = &basechain->ops[i]; | ||
| 967 | ops->pf = family; | ||
| 968 | ops->owner = afi->owner; | ||
| 969 | ops->hooknum = hooknum; | ||
| 970 | ops->priority = priority; | ||
| 971 | ops->priv = chain; | ||
| 972 | ops->hook = afi->hooks[ops->hooknum]; | ||
| 973 | if (hookfn) | ||
| 974 | ops->hook = hookfn; | ||
| 975 | if (afi->hook_ops_init) | ||
| 976 | afi->hook_ops_init(ops, i); | ||
| 981 | } | 977 | } |
| 978 | |||
| 979 | chain->flags |= NFT_BASE_CHAIN; | ||
| 980 | basechain->policy = policy; | ||
| 982 | } else { | 981 | } else { |
| 983 | chain = kzalloc(sizeof(*chain), GFP_KERNEL); | 982 | chain = kzalloc(sizeof(*chain), GFP_KERNEL); |
| 984 | if (chain == NULL) | 983 | if (chain == NULL) |
| @@ -993,8 +992,9 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, | |||
| 993 | 992 | ||
| 994 | if (!(table->flags & NFT_TABLE_F_DORMANT) && | 993 | if (!(table->flags & NFT_TABLE_F_DORMANT) && |
| 995 | chain->flags & NFT_BASE_CHAIN) { | 994 | chain->flags & NFT_BASE_CHAIN) { |
| 996 | err = nf_register_hook(&nft_base_chain(chain)->ops); | 995 | err = nf_register_hooks(nft_base_chain(chain)->ops, afi->nops); |
| 997 | if (err < 0) { | 996 | if (err < 0) { |
| 997 | module_put(basechain->type->owner); | ||
| 998 | free_percpu(basechain->stats); | 998 | free_percpu(basechain->stats); |
| 999 | kfree(basechain); | 999 | kfree(basechain); |
| 1000 | return err; | 1000 | return err; |
| @@ -1015,6 +1015,7 @@ static void nf_tables_rcu_chain_destroy(struct rcu_head *head) | |||
| 1015 | BUG_ON(chain->use > 0); | 1015 | BUG_ON(chain->use > 0); |
| 1016 | 1016 | ||
| 1017 | if (chain->flags & NFT_BASE_CHAIN) { | 1017 | if (chain->flags & NFT_BASE_CHAIN) { |
| 1018 | module_put(nft_base_chain(chain)->type->owner); | ||
| 1018 | free_percpu(nft_base_chain(chain)->stats); | 1019 | free_percpu(nft_base_chain(chain)->stats); |
| 1019 | kfree(nft_base_chain(chain)); | 1020 | kfree(nft_base_chain(chain)); |
| 1020 | } else | 1021 | } else |
| @@ -1052,7 +1053,7 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb, | |||
| 1052 | 1053 | ||
| 1053 | if (!(table->flags & NFT_TABLE_F_DORMANT) && | 1054 | if (!(table->flags & NFT_TABLE_F_DORMANT) && |
| 1054 | chain->flags & NFT_BASE_CHAIN) | 1055 | chain->flags & NFT_BASE_CHAIN) |
| 1055 | nf_unregister_hook(&nft_base_chain(chain)->ops); | 1056 | nf_unregister_hooks(nft_base_chain(chain)->ops, afi->nops); |
| 1056 | 1057 | ||
| 1057 | nf_tables_chain_notify(skb, nlh, table, chain, NFT_MSG_DELCHAIN, | 1058 | nf_tables_chain_notify(skb, nlh, table, chain, NFT_MSG_DELCHAIN, |
| 1058 | family); | 1059 | family); |
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index e8fcc343c2b9..0d879fcb8763 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c | |||
| @@ -109,14 +109,14 @@ static inline void nft_trace_packet(const struct nft_pktinfo *pkt, | |||
| 109 | { | 109 | { |
| 110 | struct net *net = dev_net(pkt->in ? pkt->in : pkt->out); | 110 | struct net *net = dev_net(pkt->in ? pkt->in : pkt->out); |
| 111 | 111 | ||
| 112 | nf_log_packet(net, pkt->xt.family, pkt->hooknum, pkt->skb, pkt->in, | 112 | nf_log_packet(net, pkt->xt.family, pkt->ops->hooknum, pkt->skb, pkt->in, |
| 113 | pkt->out, &trace_loginfo, "TRACE: %s:%s:%s:%u ", | 113 | pkt->out, &trace_loginfo, "TRACE: %s:%s:%s:%u ", |
| 114 | chain->table->name, chain->name, comments[type], | 114 | chain->table->name, chain->name, comments[type], |
| 115 | rulenum); | 115 | rulenum); |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | unsigned int | 118 | unsigned int |
| 119 | nft_do_chain_pktinfo(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops) | 119 | nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops) |
| 120 | { | 120 | { |
| 121 | const struct nft_chain *chain = ops->priv; | 121 | const struct nft_chain *chain = ops->priv; |
| 122 | const struct nft_rule *rule; | 122 | const struct nft_rule *rule; |
| @@ -216,7 +216,7 @@ next_rule: | |||
| 216 | 216 | ||
| 217 | return nft_base_chain(chain)->policy; | 217 | return nft_base_chain(chain)->policy; |
| 218 | } | 218 | } |
| 219 | EXPORT_SYMBOL_GPL(nft_do_chain_pktinfo); | 219 | EXPORT_SYMBOL_GPL(nft_do_chain); |
| 220 | 220 | ||
| 221 | int __init nf_tables_core_module_init(void) | 221 | int __init nf_tables_core_module_init(void) |
| 222 | { | 222 | { |
diff --git a/net/netfilter/nf_tables_inet.c b/net/netfilter/nf_tables_inet.c new file mode 100644 index 000000000000..9dd2d216cfc1 --- /dev/null +++ b/net/netfilter/nf_tables_inet.c | |||
| @@ -0,0 +1,104 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2012-2014 Patrick McHardy <kaber@trash.net> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/init.h> | ||
| 10 | #include <linux/module.h> | ||
| 11 | #include <linux/ip.h> | ||
| 12 | #include <linux/netfilter_ipv4.h> | ||
| 13 | #include <linux/netfilter_ipv6.h> | ||
| 14 | #include <net/netfilter/nf_tables.h> | ||
| 15 | #include <net/netfilter/nf_tables_ipv4.h> | ||
| 16 | #include <net/netfilter/nf_tables_ipv6.h> | ||
| 17 | #include <net/ip.h> | ||
| 18 | |||
| 19 | static void nft_inet_hook_ops_init(struct nf_hook_ops *ops, unsigned int n) | ||
| 20 | { | ||
| 21 | struct nft_af_info *afi; | ||
| 22 | |||
| 23 | if (n == 1) | ||
| 24 | afi = &nft_af_ipv4; | ||
| 25 | else | ||
| 26 | afi = &nft_af_ipv6; | ||
| 27 | |||
| 28 | ops->pf = afi->family; | ||
| 29 | if (afi->hooks[ops->hooknum]) | ||
| 30 | ops->hook = afi->hooks[ops->hooknum]; | ||
| 31 | } | ||
| 32 | |||
| 33 | static struct nft_af_info nft_af_inet __read_mostly = { | ||
| 34 | .family = NFPROTO_INET, | ||
| 35 | .nhooks = NF_INET_NUMHOOKS, | ||
| 36 | .owner = THIS_MODULE, | ||
| 37 | .nops = 2, | ||
| 38 | .hook_ops_init = nft_inet_hook_ops_init, | ||
| 39 | }; | ||
| 40 | |||
| 41 | static int __net_init nf_tables_inet_init_net(struct net *net) | ||
| 42 | { | ||
| 43 | net->nft.inet = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL); | ||
| 44 | if (net->nft.inet == NULL) | ||
| 45 | return -ENOMEM; | ||
| 46 | memcpy(net->nft.inet, &nft_af_inet, sizeof(nft_af_inet)); | ||
| 47 | |||
| 48 | if (nft_register_afinfo(net, net->nft.inet) < 0) | ||
| 49 | goto err; | ||
| 50 | |||
| 51 | return 0; | ||
| 52 | |||
| 53 | err: | ||
| 54 | kfree(net->nft.inet); | ||
| 55 | return -ENOMEM; | ||
| 56 | } | ||
| 57 | |||
| 58 | static void __net_exit nf_tables_inet_exit_net(struct net *net) | ||
| 59 | { | ||
| 60 | nft_unregister_afinfo(net->nft.inet); | ||
| 61 | kfree(net->nft.inet); | ||
| 62 | } | ||
| 63 | |||
| 64 | static struct pernet_operations nf_tables_inet_net_ops = { | ||
| 65 | .init = nf_tables_inet_init_net, | ||
| 66 | .exit = nf_tables_inet_exit_net, | ||
| 67 | }; | ||
| 68 | |||
| 69 | static const struct nf_chain_type filter_inet = { | ||
| 70 | .name = "filter", | ||
| 71 | .type = NFT_CHAIN_T_DEFAULT, | ||
| 72 | .family = NFPROTO_INET, | ||
| 73 | .owner = THIS_MODULE, | ||
| 74 | .hook_mask = (1 << NF_INET_LOCAL_IN) | | ||
| 75 | (1 << NF_INET_LOCAL_OUT) | | ||
| 76 | (1 << NF_INET_FORWARD) | | ||
| 77 | (1 << NF_INET_PRE_ROUTING) | | ||
| 78 | (1 << NF_INET_POST_ROUTING), | ||
| 79 | }; | ||
| 80 | |||
| 81 | static int __init nf_tables_inet_init(void) | ||
| 82 | { | ||
| 83 | int ret; | ||
| 84 | |||
| 85 | nft_register_chain_type(&filter_inet); | ||
| 86 | ret = register_pernet_subsys(&nf_tables_inet_net_ops); | ||
| 87 | if (ret < 0) | ||
| 88 | nft_unregister_chain_type(&filter_inet); | ||
| 89 | |||
| 90 | return ret; | ||
| 91 | } | ||
| 92 | |||
| 93 | static void __exit nf_tables_inet_exit(void) | ||
| 94 | { | ||
| 95 | unregister_pernet_subsys(&nf_tables_inet_net_ops); | ||
| 96 | nft_unregister_chain_type(&filter_inet); | ||
| 97 | } | ||
| 98 | |||
| 99 | module_init(nf_tables_inet_init); | ||
| 100 | module_exit(nf_tables_inet_exit); | ||
| 101 | |||
| 102 | MODULE_LICENSE("GPL"); | ||
| 103 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
| 104 | MODULE_ALIAS_NFT_FAMILY(1); | ||
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index d292c8d286eb..a155d19a225e 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
| @@ -28,6 +28,8 @@ | |||
| 28 | #include <linux/proc_fs.h> | 28 | #include <linux/proc_fs.h> |
| 29 | #include <linux/security.h> | 29 | #include <linux/security.h> |
| 30 | #include <linux/list.h> | 30 | #include <linux/list.h> |
| 31 | #include <linux/jhash.h> | ||
| 32 | #include <linux/random.h> | ||
| 31 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
| 32 | #include <net/sock.h> | 34 | #include <net/sock.h> |
| 33 | #include <net/netfilter/nf_log.h> | 35 | #include <net/netfilter/nf_log.h> |
| @@ -73,6 +75,7 @@ struct nfulnl_instance { | |||
| 73 | }; | 75 | }; |
| 74 | 76 | ||
| 75 | #define INSTANCE_BUCKETS 16 | 77 | #define INSTANCE_BUCKETS 16 |
| 78 | static unsigned int hash_init; | ||
| 76 | 79 | ||
| 77 | static int nfnl_log_net_id __read_mostly; | 80 | static int nfnl_log_net_id __read_mostly; |
| 78 | 81 | ||
| @@ -1064,6 +1067,11 @@ static int __init nfnetlink_log_init(void) | |||
| 1064 | { | 1067 | { |
| 1065 | int status = -ENOMEM; | 1068 | int status = -ENOMEM; |
| 1066 | 1069 | ||
| 1070 | /* it's not really all that important to have a random value, so | ||
| 1071 | * we can do this from the init function, even if there hasn't | ||
| 1072 | * been that much entropy yet */ | ||
| 1073 | get_random_bytes(&hash_init, sizeof(hash_init)); | ||
| 1074 | |||
| 1067 | netlink_register_notifier(&nfulnl_rtnl_notifier); | 1075 | netlink_register_notifier(&nfulnl_rtnl_notifier); |
| 1068 | status = nfnetlink_subsys_register(&nfulnl_subsys); | 1076 | status = nfnetlink_subsys_register(&nfulnl_subsys); |
| 1069 | if (status < 0) { | 1077 | if (status < 0) { |
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c index da0c1f4ada12..82cb8236f8a1 100644 --- a/net/netfilter/nft_compat.c +++ b/net/netfilter/nft_compat.c | |||
| @@ -92,7 +92,7 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par, | |||
| 92 | if (ctx->chain->flags & NFT_BASE_CHAIN) { | 92 | if (ctx->chain->flags & NFT_BASE_CHAIN) { |
| 93 | const struct nft_base_chain *basechain = | 93 | const struct nft_base_chain *basechain = |
| 94 | nft_base_chain(ctx->chain); | 94 | nft_base_chain(ctx->chain); |
| 95 | const struct nf_hook_ops *ops = &basechain->ops; | 95 | const struct nf_hook_ops *ops = &basechain->ops[0]; |
| 96 | 96 | ||
| 97 | par->hook_mask = 1 << ops->hooknum; | 97 | par->hook_mask = 1 << ops->hooknum; |
| 98 | } | 98 | } |
| @@ -253,7 +253,7 @@ static int nft_target_validate(const struct nft_ctx *ctx, | |||
| 253 | if (ctx->chain->flags & NFT_BASE_CHAIN) { | 253 | if (ctx->chain->flags & NFT_BASE_CHAIN) { |
| 254 | const struct nft_base_chain *basechain = | 254 | const struct nft_base_chain *basechain = |
| 255 | nft_base_chain(ctx->chain); | 255 | nft_base_chain(ctx->chain); |
| 256 | const struct nf_hook_ops *ops = &basechain->ops; | 256 | const struct nf_hook_ops *ops = &basechain->ops[0]; |
| 257 | 257 | ||
| 258 | hook_mask = 1 << ops->hooknum; | 258 | hook_mask = 1 << ops->hooknum; |
| 259 | if (hook_mask & target->hooks) | 259 | if (hook_mask & target->hooks) |
| @@ -323,7 +323,7 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx, | |||
| 323 | if (ctx->chain->flags & NFT_BASE_CHAIN) { | 323 | if (ctx->chain->flags & NFT_BASE_CHAIN) { |
| 324 | const struct nft_base_chain *basechain = | 324 | const struct nft_base_chain *basechain = |
| 325 | nft_base_chain(ctx->chain); | 325 | nft_base_chain(ctx->chain); |
| 326 | const struct nf_hook_ops *ops = &basechain->ops; | 326 | const struct nf_hook_ops *ops = &basechain->ops[0]; |
| 327 | 327 | ||
| 328 | par->hook_mask = 1 << ops->hooknum; | 328 | par->hook_mask = 1 << ops->hooknum; |
| 329 | } | 329 | } |
| @@ -449,7 +449,7 @@ static int nft_match_validate(const struct nft_ctx *ctx, | |||
| 449 | if (ctx->chain->flags & NFT_BASE_CHAIN) { | 449 | if (ctx->chain->flags & NFT_BASE_CHAIN) { |
| 450 | const struct nft_base_chain *basechain = | 450 | const struct nft_base_chain *basechain = |
| 451 | nft_base_chain(ctx->chain); | 451 | nft_base_chain(ctx->chain); |
| 452 | const struct nf_hook_ops *ops = &basechain->ops; | 452 | const struct nf_hook_ops *ops = &basechain->ops[0]; |
| 453 | 453 | ||
| 454 | hook_mask = 1 << ops->hooknum; | 454 | hook_mask = 1 << ops->hooknum; |
| 455 | if (hook_mask & match->hooks) | 455 | if (hook_mask & match->hooks) |
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c index 955f4e6e7089..c7c12858e113 100644 --- a/net/netfilter/nft_ct.c +++ b/net/netfilter/nft_ct.c | |||
| @@ -18,17 +18,21 @@ | |||
| 18 | #include <net/netfilter/nf_conntrack.h> | 18 | #include <net/netfilter/nf_conntrack.h> |
| 19 | #include <net/netfilter/nf_conntrack_tuple.h> | 19 | #include <net/netfilter/nf_conntrack_tuple.h> |
| 20 | #include <net/netfilter/nf_conntrack_helper.h> | 20 | #include <net/netfilter/nf_conntrack_helper.h> |
| 21 | #include <net/netfilter/nf_conntrack_ecache.h> | ||
| 21 | 22 | ||
| 22 | struct nft_ct { | 23 | struct nft_ct { |
| 23 | enum nft_ct_keys key:8; | 24 | enum nft_ct_keys key:8; |
| 24 | enum ip_conntrack_dir dir:8; | 25 | enum ip_conntrack_dir dir:8; |
| 25 | enum nft_registers dreg:8; | 26 | union{ |
| 27 | enum nft_registers dreg:8; | ||
| 28 | enum nft_registers sreg:8; | ||
| 29 | }; | ||
| 26 | uint8_t family; | 30 | uint8_t family; |
| 27 | }; | 31 | }; |
| 28 | 32 | ||
| 29 | static void nft_ct_eval(const struct nft_expr *expr, | 33 | static void nft_ct_get_eval(const struct nft_expr *expr, |
| 30 | struct nft_data data[NFT_REG_MAX + 1], | 34 | struct nft_data data[NFT_REG_MAX + 1], |
| 31 | const struct nft_pktinfo *pkt) | 35 | const struct nft_pktinfo *pkt) |
| 32 | { | 36 | { |
| 33 | const struct nft_ct *priv = nft_expr_priv(expr); | 37 | const struct nft_ct *priv = nft_expr_priv(expr); |
| 34 | struct nft_data *dest = &data[priv->dreg]; | 38 | struct nft_data *dest = &data[priv->dreg]; |
| @@ -123,24 +127,77 @@ err: | |||
| 123 | data[NFT_REG_VERDICT].verdict = NFT_BREAK; | 127 | data[NFT_REG_VERDICT].verdict = NFT_BREAK; |
| 124 | } | 128 | } |
| 125 | 129 | ||
| 130 | static void nft_ct_set_eval(const struct nft_expr *expr, | ||
| 131 | struct nft_data data[NFT_REG_MAX + 1], | ||
| 132 | const struct nft_pktinfo *pkt) | ||
| 133 | { | ||
| 134 | const struct nft_ct *priv = nft_expr_priv(expr); | ||
| 135 | struct sk_buff *skb = pkt->skb; | ||
| 136 | u32 value = data[priv->sreg].data[0]; | ||
| 137 | enum ip_conntrack_info ctinfo; | ||
| 138 | struct nf_conn *ct; | ||
| 139 | |||
| 140 | ct = nf_ct_get(skb, &ctinfo); | ||
| 141 | if (ct == NULL) | ||
| 142 | return; | ||
| 143 | |||
| 144 | switch (priv->key) { | ||
| 145 | #ifdef CONFIG_NF_CONNTRACK_MARK | ||
| 146 | case NFT_CT_MARK: | ||
| 147 | if (ct->mark != value) { | ||
| 148 | ct->mark = value; | ||
| 149 | nf_conntrack_event_cache(IPCT_MARK, ct); | ||
| 150 | } | ||
| 151 | break; | ||
| 152 | #endif | ||
| 153 | } | ||
| 154 | } | ||
| 155 | |||
| 126 | static const struct nla_policy nft_ct_policy[NFTA_CT_MAX + 1] = { | 156 | static const struct nla_policy nft_ct_policy[NFTA_CT_MAX + 1] = { |
| 127 | [NFTA_CT_DREG] = { .type = NLA_U32 }, | 157 | [NFTA_CT_DREG] = { .type = NLA_U32 }, |
| 128 | [NFTA_CT_KEY] = { .type = NLA_U32 }, | 158 | [NFTA_CT_KEY] = { .type = NLA_U32 }, |
| 129 | [NFTA_CT_DIRECTION] = { .type = NLA_U8 }, | 159 | [NFTA_CT_DIRECTION] = { .type = NLA_U8 }, |
| 160 | [NFTA_CT_SREG] = { .type = NLA_U32 }, | ||
| 130 | }; | 161 | }; |
| 131 | 162 | ||
| 132 | static int nft_ct_init(const struct nft_ctx *ctx, | 163 | static int nft_ct_l3proto_try_module_get(uint8_t family) |
| 133 | const struct nft_expr *expr, | ||
| 134 | const struct nlattr * const tb[]) | ||
| 135 | { | 164 | { |
| 136 | struct nft_ct *priv = nft_expr_priv(expr); | ||
| 137 | int err; | 165 | int err; |
| 138 | 166 | ||
| 139 | if (tb[NFTA_CT_DREG] == NULL || | 167 | if (family == NFPROTO_INET) { |
| 140 | tb[NFTA_CT_KEY] == NULL) | 168 | err = nf_ct_l3proto_try_module_get(NFPROTO_IPV4); |
| 141 | return -EINVAL; | 169 | if (err < 0) |
| 170 | goto err1; | ||
| 171 | err = nf_ct_l3proto_try_module_get(NFPROTO_IPV6); | ||
| 172 | if (err < 0) | ||
| 173 | goto err2; | ||
| 174 | } else { | ||
| 175 | err = nf_ct_l3proto_try_module_get(family); | ||
| 176 | if (err < 0) | ||
| 177 | goto err1; | ||
| 178 | } | ||
| 179 | return 0; | ||
| 180 | |||
| 181 | err2: | ||
| 182 | nf_ct_l3proto_module_put(NFPROTO_IPV4); | ||
| 183 | err1: | ||
| 184 | return err; | ||
| 185 | } | ||
| 186 | |||
| 187 | static void nft_ct_l3proto_module_put(uint8_t family) | ||
| 188 | { | ||
| 189 | if (family == NFPROTO_INET) { | ||
| 190 | nf_ct_l3proto_module_put(NFPROTO_IPV4); | ||
| 191 | nf_ct_l3proto_module_put(NFPROTO_IPV6); | ||
| 192 | } else | ||
| 193 | nf_ct_l3proto_module_put(family); | ||
| 194 | } | ||
| 195 | |||
| 196 | static int nft_ct_init_validate_get(const struct nft_expr *expr, | ||
| 197 | const struct nlattr * const tb[]) | ||
| 198 | { | ||
| 199 | struct nft_ct *priv = nft_expr_priv(expr); | ||
| 142 | 200 | ||
| 143 | priv->key = ntohl(nla_get_be32(tb[NFTA_CT_KEY])); | ||
| 144 | if (tb[NFTA_CT_DIRECTION] != NULL) { | 201 | if (tb[NFTA_CT_DIRECTION] != NULL) { |
| 145 | priv->dir = nla_get_u8(tb[NFTA_CT_DIRECTION]); | 202 | priv->dir = nla_get_u8(tb[NFTA_CT_DIRECTION]); |
| 146 | switch (priv->dir) { | 203 | switch (priv->dir) { |
| @@ -179,34 +236,72 @@ static int nft_ct_init(const struct nft_ctx *ctx, | |||
| 179 | return -EOPNOTSUPP; | 236 | return -EOPNOTSUPP; |
| 180 | } | 237 | } |
| 181 | 238 | ||
| 182 | err = nf_ct_l3proto_try_module_get(ctx->afi->family); | 239 | return 0; |
| 240 | } | ||
| 241 | |||
| 242 | static int nft_ct_init_validate_set(uint32_t key) | ||
| 243 | { | ||
| 244 | switch (key) { | ||
| 245 | case NFT_CT_MARK: | ||
| 246 | break; | ||
| 247 | default: | ||
| 248 | return -EOPNOTSUPP; | ||
| 249 | } | ||
| 250 | |||
| 251 | return 0; | ||
| 252 | } | ||
| 253 | |||
| 254 | static int nft_ct_init(const struct nft_ctx *ctx, | ||
| 255 | const struct nft_expr *expr, | ||
| 256 | const struct nlattr * const tb[]) | ||
| 257 | { | ||
| 258 | struct nft_ct *priv = nft_expr_priv(expr); | ||
| 259 | int err; | ||
| 260 | |||
| 261 | priv->key = ntohl(nla_get_be32(tb[NFTA_CT_KEY])); | ||
| 262 | |||
| 263 | if (tb[NFTA_CT_DREG]) { | ||
| 264 | err = nft_ct_init_validate_get(expr, tb); | ||
| 265 | if (err < 0) | ||
| 266 | return err; | ||
| 267 | |||
| 268 | priv->dreg = ntohl(nla_get_be32(tb[NFTA_CT_DREG])); | ||
| 269 | err = nft_validate_output_register(priv->dreg); | ||
| 270 | if (err < 0) | ||
| 271 | return err; | ||
| 272 | |||
| 273 | err = nft_validate_data_load(ctx, priv->dreg, NULL, | ||
| 274 | NFT_DATA_VALUE); | ||
| 275 | if (err < 0) | ||
| 276 | return err; | ||
| 277 | } else { | ||
| 278 | err = nft_ct_init_validate_set(priv->key); | ||
| 279 | if (err < 0) | ||
| 280 | return err; | ||
| 281 | |||
| 282 | priv->sreg = ntohl(nla_get_be32(tb[NFTA_CT_SREG])); | ||
| 283 | err = nft_validate_input_register(priv->sreg); | ||
| 284 | if (err < 0) | ||
| 285 | return err; | ||
| 286 | } | ||
| 287 | |||
| 288 | err = nft_ct_l3proto_try_module_get(ctx->afi->family); | ||
| 183 | if (err < 0) | 289 | if (err < 0) |
| 184 | return err; | 290 | return err; |
| 185 | priv->family = ctx->afi->family; | ||
| 186 | 291 | ||
| 187 | priv->dreg = ntohl(nla_get_be32(tb[NFTA_CT_DREG])); | 292 | priv->family = ctx->afi->family; |
| 188 | err = nft_validate_output_register(priv->dreg); | ||
| 189 | if (err < 0) | ||
| 190 | goto err1; | ||
| 191 | 293 | ||
| 192 | err = nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE); | ||
| 193 | if (err < 0) | ||
| 194 | goto err1; | ||
| 195 | return 0; | 294 | return 0; |
| 196 | |||
| 197 | err1: | ||
| 198 | nf_ct_l3proto_module_put(ctx->afi->family); | ||
| 199 | return err; | ||
| 200 | } | 295 | } |
| 201 | 296 | ||
| 202 | static void nft_ct_destroy(const struct nft_expr *expr) | 297 | static void nft_ct_destroy(const struct nft_expr *expr) |
| 203 | { | 298 | { |
| 204 | struct nft_ct *priv = nft_expr_priv(expr); | 299 | struct nft_ct *priv = nft_expr_priv(expr); |
| 205 | 300 | ||
| 206 | nf_ct_l3proto_module_put(priv->family); | 301 | nft_ct_l3proto_module_put(priv->family); |
| 207 | } | 302 | } |
| 208 | 303 | ||
| 209 | static int nft_ct_dump(struct sk_buff *skb, const struct nft_expr *expr) | 304 | static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr) |
| 210 | { | 305 | { |
| 211 | const struct nft_ct *priv = nft_expr_priv(expr); | 306 | const struct nft_ct *priv = nft_expr_priv(expr); |
| 212 | 307 | ||
| @@ -222,19 +317,61 @@ nla_put_failure: | |||
| 222 | return -1; | 317 | return -1; |
| 223 | } | 318 | } |
| 224 | 319 | ||
| 320 | static int nft_ct_set_dump(struct sk_buff *skb, const struct nft_expr *expr) | ||
| 321 | { | ||
| 322 | const struct nft_ct *priv = nft_expr_priv(expr); | ||
| 323 | |||
| 324 | if (nla_put_be32(skb, NFTA_CT_SREG, htonl(priv->sreg))) | ||
| 325 | goto nla_put_failure; | ||
| 326 | if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key))) | ||
| 327 | goto nla_put_failure; | ||
| 328 | return 0; | ||
| 329 | |||
| 330 | nla_put_failure: | ||
| 331 | return -1; | ||
| 332 | } | ||
| 333 | |||
| 225 | static struct nft_expr_type nft_ct_type; | 334 | static struct nft_expr_type nft_ct_type; |
| 226 | static const struct nft_expr_ops nft_ct_ops = { | 335 | static const struct nft_expr_ops nft_ct_get_ops = { |
| 227 | .type = &nft_ct_type, | 336 | .type = &nft_ct_type, |
| 228 | .size = NFT_EXPR_SIZE(sizeof(struct nft_ct)), | 337 | .size = NFT_EXPR_SIZE(sizeof(struct nft_ct)), |
| 229 | .eval = nft_ct_eval, | 338 | .eval = nft_ct_get_eval, |
| 230 | .init = nft_ct_init, | 339 | .init = nft_ct_init, |
| 231 | .destroy = nft_ct_destroy, | 340 | .destroy = nft_ct_destroy, |
| 232 | .dump = nft_ct_dump, | 341 | .dump = nft_ct_get_dump, |
| 233 | }; | 342 | }; |
| 234 | 343 | ||
| 344 | static const struct nft_expr_ops nft_ct_set_ops = { | ||
| 345 | .type = &nft_ct_type, | ||
| 346 | .size = NFT_EXPR_SIZE(sizeof(struct nft_ct)), | ||
| 347 | .eval = nft_ct_set_eval, | ||
| 348 | .init = nft_ct_init, | ||
| 349 | .destroy = nft_ct_destroy, | ||
| 350 | .dump = nft_ct_set_dump, | ||
| 351 | }; | ||
| 352 | |||
| 353 | static const struct nft_expr_ops * | ||
| 354 | nft_ct_select_ops(const struct nft_ctx *ctx, | ||
| 355 | const struct nlattr * const tb[]) | ||
| 356 | { | ||
| 357 | if (tb[NFTA_CT_KEY] == NULL) | ||
| 358 | return ERR_PTR(-EINVAL); | ||
| 359 | |||
| 360 | if (tb[NFTA_CT_DREG] && tb[NFTA_CT_SREG]) | ||
| 361 | return ERR_PTR(-EINVAL); | ||
| 362 | |||
| 363 | if (tb[NFTA_CT_DREG]) | ||
| 364 | return &nft_ct_get_ops; | ||
| 365 | |||
| 366 | if (tb[NFTA_CT_SREG]) | ||
| 367 | return &nft_ct_set_ops; | ||
| 368 | |||
| 369 | return ERR_PTR(-EINVAL); | ||
| 370 | } | ||
| 371 | |||
| 235 | static struct nft_expr_type nft_ct_type __read_mostly = { | 372 | static struct nft_expr_type nft_ct_type __read_mostly = { |
| 236 | .name = "ct", | 373 | .name = "ct", |
| 237 | .ops = &nft_ct_ops, | 374 | .select_ops = &nft_ct_select_ops, |
| 238 | .policy = nft_ct_policy, | 375 | .policy = nft_ct_policy, |
| 239 | .maxattr = NFTA_CT_MAX, | 376 | .maxattr = NFTA_CT_MAX, |
| 240 | .owner = THIS_MODULE, | 377 | .owner = THIS_MODULE, |
diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c index 6aae699aeb46..3d3f8fce10a5 100644 --- a/net/netfilter/nft_hash.c +++ b/net/netfilter/nft_hash.c | |||
| @@ -164,7 +164,7 @@ static int nft_hash_init(const struct nft_set *set, | |||
| 164 | unsigned int cnt, i; | 164 | unsigned int cnt, i; |
| 165 | 165 | ||
| 166 | if (unlikely(!nft_hash_rnd_initted)) { | 166 | if (unlikely(!nft_hash_rnd_initted)) { |
| 167 | nft_hash_rnd = prandom_u32(); | 167 | get_random_bytes(&nft_hash_rnd, 4); |
| 168 | nft_hash_rnd_initted = true; | 168 | nft_hash_rnd_initted = true; |
| 169 | } | 169 | } |
| 170 | 170 | ||
diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c index 57cad072a13e..5af790123ad8 100644 --- a/net/netfilter/nft_log.c +++ b/net/netfilter/nft_log.c | |||
| @@ -33,7 +33,7 @@ static void nft_log_eval(const struct nft_expr *expr, | |||
| 33 | const struct nft_log *priv = nft_expr_priv(expr); | 33 | const struct nft_log *priv = nft_expr_priv(expr); |
| 34 | struct net *net = dev_net(pkt->in ? pkt->in : pkt->out); | 34 | struct net *net = dev_net(pkt->in ? pkt->in : pkt->out); |
| 35 | 35 | ||
| 36 | nf_log_packet(net, priv->family, pkt->hooknum, pkt->skb, pkt->in, | 36 | nf_log_packet(net, priv->family, pkt->ops->hooknum, pkt->skb, pkt->in, |
| 37 | pkt->out, &priv->loginfo, "%s", priv->prefix); | 37 | pkt->out, &priv->loginfo, "%s", priv->prefix); |
| 38 | } | 38 | } |
| 39 | 39 | ||
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c index 1ceaaa6dfe72..e8254ad2e5a9 100644 --- a/net/netfilter/nft_meta.c +++ b/net/netfilter/nft_meta.c | |||
| @@ -43,6 +43,12 @@ static void nft_meta_get_eval(const struct nft_expr *expr, | |||
| 43 | case NFT_META_PROTOCOL: | 43 | case NFT_META_PROTOCOL: |
| 44 | *(__be16 *)dest->data = skb->protocol; | 44 | *(__be16 *)dest->data = skb->protocol; |
| 45 | break; | 45 | break; |
| 46 | case NFT_META_NFPROTO: | ||
| 47 | dest->data[0] = pkt->ops->pf; | ||
| 48 | break; | ||
| 49 | case NFT_META_L4PROTO: | ||
| 50 | dest->data[0] = pkt->tprot; | ||
| 51 | break; | ||
| 46 | case NFT_META_PRIORITY: | 52 | case NFT_META_PRIORITY: |
| 47 | dest->data[0] = skb->priority; | 53 | dest->data[0] = skb->priority; |
| 48 | break; | 54 | break; |
| @@ -181,6 +187,8 @@ static int nft_meta_init_validate_get(uint32_t key) | |||
| 181 | switch (key) { | 187 | switch (key) { |
| 182 | case NFT_META_LEN: | 188 | case NFT_META_LEN: |
| 183 | case NFT_META_PROTOCOL: | 189 | case NFT_META_PROTOCOL: |
| 190 | case NFT_META_NFPROTO: | ||
| 191 | case NFT_META_L4PROTO: | ||
| 184 | case NFT_META_PRIORITY: | 192 | case NFT_META_PRIORITY: |
| 185 | case NFT_META_MARK: | 193 | case NFT_META_MARK: |
| 186 | case NFT_META_IIF: | 194 | case NFT_META_IIF: |
| @@ -231,6 +239,9 @@ static int nft_meta_init(const struct nft_ctx *ctx, const struct nft_expr *expr, | |||
| 231 | return err; | 239 | return err; |
| 232 | 240 | ||
| 233 | priv->sreg = ntohl(nla_get_be32(tb[NFTA_META_SREG])); | 241 | priv->sreg = ntohl(nla_get_be32(tb[NFTA_META_SREG])); |
| 242 | err = nft_validate_input_register(priv->sreg); | ||
| 243 | if (err < 0) | ||
| 244 | return err; | ||
| 234 | 245 | ||
| 235 | return 0; | 246 | return 0; |
| 236 | } | 247 | } |
diff --git a/net/netfilter/nft_reject.c b/net/netfilter/nft_reject.c index 0d690d4101d2..5e204711d704 100644 --- a/net/netfilter/nft_reject.c +++ b/net/netfilter/nft_reject.c | |||
| @@ -34,8 +34,9 @@ static void nft_reject_eval(const struct nft_expr *expr, | |||
| 34 | const struct nft_pktinfo *pkt) | 34 | const struct nft_pktinfo *pkt) |
| 35 | { | 35 | { |
| 36 | struct nft_reject *priv = nft_expr_priv(expr); | 36 | struct nft_reject *priv = nft_expr_priv(expr); |
| 37 | #if IS_ENABLED(CONFIG_NF_TABLES_IPV6) | ||
| 37 | struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); | 38 | struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); |
| 38 | 39 | #endif | |
| 39 | switch (priv->type) { | 40 | switch (priv->type) { |
| 40 | case NFT_REJECT_ICMP_UNREACH: | 41 | case NFT_REJECT_ICMP_UNREACH: |
| 41 | if (priv->family == NFPROTO_IPV4) | 42 | if (priv->family == NFPROTO_IPV4) |
| @@ -43,15 +44,15 @@ static void nft_reject_eval(const struct nft_expr *expr, | |||
| 43 | #if IS_ENABLED(CONFIG_NF_TABLES_IPV6) | 44 | #if IS_ENABLED(CONFIG_NF_TABLES_IPV6) |
| 44 | else if (priv->family == NFPROTO_IPV6) | 45 | else if (priv->family == NFPROTO_IPV6) |
| 45 | nf_send_unreach6(net, pkt->skb, priv->icmp_code, | 46 | nf_send_unreach6(net, pkt->skb, priv->icmp_code, |
| 46 | pkt->hooknum); | 47 | pkt->ops->hooknum); |
| 47 | #endif | 48 | #endif |
| 48 | break; | 49 | break; |
| 49 | case NFT_REJECT_TCP_RST: | 50 | case NFT_REJECT_TCP_RST: |
| 50 | if (priv->family == NFPROTO_IPV4) | 51 | if (priv->family == NFPROTO_IPV4) |
| 51 | nf_send_reset(pkt->skb, pkt->hooknum); | 52 | nf_send_reset(pkt->skb, pkt->ops->hooknum); |
| 52 | #if IS_ENABLED(CONFIG_NF_TABLES_IPV6) | 53 | #if IS_ENABLED(CONFIG_NF_TABLES_IPV6) |
| 53 | else if (priv->family == NFPROTO_IPV6) | 54 | else if (priv->family == NFPROTO_IPV6) |
| 54 | nf_send_reset6(net, pkt->skb, pkt->hooknum); | 55 | nf_send_reset6(net, pkt->skb, pkt->ops->hooknum); |
| 55 | #endif | 56 | #endif |
| 56 | break; | 57 | break; |
| 57 | } | 58 | } |
diff --git a/net/netfilter/xt_RATEEST.c b/net/netfilter/xt_RATEEST.c index 190854be7629..370adf622cef 100644 --- a/net/netfilter/xt_RATEEST.c +++ b/net/netfilter/xt_RATEEST.c | |||
| @@ -100,7 +100,7 @@ static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par) | |||
| 100 | int ret; | 100 | int ret; |
| 101 | 101 | ||
| 102 | if (unlikely(!rnd_inited)) { | 102 | if (unlikely(!rnd_inited)) { |
| 103 | jhash_rnd = prandom_u32(); | 103 | get_random_bytes(&jhash_rnd, sizeof(jhash_rnd)); |
| 104 | rnd_inited = true; | 104 | rnd_inited = true; |
| 105 | } | 105 | } |
| 106 | 106 | ||
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c index 7671e8214919..c40b2695633b 100644 --- a/net/netfilter/xt_connlimit.c +++ b/net/netfilter/xt_connlimit.c | |||
| @@ -229,7 +229,7 @@ static int connlimit_mt_check(const struct xt_mtchk_param *par) | |||
| 229 | u_int32_t rand; | 229 | u_int32_t rand; |
| 230 | 230 | ||
| 231 | do { | 231 | do { |
| 232 | rand = prandom_u32(); | 232 | get_random_bytes(&rand, sizeof(rand)); |
| 233 | } while (!rand); | 233 | } while (!rand); |
| 234 | cmpxchg(&connlimit_rnd, 0, rand); | 234 | cmpxchg(&connlimit_rnd, 0, rand); |
| 235 | } | 235 | } |
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index d819f62b3b7c..a3910fc2122b 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c | |||
| @@ -177,7 +177,7 @@ dsthash_alloc_init(struct xt_hashlimit_htable *ht, | |||
| 177 | /* initialize hash with random val at the time we allocate | 177 | /* initialize hash with random val at the time we allocate |
| 178 | * the first hashtable entry */ | 178 | * the first hashtable entry */ |
| 179 | if (unlikely(!ht->rnd_initialized)) { | 179 | if (unlikely(!ht->rnd_initialized)) { |
| 180 | ht->rnd = prandom_u32(); | 180 | get_random_bytes(&ht->rnd, sizeof(ht->rnd)); |
| 181 | ht->rnd_initialized = true; | 181 | ht->rnd_initialized = true; |
| 182 | } | 182 | } |
| 183 | 183 | ||
diff --git a/net/netfilter/xt_l2tp.c b/net/netfilter/xt_l2tp.c new file mode 100644 index 000000000000..8aee572771f2 --- /dev/null +++ b/net/netfilter/xt_l2tp.c | |||
| @@ -0,0 +1,354 @@ | |||
| 1 | /* Kernel module to match L2TP header parameters. */ | ||
| 2 | |||
| 3 | /* (C) 2013 James Chapman <jchapman@katalix.com> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License version 2 as | ||
| 7 | * published by the Free Software Foundation. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/skbuff.h> | ||
| 13 | #include <linux/if_ether.h> | ||
| 14 | #include <net/ip.h> | ||
| 15 | #include <linux/ipv6.h> | ||
| 16 | #include <net/ipv6.h> | ||
| 17 | #include <net/udp.h> | ||
| 18 | #include <linux/l2tp.h> | ||
| 19 | |||
| 20 | #include <linux/netfilter_ipv4.h> | ||
| 21 | #include <linux/netfilter_ipv6.h> | ||
| 22 | #include <linux/netfilter_ipv4/ip_tables.h> | ||
| 23 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
| 24 | #include <linux/netfilter/x_tables.h> | ||
| 25 | #include <linux/netfilter/xt_tcpudp.h> | ||
| 26 | #include <linux/netfilter/xt_l2tp.h> | ||
| 27 | |||
| 28 | /* L2TP header masks */ | ||
| 29 | #define L2TP_HDR_T_BIT 0x8000 | ||
| 30 | #define L2TP_HDR_L_BIT 0x4000 | ||
| 31 | #define L2TP_HDR_VER 0x000f | ||
| 32 | |||
| 33 | MODULE_LICENSE("GPL"); | ||
| 34 | MODULE_AUTHOR("James Chapman <jchapman@katalix.com>"); | ||
| 35 | MODULE_DESCRIPTION("Xtables: L2TP header match"); | ||
| 36 | MODULE_ALIAS("ipt_l2tp"); | ||
| 37 | MODULE_ALIAS("ip6t_l2tp"); | ||
| 38 | |||
| 39 | /* The L2TP fields that can be matched */ | ||
| 40 | struct l2tp_data { | ||
| 41 | u32 tid; | ||
| 42 | u32 sid; | ||
| 43 | u8 type; | ||
| 44 | u8 version; | ||
| 45 | }; | ||
| 46 | |||
| 47 | union l2tp_val { | ||
| 48 | __be16 val16[2]; | ||
| 49 | __be32 val32; | ||
| 50 | }; | ||
| 51 | |||
| 52 | static bool l2tp_match(const struct xt_l2tp_info *info, struct l2tp_data *data) | ||
| 53 | { | ||
| 54 | if ((info->flags & XT_L2TP_TYPE) && (info->type != data->type)) | ||
| 55 | return false; | ||
| 56 | |||
| 57 | if ((info->flags & XT_L2TP_VERSION) && (info->version != data->version)) | ||
| 58 | return false; | ||
| 59 | |||
| 60 | /* Check tid only for L2TPv3 control or any L2TPv2 packets */ | ||
| 61 | if ((info->flags & XT_L2TP_TID) && | ||
| 62 | ((data->type == XT_L2TP_TYPE_CONTROL) || (data->version == 2)) && | ||
| 63 | (info->tid != data->tid)) | ||
| 64 | return false; | ||
| 65 | |||
| 66 | /* Check sid only for L2TP data packets */ | ||
| 67 | if ((info->flags & XT_L2TP_SID) && (data->type == XT_L2TP_TYPE_DATA) && | ||
| 68 | (info->sid != data->sid)) | ||
| 69 | return false; | ||
| 70 | |||
| 71 | return true; | ||
| 72 | } | ||
| 73 | |||
| 74 | /* Parse L2TP header fields when UDP encapsulation is used. Handles | ||
| 75 | * L2TPv2 and L2TPv3. Note the L2TPv3 control and data packets have a | ||
| 76 | * different format. See | ||
| 77 | * RFC2661, Section 3.1, L2TPv2 Header Format | ||
| 78 | * RFC3931, Section 3.2.1, L2TPv3 Control Message Header | ||
| 79 | * RFC3931, Section 3.2.2, L2TPv3 Data Message Header | ||
| 80 | * RFC3931, Section 4.1.2.1, L2TPv3 Session Header over UDP | ||
| 81 | */ | ||
| 82 | static bool l2tp_udp_mt(const struct sk_buff *skb, struct xt_action_param *par, u16 thoff) | ||
| 83 | { | ||
| 84 | const struct xt_l2tp_info *info = par->matchinfo; | ||
| 85 | int uhlen = sizeof(struct udphdr); | ||
| 86 | int offs = thoff + uhlen; | ||
| 87 | union l2tp_val *lh; | ||
| 88 | union l2tp_val lhbuf; | ||
| 89 | u16 flags; | ||
| 90 | struct l2tp_data data = { 0, }; | ||
| 91 | |||
| 92 | if (par->fragoff != 0) | ||
| 93 | return false; | ||
| 94 | |||
| 95 | /* Extract L2TP header fields. The flags in the first 16 bits | ||
| 96 | * tell us where the other fields are. | ||
| 97 | */ | ||
| 98 | lh = skb_header_pointer(skb, offs, 2, &lhbuf); | ||
| 99 | if (lh == NULL) | ||
| 100 | return false; | ||
| 101 | |||
| 102 | flags = ntohs(lh->val16[0]); | ||
| 103 | if (flags & L2TP_HDR_T_BIT) | ||
| 104 | data.type = XT_L2TP_TYPE_CONTROL; | ||
| 105 | else | ||
| 106 | data.type = XT_L2TP_TYPE_DATA; | ||
| 107 | data.version = (u8) flags & L2TP_HDR_VER; | ||
| 108 | |||
| 109 | /* Now extract the L2TP tid/sid. These are in different places | ||
| 110 | * for L2TPv2 (rfc2661) and L2TPv3 (rfc3931). For L2TPv2, we | ||
| 111 | * must also check to see if the length field is present, | ||
| 112 | * since this affects the offsets into the packet of the | ||
| 113 | * tid/sid fields. | ||
| 114 | */ | ||
| 115 | if (data.version == 3) { | ||
| 116 | lh = skb_header_pointer(skb, offs + 4, 4, &lhbuf); | ||
| 117 | if (lh == NULL) | ||
| 118 | return false; | ||
| 119 | if (data.type == XT_L2TP_TYPE_CONTROL) | ||
| 120 | data.tid = ntohl(lh->val32); | ||
| 121 | else | ||
| 122 | data.sid = ntohl(lh->val32); | ||
| 123 | } else if (data.version == 2) { | ||
| 124 | if (flags & L2TP_HDR_L_BIT) | ||
| 125 | offs += 2; | ||
| 126 | lh = skb_header_pointer(skb, offs + 2, 4, &lhbuf); | ||
| 127 | if (lh == NULL) | ||
| 128 | return false; | ||
| 129 | data.tid = (u32) ntohs(lh->val16[0]); | ||
| 130 | data.sid = (u32) ntohs(lh->val16[1]); | ||
| 131 | } else | ||
| 132 | return false; | ||
| 133 | |||
| 134 | return l2tp_match(info, &data); | ||
| 135 | } | ||
| 136 | |||
| 137 | /* Parse L2TP header fields for IP encapsulation (no UDP header). | ||
| 138 | * L2TPv3 data packets have a different form with IP encap. See | ||
| 139 | * RC3931, Section 4.1.1.1, L2TPv3 Session Header over IP. | ||
| 140 | * RC3931, Section 4.1.1.2, L2TPv3 Control and Data Traffic over IP. | ||
| 141 | */ | ||
| 142 | static bool l2tp_ip_mt(const struct sk_buff *skb, struct xt_action_param *par, u16 thoff) | ||
| 143 | { | ||
| 144 | const struct xt_l2tp_info *info = par->matchinfo; | ||
| 145 | union l2tp_val *lh; | ||
| 146 | union l2tp_val lhbuf; | ||
| 147 | struct l2tp_data data = { 0, }; | ||
| 148 | |||
| 149 | /* For IP encap, the L2TP sid is the first 32-bits. */ | ||
| 150 | lh = skb_header_pointer(skb, thoff, sizeof(lhbuf), &lhbuf); | ||
| 151 | if (lh == NULL) | ||
| 152 | return false; | ||
| 153 | if (lh->val32 == 0) { | ||
| 154 | /* Must be a control packet. The L2TP tid is further | ||
| 155 | * into the packet. | ||
| 156 | */ | ||
| 157 | data.type = XT_L2TP_TYPE_CONTROL; | ||
| 158 | lh = skb_header_pointer(skb, thoff + 8, sizeof(lhbuf), | ||
| 159 | &lhbuf); | ||
| 160 | if (lh == NULL) | ||
| 161 | return false; | ||
| 162 | data.tid = ntohl(lh->val32); | ||
| 163 | } else { | ||
| 164 | data.sid = ntohl(lh->val32); | ||
| 165 | data.type = XT_L2TP_TYPE_DATA; | ||
| 166 | } | ||
| 167 | |||
| 168 | data.version = 3; | ||
| 169 | |||
| 170 | return l2tp_match(info, &data); | ||
| 171 | } | ||
| 172 | |||
| 173 | static bool l2tp_mt4(const struct sk_buff *skb, struct xt_action_param *par) | ||
| 174 | { | ||
| 175 | struct iphdr *iph = ip_hdr(skb); | ||
| 176 | u8 ipproto = iph->protocol; | ||
| 177 | |||
| 178 | /* l2tp_mt_check4 already restricts the transport protocol */ | ||
| 179 | switch (ipproto) { | ||
| 180 | case IPPROTO_UDP: | ||
| 181 | return l2tp_udp_mt(skb, par, par->thoff); | ||
| 182 | case IPPROTO_L2TP: | ||
| 183 | return l2tp_ip_mt(skb, par, par->thoff); | ||
| 184 | } | ||
| 185 | |||
| 186 | return false; | ||
| 187 | } | ||
| 188 | |||
| 189 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) | ||
| 190 | static bool l2tp_mt6(const struct sk_buff *skb, struct xt_action_param *par) | ||
| 191 | { | ||
| 192 | unsigned int thoff = 0; | ||
| 193 | unsigned short fragoff = 0; | ||
| 194 | int ipproto; | ||
| 195 | |||
| 196 | ipproto = ipv6_find_hdr(skb, &thoff, -1, &fragoff, NULL); | ||
| 197 | if (fragoff != 0) | ||
| 198 | return false; | ||
| 199 | |||
| 200 | /* l2tp_mt_check6 already restricts the transport protocol */ | ||
| 201 | switch (ipproto) { | ||
| 202 | case IPPROTO_UDP: | ||
| 203 | return l2tp_udp_mt(skb, par, thoff); | ||
| 204 | case IPPROTO_L2TP: | ||
| 205 | return l2tp_ip_mt(skb, par, thoff); | ||
| 206 | } | ||
| 207 | |||
| 208 | return false; | ||
| 209 | } | ||
| 210 | #endif | ||
| 211 | |||
| 212 | static int l2tp_mt_check(const struct xt_mtchk_param *par) | ||
| 213 | { | ||
| 214 | const struct xt_l2tp_info *info = par->matchinfo; | ||
| 215 | |||
| 216 | /* Check for invalid flags */ | ||
| 217 | if (info->flags & ~(XT_L2TP_TID | XT_L2TP_SID | XT_L2TP_VERSION | | ||
| 218 | XT_L2TP_TYPE)) { | ||
| 219 | pr_info("unknown flags: %x\n", info->flags); | ||
| 220 | return -EINVAL; | ||
| 221 | } | ||
| 222 | |||
| 223 | /* At least one of tid, sid or type=control must be specified */ | ||
| 224 | if ((!(info->flags & XT_L2TP_TID)) && | ||
| 225 | (!(info->flags & XT_L2TP_SID)) && | ||
| 226 | ((!(info->flags & XT_L2TP_TYPE)) || | ||
| 227 | (info->type != XT_L2TP_TYPE_CONTROL))) { | ||
| 228 | pr_info("invalid flags combination: %x\n", info->flags); | ||
| 229 | return -EINVAL; | ||
| 230 | } | ||
| 231 | |||
| 232 | /* If version 2 is specified, check that incompatible params | ||
| 233 | * are not supplied | ||
| 234 | */ | ||
| 235 | if (info->flags & XT_L2TP_VERSION) { | ||
| 236 | if ((info->version < 2) || (info->version > 3)) { | ||
| 237 | pr_info("wrong L2TP version: %u\n", info->version); | ||
| 238 | return -EINVAL; | ||
| 239 | } | ||
| 240 | |||
| 241 | if (info->version == 2) { | ||
| 242 | if ((info->flags & XT_L2TP_TID) && | ||
| 243 | (info->tid > 0xffff)) { | ||
| 244 | pr_info("v2 tid > 0xffff: %u\n", info->tid); | ||
| 245 | return -EINVAL; | ||
| 246 | } | ||
| 247 | if ((info->flags & XT_L2TP_SID) && | ||
| 248 | (info->sid > 0xffff)) { | ||
| 249 | pr_info("v2 sid > 0xffff: %u\n", info->sid); | ||
| 250 | return -EINVAL; | ||
| 251 | } | ||
| 252 | } | ||
| 253 | } | ||
| 254 | |||
| 255 | return 0; | ||
| 256 | } | ||
| 257 | |||
| 258 | static int l2tp_mt_check4(const struct xt_mtchk_param *par) | ||
| 259 | { | ||
| 260 | const struct xt_l2tp_info *info = par->matchinfo; | ||
| 261 | const struct ipt_entry *e = par->entryinfo; | ||
| 262 | const struct ipt_ip *ip = &e->ip; | ||
| 263 | int ret; | ||
| 264 | |||
| 265 | ret = l2tp_mt_check(par); | ||
| 266 | if (ret != 0) | ||
| 267 | return ret; | ||
| 268 | |||
| 269 | if ((ip->proto != IPPROTO_UDP) && | ||
| 270 | (ip->proto != IPPROTO_L2TP)) { | ||
| 271 | pr_info("missing protocol rule (udp|l2tpip)\n"); | ||
| 272 | return -EINVAL; | ||
| 273 | } | ||
| 274 | |||
| 275 | if ((ip->proto == IPPROTO_L2TP) && | ||
| 276 | (info->version == 2)) { | ||
| 277 | pr_info("v2 doesn't support IP mode\n"); | ||
| 278 | return -EINVAL; | ||
| 279 | } | ||
| 280 | |||
| 281 | return 0; | ||
| 282 | } | ||
| 283 | |||
| 284 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) | ||
| 285 | static int l2tp_mt_check6(const struct xt_mtchk_param *par) | ||
| 286 | { | ||
| 287 | const struct xt_l2tp_info *info = par->matchinfo; | ||
| 288 | const struct ip6t_entry *e = par->entryinfo; | ||
| 289 | const struct ip6t_ip6 *ip = &e->ipv6; | ||
| 290 | int ret; | ||
| 291 | |||
| 292 | ret = l2tp_mt_check(par); | ||
| 293 | if (ret != 0) | ||
| 294 | return ret; | ||
| 295 | |||
| 296 | if ((ip->proto != IPPROTO_UDP) && | ||
| 297 | (ip->proto != IPPROTO_L2TP)) { | ||
| 298 | pr_info("missing protocol rule (udp|l2tpip)\n"); | ||
| 299 | return -EINVAL; | ||
| 300 | } | ||
| 301 | |||
| 302 | if ((ip->proto == IPPROTO_L2TP) && | ||
| 303 | (info->version == 2)) { | ||
| 304 | pr_info("v2 doesn't support IP mode\n"); | ||
| 305 | return -EINVAL; | ||
| 306 | } | ||
| 307 | |||
| 308 | return 0; | ||
| 309 | } | ||
| 310 | #endif | ||
| 311 | |||
| 312 | static struct xt_match l2tp_mt_reg[] __read_mostly = { | ||
| 313 | { | ||
| 314 | .name = "l2tp", | ||
| 315 | .revision = 0, | ||
| 316 | .family = NFPROTO_IPV4, | ||
| 317 | .match = l2tp_mt4, | ||
| 318 | .matchsize = XT_ALIGN(sizeof(struct xt_l2tp_info)), | ||
| 319 | .checkentry = l2tp_mt_check4, | ||
| 320 | .hooks = ((1 << NF_INET_PRE_ROUTING) | | ||
| 321 | (1 << NF_INET_LOCAL_IN) | | ||
| 322 | (1 << NF_INET_LOCAL_OUT) | | ||
| 323 | (1 << NF_INET_FORWARD)), | ||
| 324 | .me = THIS_MODULE, | ||
| 325 | }, | ||
| 326 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) | ||
| 327 | { | ||
| 328 | .name = "l2tp", | ||
| 329 | .revision = 0, | ||
| 330 | .family = NFPROTO_IPV6, | ||
| 331 | .match = l2tp_mt6, | ||
| 332 | .matchsize = XT_ALIGN(sizeof(struct xt_l2tp_info)), | ||
| 333 | .checkentry = l2tp_mt_check6, | ||
| 334 | .hooks = ((1 << NF_INET_PRE_ROUTING) | | ||
| 335 | (1 << NF_INET_LOCAL_IN) | | ||
| 336 | (1 << NF_INET_LOCAL_OUT) | | ||
| 337 | (1 << NF_INET_FORWARD)), | ||
| 338 | .me = THIS_MODULE, | ||
| 339 | }, | ||
| 340 | #endif | ||
| 341 | }; | ||
| 342 | |||
| 343 | static int __init l2tp_mt_init(void) | ||
| 344 | { | ||
| 345 | return xt_register_matches(&l2tp_mt_reg[0], ARRAY_SIZE(l2tp_mt_reg)); | ||
| 346 | } | ||
| 347 | |||
| 348 | static void __exit l2tp_mt_exit(void) | ||
| 349 | { | ||
| 350 | xt_unregister_matches(&l2tp_mt_reg[0], ARRAY_SIZE(l2tp_mt_reg)); | ||
| 351 | } | ||
| 352 | |||
| 353 | module_init(l2tp_mt_init); | ||
| 354 | module_exit(l2tp_mt_exit); | ||
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index bfdc29f1a04a..1e657cf715c4 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c | |||
| @@ -334,7 +334,7 @@ static int recent_mt_check(const struct xt_mtchk_param *par, | |||
| 334 | size_t sz; | 334 | size_t sz; |
| 335 | 335 | ||
| 336 | if (unlikely(!hash_rnd_inited)) { | 336 | if (unlikely(!hash_rnd_inited)) { |
| 337 | hash_rnd = prandom_u32(); | 337 | get_random_bytes(&hash_rnd, sizeof(hash_rnd)); |
| 338 | hash_rnd_inited = true; | 338 | hash_rnd_inited = true; |
| 339 | } | 339 | } |
| 340 | if (info->check_set & ~XT_RECENT_VALID_FLAGS) { | 340 | if (info->check_set & ~XT_RECENT_VALID_FLAGS) { |
diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c index b430d42b2d0f..c58a0fe3c889 100644 --- a/net/openvswitch/flow_table.c +++ b/net/openvswitch/flow_table.c | |||
| @@ -104,7 +104,7 @@ struct sw_flow *ovs_flow_alloc(bool percpu_stats) | |||
| 104 | } | 104 | } |
| 105 | return flow; | 105 | return flow; |
| 106 | err: | 106 | err: |
| 107 | kfree(flow); | 107 | kmem_cache_free(flow_cache, flow); |
| 108 | return ERR_PTR(-ENOMEM); | 108 | return ERR_PTR(-ENOMEM); |
| 109 | } | 109 | } |
| 110 | 110 | ||
diff --git a/net/wireless/ap.c b/net/wireless/ap.c index 324e8d851dc4..11ee4ed04f73 100644 --- a/net/wireless/ap.c +++ b/net/wireless/ap.c | |||
| @@ -29,6 +29,7 @@ static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | |||
| 29 | wdev->beacon_interval = 0; | 29 | wdev->beacon_interval = 0; |
| 30 | wdev->channel = NULL; | 30 | wdev->channel = NULL; |
| 31 | wdev->ssid_len = 0; | 31 | wdev->ssid_len = 0; |
| 32 | rdev_set_qos_map(rdev, dev, NULL); | ||
| 32 | } | 33 | } |
| 33 | 34 | ||
| 34 | return err; | 35 | return err; |
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 730147ed8e65..f911c5f9f903 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
| @@ -183,6 +183,8 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext) | |||
| 183 | kfree(wdev->connect_keys); | 183 | kfree(wdev->connect_keys); |
| 184 | wdev->connect_keys = NULL; | 184 | wdev->connect_keys = NULL; |
| 185 | 185 | ||
| 186 | rdev_set_qos_map(rdev, dev, NULL); | ||
| 187 | |||
| 186 | /* | 188 | /* |
| 187 | * Delete all the keys ... pairwise keys can't really | 189 | * Delete all the keys ... pairwise keys can't really |
| 188 | * exist any more anyway, but default keys might. | 190 | * exist any more anyway, but default keys might. |
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 9c7a11ae7936..885862447b63 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
| @@ -277,6 +277,7 @@ static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, | |||
| 277 | if (!err) { | 277 | if (!err) { |
| 278 | wdev->mesh_id_len = 0; | 278 | wdev->mesh_id_len = 0; |
| 279 | wdev->channel = NULL; | 279 | wdev->channel = NULL; |
| 280 | rdev_set_qos_map(rdev, dev, NULL); | ||
| 280 | } | 281 | } |
| 281 | 282 | ||
| 282 | return err; | 283 | return err; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 04681a46eda8..b4f40fe84a01 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
| @@ -53,6 +53,7 @@ enum nl80211_multicast_groups { | |||
| 53 | NL80211_MCGRP_SCAN, | 53 | NL80211_MCGRP_SCAN, |
| 54 | NL80211_MCGRP_REGULATORY, | 54 | NL80211_MCGRP_REGULATORY, |
| 55 | NL80211_MCGRP_MLME, | 55 | NL80211_MCGRP_MLME, |
| 56 | NL80211_MCGRP_VENDOR, | ||
| 56 | NL80211_MCGRP_TESTMODE /* keep last - ifdef! */ | 57 | NL80211_MCGRP_TESTMODE /* keep last - ifdef! */ |
| 57 | }; | 58 | }; |
| 58 | 59 | ||
| @@ -61,6 +62,7 @@ static const struct genl_multicast_group nl80211_mcgrps[] = { | |||
| 61 | [NL80211_MCGRP_SCAN] = { .name = "scan", }, | 62 | [NL80211_MCGRP_SCAN] = { .name = "scan", }, |
| 62 | [NL80211_MCGRP_REGULATORY] = { .name = "regulatory", }, | 63 | [NL80211_MCGRP_REGULATORY] = { .name = "regulatory", }, |
| 63 | [NL80211_MCGRP_MLME] = { .name = "mlme", }, | 64 | [NL80211_MCGRP_MLME] = { .name = "mlme", }, |
| 65 | [NL80211_MCGRP_VENDOR] = { .name = "vendor", }, | ||
| 64 | #ifdef CONFIG_NL80211_TESTMODE | 66 | #ifdef CONFIG_NL80211_TESTMODE |
| 65 | [NL80211_MCGRP_TESTMODE] = { .name = "testmode", } | 67 | [NL80211_MCGRP_TESTMODE] = { .name = "testmode", } |
| 66 | #endif | 68 | #endif |
| @@ -380,6 +382,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
| 380 | [NL80211_ATTR_VENDOR_ID] = { .type = NLA_U32 }, | 382 | [NL80211_ATTR_VENDOR_ID] = { .type = NLA_U32 }, |
| 381 | [NL80211_ATTR_VENDOR_SUBCMD] = { .type = NLA_U32 }, | 383 | [NL80211_ATTR_VENDOR_SUBCMD] = { .type = NLA_U32 }, |
| 382 | [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY }, | 384 | [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY }, |
| 385 | [NL80211_ATTR_QOS_MAP] = { .type = NLA_BINARY, | ||
| 386 | .len = IEEE80211_QOS_MAP_LEN_MAX }, | ||
| 383 | }; | 387 | }; |
| 384 | 388 | ||
| 385 | /* policy for the key attributes */ | 389 | /* policy for the key attributes */ |
| @@ -1188,7 +1192,6 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
| 1188 | struct nlattr *nl_bands, *nl_band; | 1192 | struct nlattr *nl_bands, *nl_band; |
| 1189 | struct nlattr *nl_freqs, *nl_freq; | 1193 | struct nlattr *nl_freqs, *nl_freq; |
| 1190 | struct nlattr *nl_cmds; | 1194 | struct nlattr *nl_cmds; |
| 1191 | struct nlattr *nl_vendor_cmds; | ||
| 1192 | enum ieee80211_band band; | 1195 | enum ieee80211_band band; |
| 1193 | struct ieee80211_channel *chan; | 1196 | struct ieee80211_channel *chan; |
| 1194 | int i; | 1197 | int i; |
| @@ -1455,6 +1458,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
| 1455 | if (dev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH) | 1458 | if (dev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH) |
| 1456 | CMD(channel_switch, CHANNEL_SWITCH); | 1459 | CMD(channel_switch, CHANNEL_SWITCH); |
| 1457 | } | 1460 | } |
| 1461 | CMD(set_qos_map, SET_QOS_MAP); | ||
| 1458 | 1462 | ||
| 1459 | #ifdef CONFIG_NL80211_TESTMODE | 1463 | #ifdef CONFIG_NL80211_TESTMODE |
| 1460 | CMD(testmode_cmd, TESTMODE); | 1464 | CMD(testmode_cmd, TESTMODE); |
| @@ -1587,16 +1591,38 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
| 1587 | state->split_start++; | 1591 | state->split_start++; |
| 1588 | break; | 1592 | break; |
| 1589 | case 11: | 1593 | case 11: |
| 1590 | nl_vendor_cmds = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); | 1594 | if (dev->wiphy.n_vendor_commands) { |
| 1591 | if (!nl_vendor_cmds) | 1595 | const struct nl80211_vendor_cmd_info *info; |
| 1592 | goto nla_put_failure; | 1596 | struct nlattr *nested; |
| 1597 | |||
| 1598 | nested = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); | ||
| 1599 | if (!nested) | ||
| 1600 | goto nla_put_failure; | ||
| 1601 | |||
| 1602 | for (i = 0; i < dev->wiphy.n_vendor_commands; i++) { | ||
| 1603 | info = &dev->wiphy.vendor_commands[i].info; | ||
| 1604 | if (nla_put(msg, i + 1, sizeof(*info), info)) | ||
| 1605 | goto nla_put_failure; | ||
| 1606 | } | ||
| 1607 | nla_nest_end(msg, nested); | ||
| 1608 | } | ||
| 1609 | |||
| 1610 | if (dev->wiphy.n_vendor_events) { | ||
| 1611 | const struct nl80211_vendor_cmd_info *info; | ||
| 1612 | struct nlattr *nested; | ||
| 1593 | 1613 | ||
| 1594 | for (i = 0; i < dev->wiphy.n_vendor_commands; i++) | 1614 | nested = nla_nest_start(msg, |
| 1595 | if (nla_put(msg, i + 1, | 1615 | NL80211_ATTR_VENDOR_EVENTS); |
| 1596 | sizeof(struct nl80211_vendor_cmd_info), | 1616 | if (!nested) |
| 1597 | &dev->wiphy.vendor_commands[i].info)) | ||
| 1598 | goto nla_put_failure; | 1617 | goto nla_put_failure; |
| 1599 | nla_nest_end(msg, nl_vendor_cmds); | 1618 | |
| 1619 | for (i = 0; i < dev->wiphy.n_vendor_events; i++) { | ||
| 1620 | info = &dev->wiphy.vendor_events[i]; | ||
| 1621 | if (nla_put(msg, i + 1, sizeof(*info), info)) | ||
| 1622 | goto nla_put_failure; | ||
| 1623 | } | ||
| 1624 | nla_nest_end(msg, nested); | ||
| 1625 | } | ||
| 1600 | 1626 | ||
| 1601 | /* done */ | 1627 | /* done */ |
| 1602 | state->split_start = 0; | 1628 | state->split_start = 0; |
| @@ -6726,7 +6752,9 @@ static struct sk_buff * | |||
| 6726 | __cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev, | 6752 | __cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev, |
| 6727 | int approxlen, u32 portid, u32 seq, | 6753 | int approxlen, u32 portid, u32 seq, |
| 6728 | enum nl80211_commands cmd, | 6754 | enum nl80211_commands cmd, |
| 6729 | enum nl80211_attrs attr, gfp_t gfp) | 6755 | enum nl80211_attrs attr, |
| 6756 | const struct nl80211_vendor_cmd_info *info, | ||
| 6757 | gfp_t gfp) | ||
| 6730 | { | 6758 | { |
| 6731 | struct sk_buff *skb; | 6759 | struct sk_buff *skb; |
| 6732 | void *hdr; | 6760 | void *hdr; |
| @@ -6744,6 +6772,16 @@ __cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev, | |||
| 6744 | 6772 | ||
| 6745 | if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx)) | 6773 | if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx)) |
| 6746 | goto nla_put_failure; | 6774 | goto nla_put_failure; |
| 6775 | |||
| 6776 | if (info) { | ||
| 6777 | if (nla_put_u32(skb, NL80211_ATTR_VENDOR_ID, | ||
| 6778 | info->vendor_id)) | ||
| 6779 | goto nla_put_failure; | ||
| 6780 | if (nla_put_u32(skb, NL80211_ATTR_VENDOR_SUBCMD, | ||
| 6781 | info->subcmd)) | ||
| 6782 | goto nla_put_failure; | ||
| 6783 | } | ||
| 6784 | |||
| 6747 | data = nla_nest_start(skb, attr); | 6785 | data = nla_nest_start(skb, attr); |
| 6748 | 6786 | ||
| 6749 | ((void **)skb->cb)[0] = rdev; | 6787 | ((void **)skb->cb)[0] = rdev; |
| @@ -6884,29 +6922,54 @@ static int nl80211_testmode_dump(struct sk_buff *skb, | |||
| 6884 | return err; | 6922 | return err; |
| 6885 | } | 6923 | } |
| 6886 | 6924 | ||
| 6887 | struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy, | 6925 | struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy, |
| 6888 | int approxlen, gfp_t gfp) | 6926 | enum nl80211_commands cmd, |
| 6927 | enum nl80211_attrs attr, | ||
| 6928 | int vendor_event_idx, | ||
| 6929 | int approxlen, gfp_t gfp) | ||
| 6889 | { | 6930 | { |
| 6890 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 6931 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
| 6932 | const struct nl80211_vendor_cmd_info *info; | ||
| 6933 | |||
| 6934 | switch (cmd) { | ||
| 6935 | case NL80211_CMD_TESTMODE: | ||
| 6936 | if (WARN_ON(vendor_event_idx != -1)) | ||
| 6937 | return NULL; | ||
| 6938 | info = NULL; | ||
| 6939 | break; | ||
| 6940 | case NL80211_CMD_VENDOR: | ||
| 6941 | if (WARN_ON(vendor_event_idx < 0 || | ||
| 6942 | vendor_event_idx >= wiphy->n_vendor_events)) | ||
| 6943 | return NULL; | ||
| 6944 | info = &wiphy->vendor_events[vendor_event_idx]; | ||
| 6945 | break; | ||
| 6946 | default: | ||
| 6947 | WARN_ON(1); | ||
| 6948 | return NULL; | ||
| 6949 | } | ||
| 6891 | 6950 | ||
| 6892 | return __cfg80211_alloc_vendor_skb(rdev, approxlen, 0, 0, | 6951 | return __cfg80211_alloc_vendor_skb(rdev, approxlen, 0, 0, |
| 6893 | NL80211_CMD_TESTMODE, | 6952 | cmd, attr, info, gfp); |
| 6894 | NL80211_ATTR_TESTDATA, gfp); | ||
| 6895 | } | 6953 | } |
| 6896 | EXPORT_SYMBOL(cfg80211_testmode_alloc_event_skb); | 6954 | EXPORT_SYMBOL(__cfg80211_alloc_event_skb); |
| 6897 | 6955 | ||
| 6898 | void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp) | 6956 | void __cfg80211_send_event_skb(struct sk_buff *skb, gfp_t gfp) |
| 6899 | { | 6957 | { |
| 6900 | struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0]; | 6958 | struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0]; |
| 6901 | void *hdr = ((void **)skb->cb)[1]; | 6959 | void *hdr = ((void **)skb->cb)[1]; |
| 6902 | struct nlattr *data = ((void **)skb->cb)[2]; | 6960 | struct nlattr *data = ((void **)skb->cb)[2]; |
| 6961 | enum nl80211_multicast_groups mcgrp = NL80211_MCGRP_TESTMODE; | ||
| 6903 | 6962 | ||
| 6904 | nla_nest_end(skb, data); | 6963 | nla_nest_end(skb, data); |
| 6905 | genlmsg_end(skb, hdr); | 6964 | genlmsg_end(skb, hdr); |
| 6965 | |||
| 6966 | if (data->nla_type == NL80211_ATTR_VENDOR_DATA) | ||
| 6967 | mcgrp = NL80211_MCGRP_VENDOR; | ||
| 6968 | |||
| 6906 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), skb, 0, | 6969 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), skb, 0, |
| 6907 | NL80211_MCGRP_TESTMODE, gfp); | 6970 | mcgrp, gfp); |
| 6908 | } | 6971 | } |
| 6909 | EXPORT_SYMBOL(cfg80211_testmode_event); | 6972 | EXPORT_SYMBOL(__cfg80211_send_event_skb); |
| 6910 | #endif | 6973 | #endif |
| 6911 | 6974 | ||
| 6912 | static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | 6975 | static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) |
| @@ -9039,7 +9102,7 @@ struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy, | |||
| 9039 | return __cfg80211_alloc_vendor_skb(rdev, approxlen, | 9102 | return __cfg80211_alloc_vendor_skb(rdev, approxlen, |
| 9040 | rdev->cur_cmd_info->snd_portid, | 9103 | rdev->cur_cmd_info->snd_portid, |
| 9041 | rdev->cur_cmd_info->snd_seq, | 9104 | rdev->cur_cmd_info->snd_seq, |
| 9042 | cmd, attr, GFP_KERNEL); | 9105 | cmd, attr, NULL, GFP_KERNEL); |
| 9043 | } | 9106 | } |
| 9044 | EXPORT_SYMBOL(__cfg80211_alloc_reply_skb); | 9107 | EXPORT_SYMBOL(__cfg80211_alloc_reply_skb); |
| 9045 | 9108 | ||
| @@ -9061,6 +9124,57 @@ int cfg80211_vendor_cmd_reply(struct sk_buff *skb) | |||
| 9061 | EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_reply); | 9124 | EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_reply); |
| 9062 | 9125 | ||
| 9063 | 9126 | ||
| 9127 | static int nl80211_set_qos_map(struct sk_buff *skb, | ||
| 9128 | struct genl_info *info) | ||
| 9129 | { | ||
| 9130 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
| 9131 | struct cfg80211_qos_map *qos_map = NULL; | ||
| 9132 | struct net_device *dev = info->user_ptr[1]; | ||
| 9133 | u8 *pos, len, num_des, des_len, des; | ||
| 9134 | int ret; | ||
| 9135 | |||
| 9136 | if (!rdev->ops->set_qos_map) | ||
| 9137 | return -EOPNOTSUPP; | ||
| 9138 | |||
| 9139 | if (info->attrs[NL80211_ATTR_QOS_MAP]) { | ||
| 9140 | pos = nla_data(info->attrs[NL80211_ATTR_QOS_MAP]); | ||
| 9141 | len = nla_len(info->attrs[NL80211_ATTR_QOS_MAP]); | ||
| 9142 | |||
| 9143 | if (len % 2 || len < IEEE80211_QOS_MAP_LEN_MIN || | ||
| 9144 | len > IEEE80211_QOS_MAP_LEN_MAX) | ||
| 9145 | return -EINVAL; | ||
| 9146 | |||
| 9147 | qos_map = kzalloc(sizeof(struct cfg80211_qos_map), GFP_KERNEL); | ||
| 9148 | if (!qos_map) | ||
| 9149 | return -ENOMEM; | ||
| 9150 | |||
| 9151 | num_des = (len - IEEE80211_QOS_MAP_LEN_MIN) >> 1; | ||
| 9152 | if (num_des) { | ||
| 9153 | des_len = num_des * | ||
| 9154 | sizeof(struct cfg80211_dscp_exception); | ||
| 9155 | memcpy(qos_map->dscp_exception, pos, des_len); | ||
| 9156 | qos_map->num_des = num_des; | ||
| 9157 | for (des = 0; des < num_des; des++) { | ||
| 9158 | if (qos_map->dscp_exception[des].up > 7) { | ||
| 9159 | kfree(qos_map); | ||
| 9160 | return -EINVAL; | ||
| 9161 | } | ||
| 9162 | } | ||
| 9163 | pos += des_len; | ||
| 9164 | } | ||
| 9165 | memcpy(qos_map->up, pos, IEEE80211_QOS_MAP_LEN_MIN); | ||
| 9166 | } | ||
| 9167 | |||
| 9168 | wdev_lock(dev->ieee80211_ptr); | ||
| 9169 | ret = nl80211_key_allowed(dev->ieee80211_ptr); | ||
| 9170 | if (!ret) | ||
| 9171 | ret = rdev_set_qos_map(rdev, dev, qos_map); | ||
| 9172 | wdev_unlock(dev->ieee80211_ptr); | ||
| 9173 | |||
| 9174 | kfree(qos_map); | ||
| 9175 | return ret; | ||
| 9176 | } | ||
| 9177 | |||
| 9064 | #define NL80211_FLAG_NEED_WIPHY 0x01 | 9178 | #define NL80211_FLAG_NEED_WIPHY 0x01 |
| 9065 | #define NL80211_FLAG_NEED_NETDEV 0x02 | 9179 | #define NL80211_FLAG_NEED_NETDEV 0x02 |
| 9066 | #define NL80211_FLAG_NEED_RTNL 0x04 | 9180 | #define NL80211_FLAG_NEED_RTNL 0x04 |
| @@ -9793,6 +9907,14 @@ static const struct genl_ops nl80211_ops[] = { | |||
| 9793 | .internal_flags = NL80211_FLAG_NEED_WIPHY | | 9907 | .internal_flags = NL80211_FLAG_NEED_WIPHY | |
| 9794 | NL80211_FLAG_NEED_RTNL, | 9908 | NL80211_FLAG_NEED_RTNL, |
| 9795 | }, | 9909 | }, |
| 9910 | { | ||
| 9911 | .cmd = NL80211_CMD_SET_QOS_MAP, | ||
| 9912 | .doit = nl80211_set_qos_map, | ||
| 9913 | .policy = nl80211_policy, | ||
| 9914 | .flags = GENL_ADMIN_PERM, | ||
| 9915 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
| 9916 | NL80211_FLAG_NEED_RTNL, | ||
| 9917 | }, | ||
| 9796 | }; | 9918 | }; |
| 9797 | 9919 | ||
| 9798 | /* notification functions */ | 9920 | /* notification functions */ |
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index a6c03ab14a0d..c8e225947adb 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h | |||
| @@ -932,4 +932,19 @@ static inline int rdev_channel_switch(struct cfg80211_registered_device *rdev, | |||
| 932 | return ret; | 932 | return ret; |
| 933 | } | 933 | } |
| 934 | 934 | ||
| 935 | static inline int rdev_set_qos_map(struct cfg80211_registered_device *rdev, | ||
| 936 | struct net_device *dev, | ||
| 937 | struct cfg80211_qos_map *qos_map) | ||
| 938 | { | ||
| 939 | int ret = -EOPNOTSUPP; | ||
| 940 | |||
| 941 | if (rdev->ops->set_qos_map) { | ||
| 942 | trace_rdev_set_qos_map(&rdev->wiphy, dev, qos_map); | ||
| 943 | ret = rdev->ops->set_qos_map(&rdev->wiphy, dev, qos_map); | ||
| 944 | trace_rdev_return_int(&rdev->wiphy, ret); | ||
| 945 | } | ||
| 946 | |||
| 947 | return ret; | ||
| 948 | } | ||
| 949 | |||
| 935 | #endif /* __CFG80211_RDEV_OPS */ | 950 | #endif /* __CFG80211_RDEV_OPS */ |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index d3c5bd7c6b51..5d6e7bb2fc89 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
| @@ -872,6 +872,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | |||
| 872 | for (i = 0; i < 6; i++) | 872 | for (i = 0; i < 6; i++) |
| 873 | rdev_del_key(rdev, dev, i, false, NULL); | 873 | rdev_del_key(rdev, dev, i, false, NULL); |
| 874 | 874 | ||
| 875 | rdev_set_qos_map(rdev, dev, NULL); | ||
| 876 | |||
| 875 | #ifdef CONFIG_CFG80211_WEXT | 877 | #ifdef CONFIG_CFG80211_WEXT |
| 876 | memset(&wrqu, 0, sizeof(wrqu)); | 878 | memset(&wrqu, 0, sizeof(wrqu)); |
| 877 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | 879 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index f7aa7a72d9bc..fbcc23edee54 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
| @@ -186,6 +186,28 @@ | |||
| 186 | 186 | ||
| 187 | #define BOOL_TO_STR(bo) (bo) ? "true" : "false" | 187 | #define BOOL_TO_STR(bo) (bo) ? "true" : "false" |
| 188 | 188 | ||
| 189 | #define QOS_MAP_ENTRY __field(u8, num_des) \ | ||
| 190 | __array(u8, dscp_exception, \ | ||
| 191 | 2 * IEEE80211_QOS_MAP_MAX_EX) \ | ||
| 192 | __array(u8, up, IEEE80211_QOS_MAP_LEN_MIN) | ||
| 193 | #define QOS_MAP_ASSIGN(qos_map) \ | ||
| 194 | do { \ | ||
| 195 | if ((qos_map)) { \ | ||
| 196 | __entry->num_des = (qos_map)->num_des; \ | ||
| 197 | memcpy(__entry->dscp_exception, \ | ||
| 198 | &(qos_map)->dscp_exception, \ | ||
| 199 | 2 * IEEE80211_QOS_MAP_MAX_EX); \ | ||
| 200 | memcpy(__entry->up, &(qos_map)->up, \ | ||
| 201 | IEEE80211_QOS_MAP_LEN_MIN); \ | ||
| 202 | } else { \ | ||
| 203 | __entry->num_des = 0; \ | ||
| 204 | memset(__entry->dscp_exception, 0, \ | ||
| 205 | 2 * IEEE80211_QOS_MAP_MAX_EX); \ | ||
| 206 | memset(__entry->up, 0, \ | ||
| 207 | IEEE80211_QOS_MAP_LEN_MIN); \ | ||
| 208 | } \ | ||
| 209 | } while (0) | ||
| 210 | |||
| 189 | /************************************************************* | 211 | /************************************************************* |
| 190 | * rdev->ops traces * | 212 | * rdev->ops traces * |
| 191 | *************************************************************/ | 213 | *************************************************************/ |
| @@ -1875,6 +1897,24 @@ TRACE_EVENT(rdev_channel_switch, | |||
| 1875 | __entry->counter_offset_presp) | 1897 | __entry->counter_offset_presp) |
| 1876 | ); | 1898 | ); |
| 1877 | 1899 | ||
| 1900 | TRACE_EVENT(rdev_set_qos_map, | ||
| 1901 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, | ||
| 1902 | struct cfg80211_qos_map *qos_map), | ||
| 1903 | TP_ARGS(wiphy, netdev, qos_map), | ||
| 1904 | TP_STRUCT__entry( | ||
| 1905 | WIPHY_ENTRY | ||
| 1906 | NETDEV_ENTRY | ||
| 1907 | QOS_MAP_ENTRY | ||
| 1908 | ), | ||
| 1909 | TP_fast_assign( | ||
| 1910 | WIPHY_ASSIGN; | ||
| 1911 | NETDEV_ASSIGN; | ||
| 1912 | QOS_MAP_ASSIGN(qos_map); | ||
| 1913 | ), | ||
| 1914 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", num_des: %u", | ||
| 1915 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->num_des) | ||
| 1916 | ); | ||
| 1917 | |||
| 1878 | /************************************************************* | 1918 | /************************************************************* |
| 1879 | * cfg80211 exported functions traces * | 1919 | * cfg80211 exported functions traces * |
| 1880 | *************************************************************/ | 1920 | *************************************************************/ |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 935dea9485da..5618888853b2 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
| @@ -689,7 +689,8 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, | |||
| 689 | EXPORT_SYMBOL(ieee80211_amsdu_to_8023s); | 689 | EXPORT_SYMBOL(ieee80211_amsdu_to_8023s); |
| 690 | 690 | ||
| 691 | /* Given a data frame determine the 802.1p/1d tag to use. */ | 691 | /* Given a data frame determine the 802.1p/1d tag to use. */ |
| 692 | unsigned int cfg80211_classify8021d(struct sk_buff *skb) | 692 | unsigned int cfg80211_classify8021d(struct sk_buff *skb, |
| 693 | struct cfg80211_qos_map *qos_map) | ||
| 693 | { | 694 | { |
| 694 | unsigned int dscp; | 695 | unsigned int dscp; |
| 695 | unsigned char vlan_priority; | 696 | unsigned char vlan_priority; |
| @@ -720,6 +721,21 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb) | |||
| 720 | return 0; | 721 | return 0; |
| 721 | } | 722 | } |
| 722 | 723 | ||
| 724 | if (qos_map) { | ||
| 725 | unsigned int i, tmp_dscp = dscp >> 2; | ||
| 726 | |||
| 727 | for (i = 0; i < qos_map->num_des; i++) { | ||
| 728 | if (tmp_dscp == qos_map->dscp_exception[i].dscp) | ||
| 729 | return qos_map->dscp_exception[i].up; | ||
| 730 | } | ||
| 731 | |||
| 732 | for (i = 0; i < 8; i++) { | ||
| 733 | if (tmp_dscp >= qos_map->up[i].low && | ||
| 734 | tmp_dscp <= qos_map->up[i].high) | ||
| 735 | return i; | ||
| 736 | } | ||
| 737 | } | ||
| 738 | |||
| 723 | return dscp >> 5; | 739 | return dscp >> 5; |
| 724 | } | 740 | } |
| 725 | EXPORT_SYMBOL(cfg80211_classify8021d); | 741 | EXPORT_SYMBOL(cfg80211_classify8021d); |
| @@ -863,6 +879,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
| 863 | 879 | ||
| 864 | dev->ieee80211_ptr->use_4addr = false; | 880 | dev->ieee80211_ptr->use_4addr = false; |
| 865 | dev->ieee80211_ptr->mesh_id_up_len = 0; | 881 | dev->ieee80211_ptr->mesh_id_up_len = 0; |
| 882 | rdev_set_qos_map(rdev, dev, NULL); | ||
| 866 | 883 | ||
| 867 | switch (otype) { | 884 | switch (otype) { |
| 868 | case NL80211_IFTYPE_AP: | 885 | case NL80211_IFTYPE_AP: |
