diff options
Diffstat (limited to 'drivers')
213 files changed, 13053 insertions, 12138 deletions
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c index 729a149b6b2..2f3516b7f11 100644 --- a/drivers/atm/nicstar.c +++ b/drivers/atm/nicstar.c @@ -154,7 +154,6 @@ static void which_list(ns_dev * card, struct sk_buff *skb); #endif static void ns_poll(unsigned long arg); static int ns_parse_mac(char *mac, unsigned char *esi); -static short ns_h2i(char c); static void ns_phy_put(struct atm_dev *dev, unsigned char value, unsigned long addr); static unsigned char ns_phy_get(struct atm_dev *dev, unsigned long addr); @@ -2824,9 +2823,9 @@ static int ns_parse_mac(char *mac, unsigned char *esi) return -1; j = 0; for (i = 0; i < 6; i++) { - if ((byte1 = ns_h2i(mac[j++])) < 0) + if ((byte1 = hex_to_bin(mac[j++])) < 0) return -1; - if ((byte0 = ns_h2i(mac[j++])) < 0) + if ((byte0 = hex_to_bin(mac[j++])) < 0) return -1; esi[i] = (unsigned char)(byte1 * 16 + byte0); if (i < 5) { @@ -2837,16 +2836,6 @@ static int ns_parse_mac(char *mac, unsigned char *esi) return 0; } -static short ns_h2i(char c) -{ - if (c >= '0' && c <= '9') - return (short)(c - '0'); - if (c >= 'A' && c <= 'F') - return (short)(c - 'A' + 10); - if (c >= 'a' && c <= 'f') - return (short)(c - 'a' + 10); - return -1; -} static void ns_phy_put(struct atm_dev *dev, unsigned char value, unsigned long addr) diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 058fbccf2f5..02deef42492 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -58,6 +58,18 @@ config BT_HCIUART_BCSP Say Y here to compile support for HCI BCSP protocol. +config BT_HCIUART_ATH3K + bool "Atheros AR300x serial support" + depends on BT_HCIUART + help + HCIATH3K (HCI Atheros AR300x) is a serial protocol for + communication between host and Atheros AR300x Bluetooth devices. + This protocol enables AR300x chips to be enabled with + power management support. + Enable this if you have Atheros AR300x serial Bluetooth device. + + Say Y here to compile support for HCI UART ATH3K protocol. + config BT_HCIUART_LL bool "HCILL protocol support" depends on BT_HCIUART diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile index 7e5aed59812..71bdf13287c 100644 --- a/drivers/bluetooth/Makefile +++ b/drivers/bluetooth/Makefile @@ -26,4 +26,5 @@ hci_uart-y := hci_ldisc.o hci_uart-$(CONFIG_BT_HCIUART_H4) += hci_h4.o hci_uart-$(CONFIG_BT_HCIUART_BCSP) += hci_bcsp.o hci_uart-$(CONFIG_BT_HCIUART_LL) += hci_ll.o +hci_uart-$(CONFIG_BT_HCIUART_ATH3K) += hci_ath.o hci_uart-objs := $(hci_uart-y) diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c index b0c84c19f44..8b1b643a519 100644 --- a/drivers/bluetooth/bcm203x.c +++ b/drivers/bluetooth/bcm203x.c @@ -224,7 +224,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id BT_DBG("firmware data %p size %zu", firmware->data, firmware->size); - data->fw_data = kmalloc(firmware->size, GFP_KERNEL); + data->fw_data = kmemdup(firmware->data, firmware->size, GFP_KERNEL); if (!data->fw_data) { BT_ERR("Can't allocate memory for firmware image"); release_firmware(firmware); @@ -234,7 +234,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id return -ENOMEM; } - memcpy(data->fw_data, firmware->data, firmware->size); data->fw_size = firmware->size; data->fw_sent = 0; diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index d945cd12433..751b338d904 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c @@ -62,7 +62,7 @@ struct hci_vendor_hdr { __u8 type; __le16 snum; __le16 dlen; -} __attribute__ ((packed)); +} __packed; static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count) { diff --git a/drivers/bluetooth/btmrvl_debugfs.c b/drivers/bluetooth/btmrvl_debugfs.c index b50b41d97a7..54739b08c30 100644 --- a/drivers/bluetooth/btmrvl_debugfs.c +++ b/drivers/bluetooth/btmrvl_debugfs.c @@ -216,7 +216,7 @@ static const struct file_operations btmrvl_gpiogap_fops = { static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { - struct btmrvl_private *priv = (struct btmrvl_private *) file->private_data; + struct btmrvl_private *priv = file->private_data; char buf[16]; long result, ret; diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index bed0ba63023..90bda50dc44 100644 --- a/drivers/bluetooth/btmrvl_drv.h +++ b/drivers/bluetooth/btmrvl_drv.h @@ -76,6 +76,7 @@ struct btmrvl_private { int (*hw_host_to_card) (struct btmrvl_private *priv, u8 *payload, u16 nb); int (*hw_wakeup_firmware) (struct btmrvl_private *priv); + int (*hw_process_int_status) (struct btmrvl_private *priv); spinlock_t driver_lock; /* spinlock used by driver */ #ifdef CONFIG_DEBUG_FS void *debugfs_data; @@ -118,13 +119,13 @@ struct btmrvl_cmd { __le16 ocf_ogf; u8 length; u8 data[4]; -} __attribute__ ((packed)); +} __packed; struct btmrvl_event { u8 ec; /* event counter */ u8 length; u8 data[4]; -} __attribute__ ((packed)); +} __packed; /* Prototype of global function */ diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index ee37ef0caee..0d32ec82e9b 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -502,14 +502,17 @@ static int btmrvl_service_main_thread(void *data) spin_lock_irqsave(&priv->driver_lock, flags); if (adapter->int_count) { adapter->int_count = 0; + spin_unlock_irqrestore(&priv->driver_lock, flags); + priv->hw_process_int_status(priv); } else if (adapter->ps_state == PS_SLEEP && !skb_queue_empty(&adapter->tx_queue)) { spin_unlock_irqrestore(&priv->driver_lock, flags); adapter->wakeup_tries++; priv->hw_wakeup_firmware(priv); continue; + } else { + spin_unlock_irqrestore(&priv->driver_lock, flags); } - spin_unlock_irqrestore(&priv->driver_lock, flags); if (adapter->ps_state == PS_SLEEP) continue; diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index df0773ebd9e..dcc2a6ec23f 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -47,6 +47,7 @@ * module_exit function is called. */ static u8 user_rmmod; +static u8 sdio_ireg; static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = { .helper = "sd8688_helper.bin", @@ -83,10 +84,10 @@ static int btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card *card, u16 *dat) *dat = 0; fws0 = sdio_readb(card->func, CARD_FW_STATUS0_REG, &ret); + if (ret) + return -EIO; - if (!ret) - fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret); - + fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret); if (ret) return -EIO; @@ -216,7 +217,7 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card) tmphlprbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN); - tmphlprbuf = kmalloc(tmphlprbufsz, GFP_KERNEL); + tmphlprbuf = kzalloc(tmphlprbufsz, GFP_KERNEL); if (!tmphlprbuf) { BT_ERR("Unable to allocate buffer for helper." " Terminating download"); @@ -224,8 +225,6 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card) goto done; } - memset(tmphlprbuf, 0, tmphlprbufsz); - helperbuf = (u8 *) ALIGN_ADDR(tmphlprbuf, BTSDIO_DMA_ALIGN); /* Perform helper data transfer */ @@ -318,7 +317,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card) BT_DBG("Downloading FW image (%d bytes)", firmwarelen); tmpfwbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN); - tmpfwbuf = kmalloc(tmpfwbufsz, GFP_KERNEL); + tmpfwbuf = kzalloc(tmpfwbufsz, GFP_KERNEL); if (!tmpfwbuf) { BT_ERR("Unable to allocate buffer for firmware." " Terminating download"); @@ -326,8 +325,6 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card) goto done; } - memset(tmpfwbuf, 0, tmpfwbufsz); - /* Ensure aligned firmware buffer */ fwbuf = (u8 *) ALIGN_ADDR(tmpfwbuf, BTSDIO_DMA_ALIGN); @@ -555,78 +552,79 @@ exit: return ret; } -static int btmrvl_sdio_get_int_status(struct btmrvl_private *priv, u8 * ireg) +static int btmrvl_sdio_process_int_status(struct btmrvl_private *priv) { - int ret; - u8 sdio_ireg = 0; + ulong flags; + u8 ireg; struct btmrvl_sdio_card *card = priv->btmrvl_dev.card; - *ireg = 0; - - sdio_ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret); - if (ret) { - BT_ERR("sdio_readb: read int status register failed"); - ret = -EIO; - goto done; - } - - if (sdio_ireg != 0) { - /* - * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS - * Clear the interrupt status register and re-enable the - * interrupt. - */ - BT_DBG("sdio_ireg = 0x%x", sdio_ireg); - - sdio_writeb(card->func, ~(sdio_ireg) & (DN_LD_HOST_INT_STATUS | - UP_LD_HOST_INT_STATUS), - HOST_INTSTATUS_REG, &ret); - if (ret) { - BT_ERR("sdio_writeb: clear int status register " - "failed"); - ret = -EIO; - goto done; - } - } + spin_lock_irqsave(&priv->driver_lock, flags); + ireg = sdio_ireg; + sdio_ireg = 0; + spin_unlock_irqrestore(&priv->driver_lock, flags); - if (sdio_ireg & DN_LD_HOST_INT_STATUS) { + sdio_claim_host(card->func); + if (ireg & DN_LD_HOST_INT_STATUS) { if (priv->btmrvl_dev.tx_dnld_rdy) BT_DBG("tx_done already received: " - " int_status=0x%x", sdio_ireg); + " int_status=0x%x", ireg); else priv->btmrvl_dev.tx_dnld_rdy = true; } - if (sdio_ireg & UP_LD_HOST_INT_STATUS) + if (ireg & UP_LD_HOST_INT_STATUS) btmrvl_sdio_card_to_host(priv); - *ireg = sdio_ireg; - - ret = 0; + sdio_release_host(card->func); -done: - return ret; + return 0; } static void btmrvl_sdio_interrupt(struct sdio_func *func) { struct btmrvl_private *priv; - struct hci_dev *hcidev; struct btmrvl_sdio_card *card; + ulong flags; u8 ireg = 0; + int ret; card = sdio_get_drvdata(func); - if (card && card->priv) { - priv = card->priv; - hcidev = priv->btmrvl_dev.hcidev; + if (!card || !card->priv) { + BT_ERR("sbi_interrupt(%p) card or priv is " + "NULL, card=%p\n", func, card); + return; + } - if (btmrvl_sdio_get_int_status(priv, &ireg)) - BT_ERR("reading HOST_INT_STATUS_REG failed"); - else - BT_DBG("HOST_INT_STATUS_REG %#x", ireg); + priv = card->priv; + + ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret); + if (ret) { + BT_ERR("sdio_readb: read int status register failed"); + return; + } + + if (ireg != 0) { + /* + * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS + * Clear the interrupt status register and re-enable the + * interrupt. + */ + BT_DBG("ireg = 0x%x", ireg); - btmrvl_interrupt(priv); + sdio_writeb(card->func, ~(ireg) & (DN_LD_HOST_INT_STATUS | + UP_LD_HOST_INT_STATUS), + HOST_INTSTATUS_REG, &ret); + if (ret) { + BT_ERR("sdio_writeb: clear int status register failed"); + return; + } } + + spin_lock_irqsave(&priv->driver_lock, flags); + sdio_ireg |= ireg; + spin_unlock_irqrestore(&priv->driver_lock, flags); + + btmrvl_interrupt(priv); } static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card) @@ -930,6 +928,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func, /* Initialize the interface specific function pointers */ priv->hw_host_to_card = btmrvl_sdio_host_to_card; priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw; + priv->hw_process_int_status = btmrvl_sdio_process_int_status; if (btmrvl_register_hdev(priv)) { BT_ERR("Register hdev failed!"); diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 5d9cc53bd64..d22ce3cc611 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -59,6 +59,9 @@ static struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, + /* Apple iMac11,1 */ + { USB_DEVICE(0x05ac, 0x8215) }, + /* AVM BlueFRITZ! USB v2.0 */ { USB_DEVICE(0x057c, 0x3800) }, @@ -146,6 +149,7 @@ static struct usb_device_id blacklist_table[] = { #define BTUSB_BULK_RUNNING 1 #define BTUSB_ISOC_RUNNING 2 #define BTUSB_SUSPENDING 3 +#define BTUSB_DID_ISO_RESUME 4 struct btusb_data { struct hci_dev *hdev; @@ -179,7 +183,6 @@ struct btusb_data { unsigned int sco_num; int isoc_altsetting; int suspend_count; - int did_iso_resume:1; }; static int inc_tx(struct btusb_data *data) @@ -807,7 +810,7 @@ static void btusb_work(struct work_struct *work) int err; if (hdev->conn_hash.sco_num > 0) { - if (!data->did_iso_resume) { + if (!test_bit(BTUSB_DID_ISO_RESUME, &data->flags)) { err = usb_autopm_get_interface(data->isoc); if (err < 0) { clear_bit(BTUSB_ISOC_RUNNING, &data->flags); @@ -815,7 +818,7 @@ static void btusb_work(struct work_struct *work) return; } - data->did_iso_resume = 1; + set_bit(BTUSB_DID_ISO_RESUME, &data->flags); } if (data->isoc_altsetting != 2) { clear_bit(BTUSB_ISOC_RUNNING, &data->flags); @@ -836,10 +839,8 @@ static void btusb_work(struct work_struct *work) usb_kill_anchored_urbs(&data->isoc_anchor); __set_isoc_interface(hdev, 0); - if (data->did_iso_resume) { - data->did_iso_resume = 0; + if (test_and_clear_bit(BTUSB_DID_ISO_RESUME, &data->flags)) usb_autopm_put_interface(data->isoc); - } } } diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index ef044d55cb2..cbe9e44a42e 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -104,7 +104,7 @@ typedef struct { u8 type; u8 zero; u16 len; -} __attribute__ ((packed)) nsh_t; /* Nokia Specific Header */ +} __packed nsh_t; /* Nokia Specific Header */ #define NSHL 4 /* Nokia Specific Header Length */ diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c new file mode 100644 index 00000000000..6a160c17ea9 --- /dev/null +++ b/drivers/bluetooth/hci_ath.c @@ -0,0 +1,235 @@ +/* + * Atheros Communication Bluetooth HCIATH3K UART protocol + * + * HCIATH3K (HCI Atheros AR300x Protocol) is a Atheros Communication's + * power management protocol extension to H4 to support AR300x Bluetooth Chip. + * + * Copyright (c) 2009-2010 Atheros Communications Inc. + * + * Acknowledgements: + * This file is based on hci_h4.c, which was written + * by Maxim Krasnyansky and Marcel Holtmann. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <linux/module.h> +#include <linux/kernel.h> + +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/tty.h> +#include <linux/errno.h> +#include <linux/ioctl.h> +#include <linux/skbuff.h> + +#include <net/bluetooth/bluetooth.h> +#include <net/bluetooth/hci_core.h> + +#include "hci_uart.h" + +struct ath_struct { + struct hci_uart *hu; + unsigned int cur_sleep; + + struct sk_buff_head txq; + struct work_struct ctxtsw; +}; + +static int ath_wakeup_ar3k(struct tty_struct *tty) +{ + struct termios settings; + int status = tty->driver->ops->tiocmget(tty, NULL); + + if (status & TIOCM_CTS) + return status; + + /* Disable Automatic RTSCTS */ + n_tty_ioctl_helper(tty, NULL, TCGETS, (unsigned long)&settings); + settings.c_cflag &= ~CRTSCTS; + n_tty_ioctl_helper(tty, NULL, TCSETS, (unsigned long)&settings); + + /* Clear RTS first */ + status = tty->driver->ops->tiocmget(tty, NULL); + tty->driver->ops->tiocmset(tty, NULL, 0x00, TIOCM_RTS); + mdelay(20); + + /* Set RTS, wake up board */ + status = tty->driver->ops->tiocmget(tty, NULL); + tty->driver->ops->tiocmset(tty, NULL, TIOCM_RTS, 0x00); + mdelay(20); + + status = tty->driver->ops->tiocmget(tty, NULL); + + n_tty_ioctl_helper(tty, NULL, TCGETS, (unsigned long)&settings); + settings.c_cflag |= CRTSCTS; + n_tty_ioctl_helper(tty, NULL, TCSETS, (unsigned long)&settings); + + return status; +} + +static void ath_hci_uart_work(struct work_struct *work) +{ + int status; + struct ath_struct *ath; + struct hci_uart *hu; + struct tty_struct *tty; + + ath = container_of(work, struct ath_struct, ctxtsw); + + hu = ath->hu; + tty = hu->tty; + + /* verify and wake up controller */ + if (ath->cur_sleep) { + status = ath_wakeup_ar3k(tty); + if (!(status & TIOCM_CTS)) + return; + } + + /* Ready to send Data */ + clear_bit(HCI_UART_SENDING, &hu->tx_state); + hci_uart_tx_wakeup(hu); +} + +/* Initialize protocol */ +static int ath_open(struct hci_uart *hu) +{ + struct ath_struct *ath; + + BT_DBG("hu %p", hu); + + ath = kzalloc(sizeof(*ath), GFP_ATOMIC); + if (!ath) + return -ENOMEM; + + skb_queue_head_init(&ath->txq); + + hu->priv = ath; + ath->hu = hu; + + INIT_WORK(&ath->ctxtsw, ath_hci_uart_work); + + return 0; +} + +/* Flush protocol data */ +static int ath_flush(struct hci_uart *hu) +{ + struct ath_struct *ath = hu->priv; + + BT_DBG("hu %p", hu); + + skb_queue_purge(&ath->txq); + + return 0; +} + +/* Close protocol */ +static int ath_close(struct hci_uart *hu) +{ + struct ath_struct *ath = hu->priv; + + BT_DBG("hu %p", hu); + + skb_queue_purge(&ath->txq); + + cancel_work_sync(&ath->ctxtsw); + + hu->priv = NULL; + kfree(ath); + + return 0; +} + +#define HCI_OP_ATH_SLEEP 0xFC04 + +/* Enqueue frame for transmittion */ +static int ath_enqueue(struct hci_uart *hu, struct sk_buff *skb) +{ + struct ath_struct *ath = hu->priv; + + if (bt_cb(skb)->pkt_type == HCI_SCODATA_PKT) { + kfree_skb(skb); + return 0; + } + + /* + * Update power management enable flag with parameters of + * HCI sleep enable vendor specific HCI command. + */ + if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) { + struct hci_command_hdr *hdr = (void *)skb->data; + + if (__le16_to_cpu(hdr->opcode) == HCI_OP_ATH_SLEEP) + ath->cur_sleep = skb->data[HCI_COMMAND_HDR_SIZE]; + } + + BT_DBG("hu %p skb %p", hu, skb); + + /* Prepend skb with frame type */ + memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); + + skb_queue_tail(&ath->txq, skb); + set_bit(HCI_UART_SENDING, &hu->tx_state); + + schedule_work(&ath->ctxtsw); + + return 0; +} + +static struct sk_buff *ath_dequeue(struct hci_uart *hu) +{ + struct ath_struct *ath = hu->priv; + + return skb_dequeue(&ath->txq); +} + +/* Recv data */ +static int ath_recv(struct hci_uart *hu, void *data, int count) +{ + if (hci_recv_stream_fragment(hu->hdev, data, count) < 0) + BT_ERR("Frame Reassembly Failed"); + + return count; +} + +static struct hci_uart_proto athp = { + .id = HCI_UART_ATH3K, + .open = ath_open, + .close = ath_close, + .recv = ath_recv, + .enqueue = ath_enqueue, + .dequeue = ath_dequeue, + .flush = ath_flush, +}; + +int __init ath_init(void) +{ + int err = hci_uart_register_proto(&athp); + + if (!err) + BT_INFO("HCIATH3K protocol initialized"); + else + BT_ERR("HCIATH3K protocol registration failed"); + + return err; +} + +int __exit ath_deinit(void) +{ + return hci_uart_unregister_proto(&athp); +} diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c index 42d69d4de05..9c5b2dc38e2 100644 --- a/drivers/bluetooth/hci_bcsp.c +++ b/drivers/bluetooth/hci_bcsp.c @@ -739,7 +739,7 @@ static struct hci_uart_proto bcsp = { .flush = bcsp_flush }; -int bcsp_init(void) +int __init bcsp_init(void) { int err = hci_uart_register_proto(&bcsp); @@ -751,7 +751,7 @@ int bcsp_init(void) return err; } -int bcsp_deinit(void) +int __exit bcsp_deinit(void) { return hci_uart_unregister_proto(&bcsp); } diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c index 3f038f5308a..7b8ad93e2c3 100644 --- a/drivers/bluetooth/hci_h4.c +++ b/drivers/bluetooth/hci_h4.c @@ -151,107 +151,8 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len) /* Recv data */ static int h4_recv(struct hci_uart *hu, void *data, int count) { - struct h4_struct *h4 = hu->priv; - register char *ptr; - struct hci_event_hdr *eh; - struct hci_acl_hdr *ah; - struct hci_sco_hdr *sh; - register int len, type, dlen; - - BT_DBG("hu %p count %d rx_state %ld rx_count %ld", - hu, count, h4->rx_state, h4->rx_count); - - ptr = data; - while (count) { - if (h4->rx_count) { - len = min_t(unsigned int, h4->rx_count, count); - memcpy(skb_put(h4->rx_skb, len), ptr, len); - h4->rx_count -= len; count -= len; ptr += len; - - if (h4->rx_count) - continue; - - switch (h4->rx_state) { - case H4_W4_DATA: - BT_DBG("Complete data"); - - hci_recv_frame(h4->rx_skb); - - h4->rx_state = H4_W4_PACKET_TYPE; - h4->rx_skb = NULL; - continue; - - case H4_W4_EVENT_HDR: - eh = hci_event_hdr(h4->rx_skb); - - BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen); - - h4_check_data_len(h4, eh->plen); - continue; - - case H4_W4_ACL_HDR: - ah = hci_acl_hdr(h4->rx_skb); - dlen = __le16_to_cpu(ah->dlen); - - BT_DBG("ACL header: dlen %d", dlen); - - h4_check_data_len(h4, dlen); - continue; - - case H4_W4_SCO_HDR: - sh = hci_sco_hdr(h4->rx_skb); - - BT_DBG("SCO header: dlen %d", sh->dlen); - - h4_check_data_len(h4, sh->dlen); - continue; - } - } - - /* H4_W4_PACKET_TYPE */ - switch (*ptr) { - case HCI_EVENT_PKT: - BT_DBG("Event packet"); - h4->rx_state = H4_W4_EVENT_HDR; - h4->rx_count = HCI_EVENT_HDR_SIZE; - type = HCI_EVENT_PKT; - break; - - case HCI_ACLDATA_PKT: - BT_DBG("ACL packet"); - h4->rx_state = H4_W4_ACL_HDR; - h4->rx_count = HCI_ACL_HDR_SIZE; - type = HCI_ACLDATA_PKT; - break; - - case HCI_SCODATA_PKT: - BT_DBG("SCO packet"); - h4->rx_state = H4_W4_SCO_HDR; - h4->rx_count = HCI_SCO_HDR_SIZE; - type = HCI_SCODATA_PKT; - break; - - default: - BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr); - hu->hdev->stat.err_rx++; - ptr++; count--; - continue; - }; - - ptr++; count--; - - /* Allocate packet */ - h4->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); - if (!h4->rx_skb) { - BT_ERR("Can't allocate mem for new packet"); - h4->rx_state = H4_W4_PACKET_TYPE; - h4->rx_count = 0; - return -ENOMEM; - } - - h4->rx_skb->dev = (void *) hu->hdev; - bt_cb(h4->rx_skb)->pkt_type = type; - } + if (hci_recv_stream_fragment(hu->hdev, data, count) < 0) + BT_ERR("Frame Reassembly Failed"); return count; } @@ -272,7 +173,7 @@ static struct hci_uart_proto h4p = { .flush = h4_flush, }; -int h4_init(void) +int __init h4_init(void) { int err = hci_uart_register_proto(&h4p); @@ -284,7 +185,7 @@ int h4_init(void) return err; } -int h4_deinit(void) +int __exit h4_deinit(void) { return hci_uart_unregister_proto(&h4p); } diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 76a1abb8f21..998833d93c1 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -210,7 +210,6 @@ static int hci_uart_close(struct hci_dev *hdev) static int hci_uart_send_frame(struct sk_buff *skb) { struct hci_dev* hdev = (struct hci_dev *) skb->dev; - struct tty_struct *tty; struct hci_uart *hu; if (!hdev) { @@ -222,7 +221,6 @@ static int hci_uart_send_frame(struct sk_buff *skb) return -EBUSY; hu = (struct hci_uart *) hdev->driver_data; - tty = hu->tty; BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len); @@ -397,6 +395,9 @@ static int hci_uart_register_dev(struct hci_uart *hu) if (!reset) set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks); + if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags)) + set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); + if (hci_register_dev(hdev) < 0) { BT_ERR("Can't register HCI device"); hci_free_dev(hdev); @@ -477,6 +478,15 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file, return hu->hdev->id; return -EUNATCH; + case HCIUARTSETFLAGS: + if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) + return -EBUSY; + hu->hdev_flags = arg; + break; + + case HCIUARTGETFLAGS: + return hu->hdev_flags; + default: err = n_tty_ioctl_helper(tty, file, cmd, arg); break; @@ -542,6 +552,9 @@ static int __init hci_uart_init(void) #ifdef CONFIG_BT_HCIUART_LL ll_init(); #endif +#ifdef CONFIG_BT_HCIUART_ATH3K + ath_init(); +#endif return 0; } @@ -559,6 +572,9 @@ static void __exit hci_uart_exit(void) #ifdef CONFIG_BT_HCIUART_LL ll_deinit(); #endif +#ifdef CONFIG_BT_HCIUART_ATH3K + ath_deinit(); +#endif /* Release tty registration of line discipline */ if ((err = tty_unregister_ldisc(N_HCI))) diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index fb8445c7365..38595e782d0 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -74,7 +74,7 @@ enum hcill_states_e { struct hcill_cmd { u8 cmd; -} __attribute__((packed)); +} __packed; struct ll_struct { unsigned long rx_state; @@ -517,7 +517,7 @@ static struct hci_uart_proto llp = { .flush = ll_flush, }; -int ll_init(void) +int __init ll_init(void) { int err = hci_uart_register_proto(&llp); @@ -529,7 +529,7 @@ int ll_init(void) return err; } -int ll_deinit(void) +int __exit ll_deinit(void) { return hci_uart_unregister_proto(&llp); } diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h index 50113db06b9..99fb35239d1 100644 --- a/drivers/bluetooth/hci_uart.h +++ b/drivers/bluetooth/hci_uart.h @@ -31,15 +31,20 @@ #define HCIUARTSETPROTO _IOW('U', 200, int) #define HCIUARTGETPROTO _IOR('U', 201, int) #define HCIUARTGETDEVICE _IOR('U', 202, int) +#define HCIUARTSETFLAGS _IOW('U', 203, int) +#define HCIUARTGETFLAGS _IOR('U', 204, int) /* UART protocols */ -#define HCI_UART_MAX_PROTO 5 +#define HCI_UART_MAX_PROTO 6 #define HCI_UART_H4 0 #define HCI_UART_BCSP 1 #define HCI_UART_3WIRE 2 #define HCI_UART_H4DS 3 #define HCI_UART_LL 4 +#define HCI_UART_ATH3K 5 + +#define HCI_UART_RAW_DEVICE 0 struct hci_uart; @@ -57,6 +62,7 @@ struct hci_uart { struct tty_struct *tty; struct hci_dev *hdev; unsigned long flags; + unsigned long hdev_flags; struct hci_uart_proto *proto; void *priv; @@ -66,7 +72,7 @@ struct hci_uart { spinlock_t rx_lock; }; -/* HCI_UART flag bits */ +/* HCI_UART proto flag bits */ #define HCI_UART_PROTO_SET 0 /* TX states */ @@ -91,3 +97,8 @@ int bcsp_deinit(void); int ll_init(void); int ll_deinit(void); #endif + +#ifdef CONFIG_BT_HCIUART_ATH3K +int ath_init(void); +int ath_deinit(void); +#endif diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 069a03f717d..c754d88e5ec 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1020,10 +1020,16 @@ static int __devinit vortex_init_one(struct pci_dev *pdev, ioaddr = pci_iomap(pdev, pci_bar, 0); if (!ioaddr) /* If mapping fails, fall-back to BAR 0... */ ioaddr = pci_iomap(pdev, 0, 0); + if (!ioaddr) { + pci_disable_device(pdev); + rc = -ENOMEM; + goto out; + } rc = vortex_probe1(&pdev->dev, ioaddr, pdev->irq, ent->driver_data, unit); if (rc < 0) { + pci_iounmap(pdev, ioaddr); pci_disable_device(pdev); goto out; } @@ -1387,7 +1393,7 @@ static int __devinit vortex_probe1(struct device *gendev, mii_preamble_required++; if (vp->drv_flags & EXTRA_PREAMBLE) mii_preamble_required++; - mdio_sync(ioaddr, 32); + mdio_sync(vp, 32); mdio_read(dev, 24, MII_BMSR); for (phy = 0; phy < 32 && phy_idx < 1; phy++) { int mii_status, phyx; @@ -2912,6 +2918,36 @@ static void vortex_get_drvinfo(struct net_device *dev, } } +static void vortex_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct vortex_private *vp = netdev_priv(dev); + + spin_lock_irq(&vp->lock); + wol->supported = WAKE_MAGIC; + + wol->wolopts = 0; + if (vp->enable_wol) + wol->wolopts |= WAKE_MAGIC; + spin_unlock_irq(&vp->lock); +} + +static int vortex_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct vortex_private *vp = netdev_priv(dev); + if (wol->wolopts & ~WAKE_MAGIC) + return -EINVAL; + + spin_lock_irq(&vp->lock); + if (wol->wolopts & WAKE_MAGIC) + vp->enable_wol = 1; + else + vp->enable_wol = 0; + acpi_set_WOL(dev); + spin_unlock_irq(&vp->lock); + + return 0; +} + static const struct ethtool_ops vortex_ethtool_ops = { .get_drvinfo = vortex_get_drvinfo, .get_strings = vortex_get_strings, @@ -2923,6 +2959,8 @@ static const struct ethtool_ops vortex_ethtool_ops = { .set_settings = vortex_set_settings, .get_link = ethtool_op_get_link, .nway_reset = vortex_nway_reset, + .get_wol = vortex_get_wol, + .set_wol = vortex_set_wol, }; #ifdef CONFIG_PCI diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 8c13df7fdc1..ebe68395ecf 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1751,7 +1751,7 @@ config TLAN config KS8842 tristate "Micrel KSZ8841/42 with generic bus interface" - depends on HAS_IOMEM + depends on HAS_IOMEM && DMA_ENGINE help This platform driver is for KSZ8841(1-port) / KS8842(2-port) ethernet switch chip (managed, VLAN, QoS) from Micrel or diff --git a/drivers/net/Makefile b/drivers/net/Makefile index ce555819c8f..56e8c27f77c 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -84,8 +84,7 @@ obj-$(CONFIG_FEALNX) += fealnx.o obj-$(CONFIG_TIGON3) += tg3.o obj-$(CONFIG_BNX2) += bnx2.o obj-$(CONFIG_CNIC) += cnic.o -obj-$(CONFIG_BNX2X) += bnx2x.o -bnx2x-objs := bnx2x_main.o bnx2x_link.o +obj-$(CONFIG_BNX2X) += bnx2x/ spidernet-y += spider_net.o spider_net_ethtool.o obj-$(CONFIG_SPIDER_NET) += spidernet.o sungem_phy.o obj-$(CONFIG_GELIC_NET) += ps3_gelic.o diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index f17428caecf..99197bd54da 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -33,7 +33,7 @@ #include "be_hw.h" -#define DRV_VER "2.102.147u" +#define DRV_VER "2.103.175u" #define DRV_NAME "be2net" #define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC" #define BE3_NAME "ServerEngines BladeEngine3 10Gbps NIC" @@ -220,7 +220,16 @@ struct be_rx_obj { struct be_rx_page_info page_info_tbl[RX_Q_LEN]; }; +struct be_vf_cfg { + unsigned char vf_mac_addr[ETH_ALEN]; + u32 vf_if_handle; + u32 vf_pmac_id; + u16 vf_vlan_tag; + u32 vf_tx_rate; +}; + #define BE_NUM_MSIX_VECTORS 2 /* 1 each for Tx and Rx */ +#define BE_INVALID_PMAC_ID 0xffffffff struct be_adapter { struct pci_dev *pdev; struct net_device *netdev; @@ -276,9 +285,11 @@ struct be_adapter { u32 port_num; bool promiscuous; bool wol; - u32 cap; + u32 function_mode; u32 rx_fc; /* Rx flow control */ u32 tx_fc; /* Tx flow control */ + bool ue_detected; + bool stats_ioctl_sent; int link_speed; u8 port_type; u8 transceiver; @@ -288,8 +299,7 @@ struct be_adapter { struct completion flash_compl; bool sriov_enabled; - u32 vf_if_handle[BE_MAX_VF]; - u32 vf_pmac_id[BE_MAX_VF]; + struct be_vf_cfg vf_cfg[BE_MAX_VF]; u8 base_eq_id; u8 is_virtfn; }; diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 344e062b7f2..3d305494a60 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -75,8 +75,10 @@ static int be_mcc_compl_process(struct be_adapter *adapter, be_dws_le_to_cpu(&resp->hw_stats, sizeof(resp->hw_stats)); netdev_stats_update(adapter); + adapter->stats_ioctl_sent = false; } - } else if (compl_status != MCC_STATUS_NOT_SUPPORTED) { + } else if ((compl_status != MCC_STATUS_NOT_SUPPORTED) && + (compl->tag0 != OPCODE_COMMON_NTWK_MAC_QUERY)) { extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & CQE_STATUS_EXTD_MASK; dev_warn(&adapter->pdev->dev, @@ -205,6 +207,7 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) if (msecs > 4000) { dev_err(&adapter->pdev->dev, "mbox poll timed out\n"); + be_dump_ue(adapter); return -1; } @@ -949,6 +952,7 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) sge->len = cpu_to_le32(nonemb_cmd->size); be_mcc_notify(adapter); + adapter->stats_ioctl_sent = true; err: spin_unlock_bh(&adapter->mcc_lock); @@ -1257,7 +1261,7 @@ err: } /* Uses mbox */ -int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num, u32 *cap) +int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num, u32 *mode) { struct be_mcc_wrb *wrb; struct be_cmd_req_query_fw_cfg *req; @@ -1278,7 +1282,7 @@ int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num, u32 *cap) if (!status) { struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb); *port_num = le32_to_cpu(resp->phys_port); - *cap = le32_to_cpu(resp->function_cap); + *mode = le32_to_cpu(resp->function_mode); } spin_unlock(&adapter->mbox_lock); @@ -1730,3 +1734,36 @@ err: spin_unlock_bh(&adapter->mcc_lock); return status; } + +int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain) +{ + struct be_mcc_wrb *wrb; + struct be_cmd_req_set_qos *req; + int status; + + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } + + req = embedded_payload(wrb); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, + OPCODE_COMMON_SET_QOS); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_SET_QOS, sizeof(*req)); + + req->hdr.domain = domain; + req->valid_bits = BE_QOS_BITS_NIC; + req->max_bps_nic = bps; + + status = be_mcc_notify_wait(adapter); + +err: + spin_unlock_bh(&adapter->mcc_lock); + return status; +} diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index 912a0586f06..bdc10a28cfd 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -124,6 +124,7 @@ struct be_mcc_mailbox { #define OPCODE_COMMON_CQ_CREATE 12 #define OPCODE_COMMON_EQ_CREATE 13 #define OPCODE_COMMON_MCC_CREATE 21 +#define OPCODE_COMMON_SET_QOS 28 #define OPCODE_COMMON_SEEPROM_READ 30 #define OPCODE_COMMON_NTWK_RX_FILTER 34 #define OPCODE_COMMON_GET_FW_VERSION 35 @@ -748,7 +749,7 @@ struct be_cmd_resp_query_fw_cfg { u32 be_config_number; u32 asic_revision; u32 phys_port; - u32 function_cap; + u32 function_mode; u32 rsvd[26]; }; @@ -894,6 +895,22 @@ struct be_cmd_resp_get_phy_info { u32 future_use[4]; }; +/*********************** Set QOS ***********************/ + +#define BE_QOS_BITS_NIC 1 + +struct be_cmd_req_set_qos { + struct be_cmd_req_hdr hdr; + u32 valid_bits; + u32 max_bps_nic; + u32 rsvd[7]; +}; + +struct be_cmd_resp_set_qos { + struct be_cmd_resp_hdr hdr; + u32 rsvd; +}; + extern int be_pci_fnum_get(struct be_adapter *adapter); extern int be_cmd_POST(struct be_adapter *adapter); extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, @@ -974,4 +991,6 @@ extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, u8 loopback_type, u8 enable); extern int be_cmd_get_phy_info(struct be_adapter *adapter, struct be_dma_mem *cmd); +extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain); +extern void be_dump_ue(struct be_adapter *adapter); diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index c0ade242895..cd16243c7c3 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -322,10 +322,11 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) int status; u16 intf_type; - if (adapter->link_speed < 0) { + if ((adapter->link_speed < 0) || (!(netdev->flags & IFF_UP))) { status = be_cmd_link_status_query(adapter, &link_up, &mac_speed, &link_speed); + be_link_status_update(adapter, link_up); /* link_speed is in units of 10 Mbps */ if (link_speed) { ecmd->speed = link_speed*10; diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h index 06839676e3c..6c8f9bb8bfe 100644 --- a/drivers/net/benet/be_hw.h +++ b/drivers/net/benet/be_hw.h @@ -56,6 +56,16 @@ #define PCICFG_PM_CONTROL_OFFSET 0x44 #define PCICFG_PM_CONTROL_MASK 0x108 /* bits 3 & 8 */ +/********* Online Control Registers *******/ +#define PCICFG_ONLINE0 0xB0 +#define PCICFG_ONLINE1 0xB4 + +/********* UE Status and Mask Registers ***/ +#define PCICFG_UE_STATUS_LOW 0xA0 +#define PCICFG_UE_STATUS_HIGH 0xA4 +#define PCICFG_UE_STATUS_LOW_MASK 0xA8 +#define PCICFG_UE_STATUS_HI_MASK 0xAC + /********* ISR0 Register offset **********/ #define CEV_ISR0_OFFSET 0xC18 #define CEV_ISR_SIZE 4 diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index e6ca92334d6..74e146f470c 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -40,6 +40,76 @@ static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = { { 0 } }; MODULE_DEVICE_TABLE(pci, be_dev_ids); +/* UE Status Low CSR */ +static char *ue_status_low_desc[] = { + "CEV", + "CTX", + "DBUF", + "ERX", + "Host", + "MPU", + "NDMA", + "PTC ", + "RDMA ", + "RXF ", + "RXIPS ", + "RXULP0 ", + "RXULP1 ", + "RXULP2 ", + "TIM ", + "TPOST ", + "TPRE ", + "TXIPS ", + "TXULP0 ", + "TXULP1 ", + "UC ", + "WDMA ", + "TXULP2 ", + "HOST1 ", + "P0_OB_LINK ", + "P1_OB_LINK ", + "HOST_GPIO ", + "MBOX ", + "AXGMAC0", + "AXGMAC1", + "JTAG", + "MPU_INTPEND" +}; +/* UE Status High CSR */ +static char *ue_status_hi_desc[] = { + "LPCMEMHOST", + "MGMT_MAC", + "PCS0ONLINE", + "MPU_IRAM", + "PCS1ONLINE", + "PCTL0", + "PCTL1", + "PMEM", + "RR", + "TXPB", + "RXPP", + "XAUI", + "TXP", + "ARM", + "IPC", + "HOST2", + "HOST3", + "HOST4", + "HOST5", + "HOST6", + "HOST7", + "HOST8", + "HOST9", + "NETC" + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown" +}; static void be_queue_free(struct be_adapter *adapter, struct be_queue_info *q) { @@ -552,11 +622,18 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu) * A max of 64 (BE_NUM_VLANS_SUPPORTED) vlans can be configured in BE. * If the user configures more, place BE in vlan promiscuous mode. */ -static int be_vid_config(struct be_adapter *adapter) +static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num) { u16 vtag[BE_NUM_VLANS_SUPPORTED]; u16 ntags = 0, i; int status = 0; + u32 if_handle; + + if (vf) { + if_handle = adapter->vf_cfg[vf_num].vf_if_handle; + vtag[0] = cpu_to_le16(adapter->vf_cfg[vf_num].vf_vlan_tag); + status = be_cmd_vlan_config(adapter, if_handle, vtag, 1, 1, 0); + } if (adapter->vlans_added <= adapter->max_vlans) { /* Construct VLAN Table to give to HW */ @@ -572,6 +649,7 @@ static int be_vid_config(struct be_adapter *adapter) status = be_cmd_vlan_config(adapter, adapter->if_handle, NULL, 0, 1, 1); } + return status; } @@ -592,27 +670,28 @@ static void be_vlan_add_vid(struct net_device *netdev, u16 vid) { struct be_adapter *adapter = netdev_priv(netdev); + adapter->vlans_added++; if (!be_physfn(adapter)) return; adapter->vlan_tag[vid] = 1; - adapter->vlans_added++; if (adapter->vlans_added <= (adapter->max_vlans + 1)) - be_vid_config(adapter); + be_vid_config(adapter, false, 0); } static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) { struct be_adapter *adapter = netdev_priv(netdev); + adapter->vlans_added--; + vlan_group_set_device(adapter->vlan_grp, vid, NULL); + if (!be_physfn(adapter)) return; adapter->vlan_tag[vid] = 0; - vlan_group_set_device(adapter->vlan_grp, vid, NULL); - adapter->vlans_added--; if (adapter->vlans_added <= adapter->max_vlans) - be_vid_config(adapter); + be_vid_config(adapter, false, 0); } static void be_set_multicast_list(struct net_device *netdev) @@ -656,14 +735,93 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) if (!is_valid_ether_addr(mac) || (vf >= num_vfs)) return -EINVAL; - status = be_cmd_pmac_del(adapter, adapter->vf_if_handle[vf], - adapter->vf_pmac_id[vf]); + if (adapter->vf_cfg[vf].vf_pmac_id != BE_INVALID_PMAC_ID) + status = be_cmd_pmac_del(adapter, + adapter->vf_cfg[vf].vf_if_handle, + adapter->vf_cfg[vf].vf_pmac_id); - status = be_cmd_pmac_add(adapter, mac, adapter->vf_if_handle[vf], - &adapter->vf_pmac_id[vf]); - if (!status) + status = be_cmd_pmac_add(adapter, mac, + adapter->vf_cfg[vf].vf_if_handle, + &adapter->vf_cfg[vf].vf_pmac_id); + + if (status) dev_err(&adapter->pdev->dev, "MAC %pM set on VF %d Failed\n", mac, vf); + else + memcpy(adapter->vf_cfg[vf].vf_mac_addr, mac, ETH_ALEN); + + return status; +} + +static int be_get_vf_config(struct net_device *netdev, int vf, + struct ifla_vf_info *vi) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + if (!adapter->sriov_enabled) + return -EPERM; + + if (vf >= num_vfs) + return -EINVAL; + + vi->vf = vf; + vi->tx_rate = adapter->vf_cfg[vf].vf_tx_rate; + vi->vlan = adapter->vf_cfg[vf].vf_vlan_tag; + vi->qos = 0; + memcpy(&vi->mac, adapter->vf_cfg[vf].vf_mac_addr, ETH_ALEN); + + return 0; +} + +static int be_set_vf_vlan(struct net_device *netdev, + int vf, u16 vlan, u8 qos) +{ + struct be_adapter *adapter = netdev_priv(netdev); + int status = 0; + + if (!adapter->sriov_enabled) + return -EPERM; + + if ((vf >= num_vfs) || (vlan > 4095)) + return -EINVAL; + + if (vlan) { + adapter->vf_cfg[vf].vf_vlan_tag = vlan; + adapter->vlans_added++; + } else { + adapter->vf_cfg[vf].vf_vlan_tag = 0; + adapter->vlans_added--; + } + + status = be_vid_config(adapter, true, vf); + + if (status) + dev_info(&adapter->pdev->dev, + "VLAN %d config on VF %d failed\n", vlan, vf); + return status; +} + +static int be_set_vf_tx_rate(struct net_device *netdev, + int vf, int rate) +{ + struct be_adapter *adapter = netdev_priv(netdev); + int status = 0; + + if (!adapter->sriov_enabled) + return -EPERM; + + if ((vf >= num_vfs) || (rate < 0)) + return -EINVAL; + + if (rate > 10000) + rate = 10000; + + adapter->vf_cfg[vf].vf_tx_rate = rate; + status = be_cmd_set_qos(adapter, rate / 10, vf); + + if (status) + dev_info(&adapter->pdev->dev, + "tx rate %d on VF %d failed\n", rate, vf); return status; } @@ -875,7 +1033,7 @@ static void be_rx_compl_process(struct be_adapter *adapter, /* vlanf could be wrongly set in some cards. * ignore if vtm is not set */ - if ((adapter->cap & 0x400) && !vtm) + if ((adapter->function_mode & 0x400) && !vtm) vlanf = 0; if (unlikely(vlanf)) { @@ -915,7 +1073,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, /* vlanf could be wrongly set in some cards. * ignore if vtm is not set */ - if ((adapter->cap & 0x400) && !vtm) + if ((adapter->function_mode & 0x400) && !vtm) vlanf = 0; skb = napi_get_frags(&eq_obj->napi); @@ -1585,12 +1743,66 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget) return 1; } +static inline bool be_detect_ue(struct be_adapter *adapter) +{ + u32 online0 = 0, online1 = 0; + + pci_read_config_dword(adapter->pdev, PCICFG_ONLINE0, &online0); + + pci_read_config_dword(adapter->pdev, PCICFG_ONLINE1, &online1); + + if (!online0 || !online1) { + adapter->ue_detected = true; + dev_err(&adapter->pdev->dev, + "UE Detected!! online0=%d online1=%d\n", + online0, online1); + return true; + } + + return false; +} + +void be_dump_ue(struct be_adapter *adapter) +{ + u32 ue_status_lo, ue_status_hi, ue_status_lo_mask, ue_status_hi_mask; + u32 i; + + pci_read_config_dword(adapter->pdev, + PCICFG_UE_STATUS_LOW, &ue_status_lo); + pci_read_config_dword(adapter->pdev, + PCICFG_UE_STATUS_HIGH, &ue_status_hi); + pci_read_config_dword(adapter->pdev, + PCICFG_UE_STATUS_LOW_MASK, &ue_status_lo_mask); + pci_read_config_dword(adapter->pdev, + PCICFG_UE_STATUS_HI_MASK, &ue_status_hi_mask); + + ue_status_lo = (ue_status_lo & (~ue_status_lo_mask)); + ue_status_hi = (ue_status_hi & (~ue_status_hi_mask)); + + if (ue_status_lo) { + for (i = 0; ue_status_lo; ue_status_lo >>= 1, i++) { + if (ue_status_lo & 1) + dev_err(&adapter->pdev->dev, + "UE: %s bit set\n", ue_status_low_desc[i]); + } + } + if (ue_status_hi) { + for (i = 0; ue_status_hi; ue_status_hi >>= 1, i++) { + if (ue_status_hi & 1) + dev_err(&adapter->pdev->dev, + "UE: %s bit set\n", ue_status_hi_desc[i]); + } + } + +} + static void be_worker(struct work_struct *work) { struct be_adapter *adapter = container_of(work, struct be_adapter, work.work); - be_cmd_get_stats(adapter, &adapter->stats.cmd); + if (!adapter->stats_ioctl_sent) + be_cmd_get_stats(adapter, &adapter->stats.cmd); /* Set EQ delay */ be_rx_eqd_update(adapter); @@ -1602,6 +1814,10 @@ static void be_worker(struct work_struct *work) adapter->rx_post_starved = false; be_post_rx_frags(adapter); } + if (!adapter->ue_detected) { + if (be_detect_ue(adapter)) + be_dump_ue(adapter); + } schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); } @@ -1629,10 +1845,11 @@ static void be_msix_enable(struct be_adapter *adapter) static void be_sriov_enable(struct be_adapter *adapter) { -#ifdef CONFIG_PCI_IOV - int status; be_check_sriov_fn_type(adapter); +#ifdef CONFIG_PCI_IOV if (be_physfn(adapter) && num_vfs) { + int status; + status = pci_enable_sriov(adapter->pdev, num_vfs); adapter->sriov_enabled = status ? false : true; } @@ -1822,7 +2039,7 @@ static int be_open(struct net_device *netdev) be_link_status_update(adapter, link_up); if (be_physfn(adapter)) { - status = be_vid_config(adapter); + status = be_vid_config(adapter, false, 0); if (status) goto err; @@ -1903,13 +2120,15 @@ static int be_setup(struct be_adapter *adapter) cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST; status = be_cmd_if_create(adapter, cap_flags, en_flags, - mac, true, &adapter->vf_if_handle[vf], + mac, true, + &adapter->vf_cfg[vf].vf_if_handle, NULL, vf+1); if (status) { dev_err(&adapter->pdev->dev, "Interface Create failed for VF %d\n", vf); goto if_destroy; } + adapter->vf_cfg[vf].vf_pmac_id = BE_INVALID_PMAC_ID; vf++; } } else if (!be_physfn(adapter)) { @@ -1943,8 +2162,9 @@ tx_qs_destroy: be_tx_queues_destroy(adapter); if_destroy: for (vf = 0; vf < num_vfs; vf++) - if (adapter->vf_if_handle[vf]) - be_cmd_if_destroy(adapter, adapter->vf_if_handle[vf]); + if (adapter->vf_cfg[vf].vf_if_handle) + be_cmd_if_destroy(adapter, + adapter->vf_cfg[vf].vf_if_handle); be_cmd_if_destroy(adapter, adapter->if_handle); do_none: return status; @@ -2187,7 +2407,10 @@ static struct net_device_ops be_netdev_ops = { .ndo_vlan_rx_register = be_vlan_register, .ndo_vlan_rx_add_vid = be_vlan_add_vid, .ndo_vlan_rx_kill_vid = be_vlan_rem_vid, - .ndo_set_vf_mac = be_set_vf_mac + .ndo_set_vf_mac = be_set_vf_mac, + .ndo_set_vf_vlan = be_set_vf_vlan, + .ndo_set_vf_tx_rate = be_set_vf_tx_rate, + .ndo_get_vf_config = be_get_vf_config }; static void be_netdev_init(struct net_device *netdev) @@ -2406,7 +2629,7 @@ static int be_get_config(struct be_adapter *adapter) return status; status = be_cmd_query_fw_cfg(adapter, - &adapter->port_num, &adapter->cap); + &adapter->port_num, &adapter->function_mode); if (status) return status; @@ -2426,7 +2649,7 @@ static int be_get_config(struct be_adapter *adapter) memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN); } - if (adapter->cap & 0x400) + if (adapter->function_mode & 0x400) adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/4; else adapter->max_vlans = BE_NUM_VLANS_SUPPORTED; diff --git a/drivers/net/bnx2x/Makefile b/drivers/net/bnx2x/Makefile new file mode 100644 index 00000000000..084afce89ae --- /dev/null +++ b/drivers/net/bnx2x/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for Broadcom 10-Gigabit ethernet driver +# + +obj-$(CONFIG_BNX2X) += bnx2x.o + +bnx2x-objs := bnx2x_main.o bnx2x_link.o bnx2x_cmn.o bnx2x_ethtool.o bnx2x_stats.o diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index 8bd23687c53..53af9c93e75 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h @@ -20,6 +20,10 @@ * (you will need to reboot afterwards) */ /* #define BNX2X_STOP_ON_ERROR */ +#define DRV_MODULE_VERSION "1.52.53-3" +#define DRV_MODULE_RELDATE "2010/18/04" +#define BNX2X_BC_VER 0x040200 + #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) #define BCM_VLAN 1 #endif @@ -32,7 +36,7 @@ #if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE) #define BCM_CNIC 1 -#include "cnic_if.h" +#include "../cnic_if.h" #endif @@ -45,10 +49,12 @@ #endif #include <linux/mdio.h> +#include <linux/pci.h> #include "bnx2x_reg.h" #include "bnx2x_fw_defs.h" #include "bnx2x_hsi.h" #include "bnx2x_link.h" +#include "bnx2x_stats.h" /* error/debug prints */ @@ -106,6 +112,7 @@ do { \ dev_info(&bp->pdev->dev, __fmt, ##__args); \ } while (0) +void bnx2x_panic_dump(struct bnx2x *bp); #ifdef BNX2X_STOP_ON_ERROR #define bnx2x_panic() do { \ @@ -248,43 +255,6 @@ union db_prod { #define NEXT_SGE_MASK_ELEM(el) (((el) + 1) & RX_SGE_MASK_LEN_MASK) -struct bnx2x_eth_q_stats { - u32 total_bytes_received_hi; - u32 total_bytes_received_lo; - u32 total_bytes_transmitted_hi; - u32 total_bytes_transmitted_lo; - u32 total_unicast_packets_received_hi; - u32 total_unicast_packets_received_lo; - u32 total_multicast_packets_received_hi; - u32 total_multicast_packets_received_lo; - u32 total_broadcast_packets_received_hi; - u32 total_broadcast_packets_received_lo; - u32 total_unicast_packets_transmitted_hi; - u32 total_unicast_packets_transmitted_lo; - u32 total_multicast_packets_transmitted_hi; - u32 total_multicast_packets_transmitted_lo; - u32 total_broadcast_packets_transmitted_hi; - u32 total_broadcast_packets_transmitted_lo; - u32 valid_bytes_received_hi; - u32 valid_bytes_received_lo; - - u32 error_bytes_received_hi; - u32 error_bytes_received_lo; - u32 etherstatsoverrsizepkts_hi; - u32 etherstatsoverrsizepkts_lo; - u32 no_buff_discard_hi; - u32 no_buff_discard_lo; - - u32 driver_xoff; - u32 rx_err_discard_pkt; - u32 rx_skb_alloc_failed; - u32 hw_csum_err; -}; - -#define BNX2X_NUM_Q_STATS 13 -#define Q_STATS_OFFSET32(stat_name) \ - (offsetof(struct bnx2x_eth_q_stats, stat_name) / 4) - struct bnx2x_fastpath { struct napi_struct napi; @@ -593,27 +563,6 @@ struct bnx2x_common { /* port */ -struct nig_stats { - u32 brb_discard; - u32 brb_packet; - u32 brb_truncate; - u32 flow_ctrl_discard; - u32 flow_ctrl_octets; - u32 flow_ctrl_packet; - u32 mng_discard; - u32 mng_octet_inp; - u32 mng_octet_out; - u32 mng_packet_inp; - u32 mng_packet_out; - u32 pbf_octets; - u32 pbf_packet; - u32 safc_inp; - u32 egress_mac_pkt0_lo; - u32 egress_mac_pkt0_hi; - u32 egress_mac_pkt1_lo; - u32 egress_mac_pkt1_hi; -}; - struct bnx2x_port { u32 pmf; @@ -641,156 +590,6 @@ struct bnx2x_port { /* end of port */ -enum bnx2x_stats_event { - STATS_EVENT_PMF = 0, - STATS_EVENT_LINK_UP, - STATS_EVENT_UPDATE, - STATS_EVENT_STOP, - STATS_EVENT_MAX -}; - -enum bnx2x_stats_state { - STATS_STATE_DISABLED = 0, - STATS_STATE_ENABLED, - STATS_STATE_MAX -}; - -struct bnx2x_eth_stats { - u32 total_bytes_received_hi; - u32 total_bytes_received_lo; - u32 total_bytes_transmitted_hi; - u32 total_bytes_transmitted_lo; - u32 total_unicast_packets_received_hi; - u32 total_unicast_packets_received_lo; - u32 total_multicast_packets_received_hi; - u32 total_multicast_packets_received_lo; - u32 total_broadcast_packets_received_hi; - u32 total_broadcast_packets_received_lo; - u32 total_unicast_packets_transmitted_hi; - u32 total_unicast_packets_transmitted_lo; - u32 total_multicast_packets_transmitted_hi; - u32 total_multicast_packets_transmitted_lo; - u32 total_broadcast_packets_transmitted_hi; - u32 total_broadcast_packets_transmitted_lo; - u32 valid_bytes_received_hi; - u32 valid_bytes_received_lo; - - u32 error_bytes_received_hi; - u32 error_bytes_received_lo; - u32 etherstatsoverrsizepkts_hi; - u32 etherstatsoverrsizepkts_lo; - u32 no_buff_discard_hi; - u32 no_buff_discard_lo; - - u32 rx_stat_ifhcinbadoctets_hi; - u32 rx_stat_ifhcinbadoctets_lo; - u32 tx_stat_ifhcoutbadoctets_hi; - u32 tx_stat_ifhcoutbadoctets_lo; - u32 rx_stat_dot3statsfcserrors_hi; - u32 rx_stat_dot3statsfcserrors_lo; - u32 rx_stat_dot3statsalignmenterrors_hi; - u32 rx_stat_dot3statsalignmenterrors_lo; - u32 rx_stat_dot3statscarriersenseerrors_hi; - u32 rx_stat_dot3statscarriersenseerrors_lo; - u32 rx_stat_falsecarriererrors_hi; - u32 rx_stat_falsecarriererrors_lo; - u32 rx_stat_etherstatsundersizepkts_hi; - u32 rx_stat_etherstatsundersizepkts_lo; - u32 rx_stat_dot3statsframestoolong_hi; - u32 rx_stat_dot3statsframestoolong_lo; - u32 rx_stat_etherstatsfragments_hi; - u32 rx_stat_etherstatsfragments_lo; - u32 rx_stat_etherstatsjabbers_hi; - u32 rx_stat_etherstatsjabbers_lo; - u32 rx_stat_maccontrolframesreceived_hi; - u32 rx_stat_maccontrolframesreceived_lo; - u32 rx_stat_bmac_xpf_hi; - u32 rx_stat_bmac_xpf_lo; - u32 rx_stat_bmac_xcf_hi; - u32 rx_stat_bmac_xcf_lo; - u32 rx_stat_xoffstateentered_hi; - u32 rx_stat_xoffstateentered_lo; - u32 rx_stat_xonpauseframesreceived_hi; - u32 rx_stat_xonpauseframesreceived_lo; - u32 rx_stat_xoffpauseframesreceived_hi; - u32 rx_stat_xoffpauseframesreceived_lo; - u32 tx_stat_outxonsent_hi; - u32 tx_stat_outxonsent_lo; - u32 tx_stat_outxoffsent_hi; - u32 tx_stat_outxoffsent_lo; - u32 tx_stat_flowcontroldone_hi; - u32 tx_stat_flowcontroldone_lo; - u32 tx_stat_etherstatscollisions_hi; - u32 tx_stat_etherstatscollisions_lo; - u32 tx_stat_dot3statssinglecollisionframes_hi; - u32 tx_stat_dot3statssinglecollisionframes_lo; - u32 tx_stat_dot3statsmultiplecollisionframes_hi; - u32 tx_stat_dot3statsmultiplecollisionframes_lo; - u32 tx_stat_dot3statsdeferredtransmissions_hi; - u32 tx_stat_dot3statsdeferredtransmissions_lo; - u32 tx_stat_dot3statsexcessivecollisions_hi; - u32 tx_stat_dot3statsexcessivecollisions_lo; - u32 tx_stat_dot3statslatecollisions_hi; - u32 tx_stat_dot3statslatecollisions_lo; - u32 tx_stat_etherstatspkts64octets_hi; - u32 tx_stat_etherstatspkts64octets_lo; - u32 tx_stat_etherstatspkts65octetsto127octets_hi; - u32 tx_stat_etherstatspkts65octetsto127octets_lo; - u32 tx_stat_etherstatspkts128octetsto255octets_hi; - u32 tx_stat_etherstatspkts128octetsto255octets_lo; - u32 tx_stat_etherstatspkts256octetsto511octets_hi; - u32 tx_stat_etherstatspkts256octetsto511octets_lo; - u32 tx_stat_etherstatspkts512octetsto1023octets_hi; - u32 tx_stat_etherstatspkts512octetsto1023octets_lo; - u32 tx_stat_etherstatspkts1024octetsto1522octets_hi; - u32 tx_stat_etherstatspkts1024octetsto1522octets_lo; - u32 tx_stat_etherstatspktsover1522octets_hi; - u32 tx_stat_etherstatspktsover1522octets_lo; - u32 tx_stat_bmac_2047_hi; - u32 tx_stat_bmac_2047_lo; - u32 tx_stat_bmac_4095_hi; - u32 tx_stat_bmac_4095_lo; - u32 tx_stat_bmac_9216_hi; - u32 tx_stat_bmac_9216_lo; - u32 tx_stat_bmac_16383_hi; - u32 tx_stat_bmac_16383_lo; - u32 tx_stat_dot3statsinternalmactransmiterrors_hi; - u32 tx_stat_dot3statsinternalmactransmiterrors_lo; - u32 tx_stat_bmac_ufl_hi; - u32 tx_stat_bmac_ufl_lo; - - u32 pause_frames_received_hi; - u32 pause_frames_received_lo; - u32 pause_frames_sent_hi; - u32 pause_frames_sent_lo; - - u32 etherstatspkts1024octetsto1522octets_hi; - u32 etherstatspkts1024octetsto1522octets_lo; - u32 etherstatspktsover1522octets_hi; - u32 etherstatspktsover1522octets_lo; - - u32 brb_drop_hi; - u32 brb_drop_lo; - u32 brb_truncate_hi; - u32 brb_truncate_lo; - - u32 mac_filter_discard; - u32 xxoverflow_discard; - u32 brb_truncate_discard; - u32 mac_discard; - - u32 driver_xoff; - u32 rx_err_discard_pkt; - u32 rx_skb_alloc_failed; - u32 hw_csum_err; - - u32 nig_timer_max; -}; - -#define BNX2X_NUM_STATS 43 -#define STATS_OFFSET32(stat_name) \ - (offsetof(struct bnx2x_eth_stats, stat_name) / 4) - #ifdef BCM_CNIC #define MAX_CONTEXT 15 @@ -1006,6 +805,8 @@ struct bnx2x { int multi_mode; int num_queues; + int disable_tpa; + int int_mode; u32 rx_mode; #define BNX2X_RX_MODE_NONE 0 @@ -1062,6 +863,10 @@ struct bnx2x { /* used to synchronize stats collecting */ int stats_state; + + /* used for synchronization of concurrent threads statistics handling */ + spinlock_t stats_lock; + /* used by dmae command loader */ struct dmae_command stats_dmae; int executer_idx; @@ -1130,6 +935,10 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command); void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val); void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr, u32 addr, u32 len); +void bnx2x_calc_fc_adv(struct bnx2x *bp); +int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, + u32 data_hi, u32 data_lo, int common); +void bnx2x_update_coalesce(struct bnx2x *bp); static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms, int wait) @@ -1371,6 +1180,18 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms, #define BNX2X_VPD_LEN 128 #define VENDOR_ID_LEN 4 +#ifdef BNX2X_MAIN +#define BNX2X_EXTERN +#else +#define BNX2X_EXTERN extern +#endif + +BNX2X_EXTERN int load_count[3]; /* 0-common, 1-port0, 2-port1 */ + /* MISC_REG_RESET_REG - this is here for the hsi to work don't touch */ +extern void bnx2x_set_ethtool_ops(struct net_device *netdev); + +void bnx2x_post_dmae(struct bnx2x *bp, struct dmae_command *dmae, int idx); + #endif /* bnx2x.h */ diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c new file mode 100644 index 00000000000..02bf710629a --- /dev/null +++ b/drivers/net/bnx2x/bnx2x_cmn.c @@ -0,0 +1,2252 @@ +/* bnx2x_cmn.c: Broadcom Everest network driver. + * + * Copyright (c) 2007-2010 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * Maintained by: Eilon Greenstein <eilong@broadcom.com> + * Written by: Eliezer Tamir + * Based on code from Michael Chan's bnx2 driver + * UDP CSUM errata workaround by Arik Gendelman + * Slowpath and fastpath rework by Vladislav Zolotarov + * Statistics and Link management by Yitchak Gertner + * + */ + + +#include <linux/etherdevice.h> +#include <linux/ip.h> +#include <linux/ipv6.h> +#include <net/ip6_checksum.h> +#include "bnx2x_cmn.h" + +#ifdef BCM_VLAN +#include <linux/if_vlan.h> +#endif + +static int bnx2x_poll(struct napi_struct *napi, int budget); + +/* free skb in the packet ring at pos idx + * return idx of last bd freed + */ +static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp, + u16 idx) +{ + struct sw_tx_bd *tx_buf = &fp->tx_buf_ring[idx]; + struct eth_tx_start_bd *tx_start_bd; + struct eth_tx_bd *tx_data_bd; + struct sk_buff *skb = tx_buf->skb; + u16 bd_idx = TX_BD(tx_buf->first_bd), new_cons; + int nbd; + + /* prefetch skb end pointer to speedup dev_kfree_skb() */ + prefetch(&skb->end); + + DP(BNX2X_MSG_OFF, "pkt_idx %d buff @(%p)->skb %p\n", + idx, tx_buf, skb); + + /* unmap first bd */ + DP(BNX2X_MSG_OFF, "free bd_idx %d\n", bd_idx); + tx_start_bd = &fp->tx_desc_ring[bd_idx].start_bd; + dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd), + BD_UNMAP_LEN(tx_start_bd), PCI_DMA_TODEVICE); + + nbd = le16_to_cpu(tx_start_bd->nbd) - 1; +#ifdef BNX2X_STOP_ON_ERROR + if ((nbd - 1) > (MAX_SKB_FRAGS + 2)) { + BNX2X_ERR("BAD nbd!\n"); + bnx2x_panic(); + } +#endif + new_cons = nbd + tx_buf->first_bd; + + /* Get the next bd */ + bd_idx = TX_BD(NEXT_TX_IDX(bd_idx)); + + /* Skip a parse bd... */ + --nbd; + bd_idx = TX_BD(NEXT_TX_IDX(bd_idx)); + + /* ...and the TSO split header bd since they have no mapping */ + if (tx_buf->flags & BNX2X_TSO_SPLIT_BD) { + --nbd; + bd_idx = TX_BD(NEXT_TX_IDX(bd_idx)); + } + + /* now free frags */ + while (nbd > 0) { + + DP(BNX2X_MSG_OFF, "free frag bd_idx %d\n", bd_idx); + tx_data_bd = &fp->tx_desc_ring[bd_idx].reg_bd; + dma_unmap_page(&bp->pdev->dev, BD_UNMAP_ADDR(tx_data_bd), + BD_UNMAP_LEN(tx_data_bd), DMA_TO_DEVICE); + if (--nbd) + bd_idx = TX_BD(NEXT_TX_IDX(bd_idx)); + } + + /* release skb */ + WARN_ON(!skb); + dev_kfree_skb(skb); + tx_buf->first_bd = 0; + tx_buf->skb = NULL; + + return new_cons; +} + +int bnx2x_tx_int(struct bnx2x_fastpath *fp) +{ + struct bnx2x *bp = fp->bp; + struct netdev_queue *txq; + u16 hw_cons, sw_cons, bd_cons = fp->tx_bd_cons; + +#ifdef BNX2X_STOP_ON_ERROR + if (unlikely(bp->panic)) + return -1; +#endif + + txq = netdev_get_tx_queue(bp->dev, fp->index); + hw_cons = le16_to_cpu(*fp->tx_cons_sb); + sw_cons = fp->tx_pkt_cons; + + while (sw_cons != hw_cons) { + u16 pkt_cons; + + pkt_cons = TX_BD(sw_cons); + + /* prefetch(bp->tx_buf_ring[pkt_cons].skb); */ + + DP(NETIF_MSG_TX_DONE, "hw_cons %u sw_cons %u pkt_cons %u\n", + hw_cons, sw_cons, pkt_cons); + +/* if (NEXT_TX_IDX(sw_cons) != hw_cons) { + rmb(); + prefetch(fp->tx_buf_ring[NEXT_TX_IDX(sw_cons)].skb); + } +*/ + bd_cons = bnx2x_free_tx_pkt(bp, fp, pkt_cons); + sw_cons++; + } + + fp->tx_pkt_cons = sw_cons; + fp->tx_bd_cons = bd_cons; + + /* Need to make the tx_bd_cons update visible to start_xmit() + * before checking for netif_tx_queue_stopped(). Without the + * memory barrier, there is a small possibility that + * start_xmit() will miss it and cause the queue to be stopped + * forever. + */ + smp_mb(); + + /* TBD need a thresh? */ + if (unlikely(netif_tx_queue_stopped(txq))) { + /* Taking tx_lock() is needed to prevent reenabling the queue + * while it's empty. This could have happen if rx_action() gets + * suspended in bnx2x_tx_int() after the condition before + * netif_tx_wake_queue(), while tx_action (bnx2x_start_xmit()): + * + * stops the queue->sees fresh tx_bd_cons->releases the queue-> + * sends some packets consuming the whole queue again-> + * stops the queue + */ + + __netif_tx_lock(txq, smp_processor_id()); + + if ((netif_tx_queue_stopped(txq)) && + (bp->state == BNX2X_STATE_OPEN) && + (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3)) + netif_tx_wake_queue(txq); + + __netif_tx_unlock(txq); + } + return 0; +} + +static inline void bnx2x_update_last_max_sge(struct bnx2x_fastpath *fp, + u16 idx) +{ + u16 last_max = fp->last_max_sge; + + if (SUB_S16(idx, last_max) > 0) + fp->last_max_sge = idx; +} + +static void bnx2x_update_sge_prod(struct bnx2x_fastpath *fp, + struct eth_fast_path_rx_cqe *fp_cqe) +{ + struct bnx2x *bp = fp->bp; + u16 sge_len = SGE_PAGE_ALIGN(le16_to_cpu(fp_cqe->pkt_len) - + le16_to_cpu(fp_cqe->len_on_bd)) >> + SGE_PAGE_SHIFT; + u16 last_max, last_elem, first_elem; + u16 delta = 0; + u16 i; + + if (!sge_len) + return; + + /* First mark all used pages */ + for (i = 0; i < sge_len; i++) + SGE_MASK_CLEAR_BIT(fp, RX_SGE(le16_to_cpu(fp_cqe->sgl[i]))); + + DP(NETIF_MSG_RX_STATUS, "fp_cqe->sgl[%d] = %d\n", + sge_len - 1, le16_to_cpu(fp_cqe->sgl[sge_len - 1])); + + /* Here we assume that the last SGE index is the biggest */ + prefetch((void *)(fp->sge_mask)); + bnx2x_update_last_max_sge(fp, le16_to_cpu(fp_cqe->sgl[sge_len - 1])); + + last_max = RX_SGE(fp->last_max_sge); + last_elem = last_max >> RX_SGE_MASK_ELEM_SHIFT; + first_elem = RX_SGE(fp->rx_sge_prod) >> RX_SGE_MASK_ELEM_SHIFT; + + /* If ring is not full */ + if (last_elem + 1 != first_elem) + last_elem++; + + /* Now update the prod */ + for (i = first_elem; i != last_elem; i = NEXT_SGE_MASK_ELEM(i)) { + if (likely(fp->sge_mask[i])) + break; + + fp->sge_mask[i] = RX_SGE_MASK_ELEM_ONE_MASK; + delta += RX_SGE_MASK_ELEM_SZ; + } + + if (delta > 0) { + fp->rx_sge_prod += delta; + /* clear page-end entries */ + bnx2x_clear_sge_mask_next_elems(fp); + } + + DP(NETIF_MSG_RX_STATUS, + "fp->last_max_sge = %d fp->rx_sge_prod = %d\n", + fp->last_max_sge, fp->rx_sge_prod); +} + +static void bnx2x_tpa_start(struct bnx2x_fastpath *fp, u16 queue, + struct sk_buff *skb, u16 cons, u16 prod) +{ + struct bnx2x *bp = fp->bp; + struct sw_rx_bd *cons_rx_buf = &fp->rx_buf_ring[cons]; + struct sw_rx_bd *prod_rx_buf = &fp->rx_buf_ring[prod]; + struct eth_rx_bd *prod_bd = &fp->rx_desc_ring[prod]; + dma_addr_t mapping; + + /* move empty skb from pool to prod and map it */ + prod_rx_buf->skb = fp->tpa_pool[queue].skb; + mapping = dma_map_single(&bp->pdev->dev, fp->tpa_pool[queue].skb->data, + bp->rx_buf_size, DMA_FROM_DEVICE); + dma_unmap_addr_set(prod_rx_buf, mapping, mapping); + + /* move partial skb from cons to pool (don't unmap yet) */ + fp->tpa_pool[queue] = *cons_rx_buf; + + /* mark bin state as start - print error if current state != stop */ + if (fp->tpa_state[queue] != BNX2X_TPA_STOP) + BNX2X_ERR("start of bin not in stop [%d]\n", queue); + + fp->tpa_state[queue] = BNX2X_TPA_START; + + /* point prod_bd to new skb */ + prod_bd->addr_hi = cpu_to_le32(U64_HI(mapping)); + prod_bd->addr_lo = cpu_to_le32(U64_LO(mapping)); + +#ifdef BNX2X_STOP_ON_ERROR + fp->tpa_queue_used |= (1 << queue); +#ifdef _ASM_GENERIC_INT_L64_H + DP(NETIF_MSG_RX_STATUS, "fp->tpa_queue_used = 0x%lx\n", +#else + DP(NETIF_MSG_RX_STATUS, "fp->tpa_queue_used = 0x%llx\n", +#endif + fp->tpa_queue_used); +#endif +} + +static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp, + struct sk_buff *skb, + struct eth_fast_path_rx_cqe *fp_cqe, + u16 cqe_idx) +{ + struct sw_rx_page *rx_pg, old_rx_pg; + u16 len_on_bd = le16_to_cpu(fp_cqe->len_on_bd); + u32 i, frag_len, frag_size, pages; + int err; + int j; + + frag_size = le16_to_cpu(fp_cqe->pkt_len) - len_on_bd; + pages = SGE_PAGE_ALIGN(frag_size) >> SGE_PAGE_SHIFT; + + /* This is needed in order to enable forwarding support */ + if (frag_size) + skb_shinfo(skb)->gso_size = min((u32)SGE_PAGE_SIZE, + max(frag_size, (u32)len_on_bd)); + +#ifdef BNX2X_STOP_ON_ERROR + if (pages > min_t(u32, 8, MAX_SKB_FRAGS)*SGE_PAGE_SIZE*PAGES_PER_SGE) { + BNX2X_ERR("SGL length is too long: %d. CQE index is %d\n", + pages, cqe_idx); + BNX2X_ERR("fp_cqe->pkt_len = %d fp_cqe->len_on_bd = %d\n", + fp_cqe->pkt_len, len_on_bd); + bnx2x_panic(); + return -EINVAL; + } +#endif + + /* Run through the SGL and compose the fragmented skb */ + for (i = 0, j = 0; i < pages; i += PAGES_PER_SGE, j++) { + u16 sge_idx = RX_SGE(le16_to_cpu(fp_cqe->sgl[j])); + + /* FW gives the indices of the SGE as if the ring is an array + (meaning that "next" element will consume 2 indices) */ + frag_len = min(frag_size, (u32)(SGE_PAGE_SIZE*PAGES_PER_SGE)); + rx_pg = &fp->rx_page_ring[sge_idx]; + old_rx_pg = *rx_pg; + + /* If we fail to allocate a substitute page, we simply stop + where we are and drop the whole packet */ + err = bnx2x_alloc_rx_sge(bp, fp, sge_idx); + if (unlikely(err)) { + fp->eth_q_stats.rx_skb_alloc_failed++; + return err; + } + + /* Unmap the page as we r going to pass it to the stack */ + dma_unmap_page(&bp->pdev->dev, + dma_unmap_addr(&old_rx_pg, mapping), + SGE_PAGE_SIZE*PAGES_PER_SGE, DMA_FROM_DEVICE); + + /* Add one frag and update the appropriate fields in the skb */ + skb_fill_page_desc(skb, j, old_rx_pg.page, 0, frag_len); + + skb->data_len += frag_len; + skb->truesize += frag_len; + skb->len += frag_len; + + frag_size -= frag_len; + } + + return 0; +} + +static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp, + u16 queue, int pad, int len, union eth_rx_cqe *cqe, + u16 cqe_idx) +{ + struct sw_rx_bd *rx_buf = &fp->tpa_pool[queue]; + struct sk_buff *skb = rx_buf->skb; + /* alloc new skb */ + struct sk_buff *new_skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size); + + /* Unmap skb in the pool anyway, as we are going to change + pool entry status to BNX2X_TPA_STOP even if new skb allocation + fails. */ + dma_unmap_single(&bp->pdev->dev, dma_unmap_addr(rx_buf, mapping), + bp->rx_buf_size, DMA_FROM_DEVICE); + + if (likely(new_skb)) { + /* fix ip xsum and give it to the stack */ + /* (no need to map the new skb) */ +#ifdef BCM_VLAN + int is_vlan_cqe = + (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) & + PARSING_FLAGS_VLAN); + int is_not_hwaccel_vlan_cqe = + (is_vlan_cqe && (!(bp->flags & HW_VLAN_RX_FLAG))); +#endif + + prefetch(skb); + prefetch(((char *)(skb)) + 128); + +#ifdef BNX2X_STOP_ON_ERROR + if (pad + len > bp->rx_buf_size) { + BNX2X_ERR("skb_put is about to fail... " + "pad %d len %d rx_buf_size %d\n", + pad, len, bp->rx_buf_size); + bnx2x_panic(); + return; + } +#endif + + skb_reserve(skb, pad); + skb_put(skb, len); + + skb->protocol = eth_type_trans(skb, bp->dev); + skb->ip_summed = CHECKSUM_UNNECESSARY; + + { + struct iphdr *iph; + + iph = (struct iphdr *)skb->data; +#ifdef BCM_VLAN + /* If there is no Rx VLAN offloading - + take VLAN tag into an account */ + if (unlikely(is_not_hwaccel_vlan_cqe)) + iph = (struct iphdr *)((u8 *)iph + VLAN_HLEN); +#endif + iph->check = 0; + iph->check = ip_fast_csum((u8 *)iph, iph->ihl); + } + + if (!bnx2x_fill_frag_skb(bp, fp, skb, + &cqe->fast_path_cqe, cqe_idx)) { +#ifdef BCM_VLAN + if ((bp->vlgrp != NULL) && is_vlan_cqe && + (!is_not_hwaccel_vlan_cqe)) + vlan_gro_receive(&fp->napi, bp->vlgrp, + le16_to_cpu(cqe->fast_path_cqe. + vlan_tag), skb); + else +#endif + napi_gro_receive(&fp->napi, skb); + } else { + DP(NETIF_MSG_RX_STATUS, "Failed to allocate new pages" + " - dropping packet!\n"); + dev_kfree_skb(skb); + } + + + /* put new skb in bin */ + fp->tpa_pool[queue].skb = new_skb; + + } else { + /* else drop the packet and keep the buffer in the bin */ + DP(NETIF_MSG_RX_STATUS, + "Failed to allocate new skb - dropping packet!\n"); + fp->eth_q_stats.rx_skb_alloc_failed++; + } + + fp->tpa_state[queue] = BNX2X_TPA_STOP; +} + +/* Set Toeplitz hash value in the skb using the value from the + * CQE (calculated by HW). + */ +static inline void bnx2x_set_skb_rxhash(struct bnx2x *bp, union eth_rx_cqe *cqe, + struct sk_buff *skb) +{ + /* Set Toeplitz hash from CQE */ + if ((bp->dev->features & NETIF_F_RXHASH) && + (cqe->fast_path_cqe.status_flags & + ETH_FAST_PATH_RX_CQE_RSS_HASH_FLG)) + skb->rxhash = + le32_to_cpu(cqe->fast_path_cqe.rss_hash_result); +} + +int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) +{ + struct bnx2x *bp = fp->bp; + u16 bd_cons, bd_prod, bd_prod_fw, comp_ring_cons; + u16 hw_comp_cons, sw_comp_cons, sw_comp_prod; + int rx_pkt = 0; + +#ifdef BNX2X_STOP_ON_ERROR + if (unlikely(bp->panic)) + return 0; +#endif + + /* CQ "next element" is of the size of the regular element, + that's why it's ok here */ + hw_comp_cons = le16_to_cpu(*fp->rx_cons_sb); + if ((hw_comp_cons & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT) + hw_comp_cons++; + + bd_cons = fp->rx_bd_cons; + bd_prod = fp->rx_bd_prod; + bd_prod_fw = bd_prod; + sw_comp_cons = fp->rx_comp_cons; + sw_comp_prod = fp->rx_comp_prod; + + /* Memory barrier necessary as speculative reads of the rx + * buffer can be ahead of the index in the status block + */ + rmb(); + + DP(NETIF_MSG_RX_STATUS, + "queue[%d]: hw_comp_cons %u sw_comp_cons %u\n", + fp->index, hw_comp_cons, sw_comp_cons); + + while (sw_comp_cons != hw_comp_cons) { + struct sw_rx_bd *rx_buf = NULL; + struct sk_buff *skb; + union eth_rx_cqe *cqe; + u8 cqe_fp_flags; + u16 len, pad; + + comp_ring_cons = RCQ_BD(sw_comp_cons); + bd_prod = RX_BD(bd_prod); + bd_cons = RX_BD(bd_cons); + + /* Prefetch the page containing the BD descriptor + at producer's index. It will be needed when new skb is + allocated */ + prefetch((void *)(PAGE_ALIGN((unsigned long) + (&fp->rx_desc_ring[bd_prod])) - + PAGE_SIZE + 1)); + + cqe = &fp->rx_comp_ring[comp_ring_cons]; + cqe_fp_flags = cqe->fast_path_cqe.type_error_flags; + + DP(NETIF_MSG_RX_STATUS, "CQE type %x err %x status %x" + " queue %x vlan %x len %u\n", CQE_TYPE(cqe_fp_flags), + cqe_fp_flags, cqe->fast_path_cqe.status_flags, + le32_to_cpu(cqe->fast_path_cqe.rss_hash_result), + le16_to_cpu(cqe->fast_path_cqe.vlan_tag), + le16_to_cpu(cqe->fast_path_cqe.pkt_len)); + + /* is this a slowpath msg? */ + if (unlikely(CQE_TYPE(cqe_fp_flags))) { + bnx2x_sp_event(fp, cqe); + goto next_cqe; + + /* this is an rx packet */ + } else { + rx_buf = &fp->rx_buf_ring[bd_cons]; + skb = rx_buf->skb; + prefetch(skb); + len = le16_to_cpu(cqe->fast_path_cqe.pkt_len); + pad = cqe->fast_path_cqe.placement_offset; + + /* If CQE is marked both TPA_START and TPA_END + it is a non-TPA CQE */ + if ((!fp->disable_tpa) && + (TPA_TYPE(cqe_fp_flags) != + (TPA_TYPE_START | TPA_TYPE_END))) { + u16 queue = cqe->fast_path_cqe.queue_index; + + if (TPA_TYPE(cqe_fp_flags) == TPA_TYPE_START) { + DP(NETIF_MSG_RX_STATUS, + "calling tpa_start on queue %d\n", + queue); + + bnx2x_tpa_start(fp, queue, skb, + bd_cons, bd_prod); + + /* Set Toeplitz hash for an LRO skb */ + bnx2x_set_skb_rxhash(bp, cqe, skb); + + goto next_rx; + } + + if (TPA_TYPE(cqe_fp_flags) == TPA_TYPE_END) { + DP(NETIF_MSG_RX_STATUS, + "calling tpa_stop on queue %d\n", + queue); + + if (!BNX2X_RX_SUM_FIX(cqe)) + BNX2X_ERR("STOP on none TCP " + "data\n"); + + /* This is a size of the linear data + on this skb */ + len = le16_to_cpu(cqe->fast_path_cqe. + len_on_bd); + bnx2x_tpa_stop(bp, fp, queue, pad, + len, cqe, comp_ring_cons); +#ifdef BNX2X_STOP_ON_ERROR + if (bp->panic) + return 0; +#endif + + bnx2x_update_sge_prod(fp, + &cqe->fast_path_cqe); + goto next_cqe; + } + } + + dma_sync_single_for_device(&bp->pdev->dev, + dma_unmap_addr(rx_buf, mapping), + pad + RX_COPY_THRESH, + DMA_FROM_DEVICE); + prefetch(((char *)(skb)) + 128); + + /* is this an error packet? */ + if (unlikely(cqe_fp_flags & ETH_RX_ERROR_FALGS)) { + DP(NETIF_MSG_RX_ERR, + "ERROR flags %x rx packet %u\n", + cqe_fp_flags, sw_comp_cons); + fp->eth_q_stats.rx_err_discard_pkt++; + goto reuse_rx; + } + + /* Since we don't have a jumbo ring + * copy small packets if mtu > 1500 + */ + if ((bp->dev->mtu > ETH_MAX_PACKET_SIZE) && + (len <= RX_COPY_THRESH)) { + struct sk_buff *new_skb; + + new_skb = netdev_alloc_skb(bp->dev, + len + pad); + if (new_skb == NULL) { + DP(NETIF_MSG_RX_ERR, + "ERROR packet dropped " + "because of alloc failure\n"); + fp->eth_q_stats.rx_skb_alloc_failed++; + goto reuse_rx; + } + + /* aligned copy */ + skb_copy_from_linear_data_offset(skb, pad, + new_skb->data + pad, len); + skb_reserve(new_skb, pad); + skb_put(new_skb, len); + + bnx2x_reuse_rx_skb(fp, skb, bd_cons, bd_prod); + + skb = new_skb; + + } else + if (likely(bnx2x_alloc_rx_skb(bp, fp, bd_prod) == 0)) { + dma_unmap_single(&bp->pdev->dev, + dma_unmap_addr(rx_buf, mapping), + bp->rx_buf_size, + DMA_FROM_DEVICE); + skb_reserve(skb, pad); + skb_put(skb, len); + + } else { + DP(NETIF_MSG_RX_ERR, + "ERROR packet dropped because " + "of alloc failure\n"); + fp->eth_q_stats.rx_skb_alloc_failed++; +reuse_rx: + bnx2x_reuse_rx_skb(fp, skb, bd_cons, bd_prod); + goto next_rx; + } + + skb->protocol = eth_type_trans(skb, bp->dev); + + /* Set Toeplitz hash for a none-LRO skb */ + bnx2x_set_skb_rxhash(bp, cqe, skb); + + skb->ip_summed = CHECKSUM_NONE; + if (bp->rx_csum) { + if (likely(BNX2X_RX_CSUM_OK(cqe))) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + fp->eth_q_stats.hw_csum_err++; + } + } + + skb_record_rx_queue(skb, fp->index); + +#ifdef BCM_VLAN + if ((bp->vlgrp != NULL) && (bp->flags & HW_VLAN_RX_FLAG) && + (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) & + PARSING_FLAGS_VLAN)) + vlan_gro_receive(&fp->napi, bp->vlgrp, + le16_to_cpu(cqe->fast_path_cqe.vlan_tag), skb); + else +#endif + napi_gro_receive(&fp->napi, skb); + + +next_rx: + rx_buf->skb = NULL; + + bd_cons = NEXT_RX_IDX(bd_cons); + bd_prod = NEXT_RX_IDX(bd_prod); + bd_prod_fw = NEXT_RX_IDX(bd_prod_fw); + rx_pkt++; +next_cqe: + sw_comp_prod = NEXT_RCQ_IDX(sw_comp_prod); + sw_comp_cons = NEXT_RCQ_IDX(sw_comp_cons); + + if (rx_pkt == budget) + break; + } /* while */ + + fp->rx_bd_cons = bd_cons; + fp->rx_bd_prod = bd_prod_fw; + fp->rx_comp_cons = sw_comp_cons; + fp->rx_comp_prod = sw_comp_prod; + + /* Update producers */ + bnx2x_update_rx_prod(bp, fp, bd_prod_fw, sw_comp_prod, + fp->rx_sge_prod); + + fp->rx_pkt += rx_pkt; + fp->rx_calls++; + + return rx_pkt; +} + +static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie) +{ + struct bnx2x_fastpath *fp = fp_cookie; + struct bnx2x *bp = fp->bp; + + /* Return here if interrupt is disabled */ + if (unlikely(atomic_read(&bp->intr_sem) != 0)) { + DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n"); + return IRQ_HANDLED; + } + + DP(BNX2X_MSG_FP, "got an MSI-X interrupt on IDX:SB [%d:%d]\n", + fp->index, fp->sb_id); + bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID, 0, IGU_INT_DISABLE, 0); + +#ifdef BNX2X_STOP_ON_ERROR + if (unlikely(bp->panic)) + return IRQ_HANDLED; +#endif + + /* Handle Rx and Tx according to MSI-X vector */ + prefetch(fp->rx_cons_sb); + prefetch(fp->tx_cons_sb); + prefetch(&fp->status_blk->u_status_block.status_block_index); + prefetch(&fp->status_blk->c_status_block.status_block_index); + napi_schedule(&bnx2x_fp(bp, fp->index, napi)); + + return IRQ_HANDLED; +} + + +/* HW Lock for shared dual port PHYs */ +void bnx2x_acquire_phy_lock(struct bnx2x *bp) +{ + mutex_lock(&bp->port.phy_mutex); + + if (bp->port.need_hw_lock) + bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_MDIO); +} + +void bnx2x_release_phy_lock(struct bnx2x *bp) +{ + if (bp->port.need_hw_lock) + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_MDIO); + + mutex_unlock(&bp->port.phy_mutex); +} + +void bnx2x_link_report(struct bnx2x *bp) +{ + if (bp->flags & MF_FUNC_DIS) { + netif_carrier_off(bp->dev); + netdev_err(bp->dev, "NIC Link is Down\n"); + return; + } + + if (bp->link_vars.link_up) { + u16 line_speed; + + if (bp->state == BNX2X_STATE_OPEN) + netif_carrier_on(bp->dev); + netdev_info(bp->dev, "NIC Link is Up, "); + + line_speed = bp->link_vars.line_speed; + if (IS_E1HMF(bp)) { + u16 vn_max_rate; + + vn_max_rate = + ((bp->mf_config & FUNC_MF_CFG_MAX_BW_MASK) >> + FUNC_MF_CFG_MAX_BW_SHIFT) * 100; + if (vn_max_rate < line_speed) + line_speed = vn_max_rate; + } + pr_cont("%d Mbps ", line_speed); + + if (bp->link_vars.duplex == DUPLEX_FULL) + pr_cont("full duplex"); + else + pr_cont("half duplex"); + + if (bp->link_vars.flow_ctrl != BNX2X_FLOW_CTRL_NONE) { + if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) { + pr_cont(", receive "); + if (bp->link_vars.flow_ctrl & + BNX2X_FLOW_CTRL_TX) + pr_cont("& transmit "); + } else { + pr_cont(", transmit "); + } + pr_cont("flow control ON"); + } + pr_cont("\n"); + + } else { /* link_down */ + netif_carrier_off(bp->dev); + netdev_err(bp->dev, "NIC Link is Down\n"); + } +} + +void bnx2x_init_rx_rings(struct bnx2x *bp) +{ + int func = BP_FUNC(bp); + int max_agg_queues = CHIP_IS_E1(bp) ? ETH_MAX_AGGREGATION_QUEUES_E1 : + ETH_MAX_AGGREGATION_QUEUES_E1H; + u16 ring_prod, cqe_ring_prod; + int i, j; + + bp->rx_buf_size = bp->dev->mtu + ETH_OVREHEAD + BNX2X_RX_ALIGN; + DP(NETIF_MSG_IFUP, + "mtu %d rx_buf_size %d\n", bp->dev->mtu, bp->rx_buf_size); + + if (bp->flags & TPA_ENABLE_FLAG) { + + for_each_queue(bp, j) { + struct bnx2x_fastpath *fp = &bp->fp[j]; + + for (i = 0; i < max_agg_queues; i++) { + fp->tpa_pool[i].skb = + netdev_alloc_skb(bp->dev, bp->rx_buf_size); + if (!fp->tpa_pool[i].skb) { + BNX2X_ERR("Failed to allocate TPA " + "skb pool for queue[%d] - " + "disabling TPA on this " + "queue!\n", j); + bnx2x_free_tpa_pool(bp, fp, i); + fp->disable_tpa = 1; + break; + } + dma_unmap_addr_set((struct sw_rx_bd *) + &bp->fp->tpa_pool[i], + mapping, 0); + fp->tpa_state[i] = BNX2X_TPA_STOP; + } + } + } + + for_each_queue(bp, j) { + struct bnx2x_fastpath *fp = &bp->fp[j]; + + fp->rx_bd_cons = 0; + fp->rx_cons_sb = BNX2X_RX_SB_INDEX; + fp->rx_bd_cons_sb = BNX2X_RX_SB_BD_INDEX; + + /* "next page" elements initialization */ + /* SGE ring */ + for (i = 1; i <= NUM_RX_SGE_PAGES; i++) { + struct eth_rx_sge *sge; + + sge = &fp->rx_sge_ring[RX_SGE_CNT * i - 2]; + sge->addr_hi = + cpu_to_le32(U64_HI(fp->rx_sge_mapping + + BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES))); + sge->addr_lo = + cpu_to_le32(U64_LO(fp->rx_sge_mapping + + BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES))); + } + + bnx2x_init_sge_ring_bit_mask(fp); + + /* RX BD ring */ + for (i = 1; i <= NUM_RX_RINGS; i++) { + struct eth_rx_bd *rx_bd; + + rx_bd = &fp->rx_desc_ring[RX_DESC_CNT * i - 2]; + rx_bd->addr_hi = + cpu_to_le32(U64_HI(fp->rx_desc_mapping + + BCM_PAGE_SIZE*(i % NUM_RX_RINGS))); + rx_bd->addr_lo = + cpu_to_le32(U64_LO(fp->rx_desc_mapping + + BCM_PAGE_SIZE*(i % NUM_RX_RINGS))); + } + + /* CQ ring */ + for (i = 1; i <= NUM_RCQ_RINGS; i++) { + struct eth_rx_cqe_next_page *nextpg; + + nextpg = (struct eth_rx_cqe_next_page *) + &fp->rx_comp_ring[RCQ_DESC_CNT * i - 1]; + nextpg->addr_hi = + cpu_to_le32(U64_HI(fp->rx_comp_mapping + + BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS))); + nextpg->addr_lo = + cpu_to_le32(U64_LO(fp->rx_comp_mapping + + BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS))); + } + + /* Allocate SGEs and initialize the ring elements */ + for (i = 0, ring_prod = 0; + i < MAX_RX_SGE_CNT*NUM_RX_SGE_PAGES; i++) { + + if (bnx2x_alloc_rx_sge(bp, fp, ring_prod) < 0) { + BNX2X_ERR("was only able to allocate " + "%d rx sges\n", i); + BNX2X_ERR("disabling TPA for queue[%d]\n", j); + /* Cleanup already allocated elements */ + bnx2x_free_rx_sge_range(bp, fp, ring_prod); + bnx2x_free_tpa_pool(bp, fp, max_agg_queues); + fp->disable_tpa = 1; + ring_prod = 0; + break; + } + ring_prod = NEXT_SGE_IDX(ring_prod); + } + fp->rx_sge_prod = ring_prod; + + /* Allocate BDs and initialize BD ring */ + fp->rx_comp_cons = 0; + cqe_ring_prod = ring_prod = 0; + for (i = 0; i < bp->rx_ring_size; i++) { + if (bnx2x_alloc_rx_skb(bp, fp, ring_prod) < 0) { + BNX2X_ERR("was only able to allocate " + "%d rx skbs on queue[%d]\n", i, j); + fp->eth_q_stats.rx_skb_alloc_failed++; + break; + } + ring_prod = NEXT_RX_IDX(ring_prod); + cqe_ring_prod = NEXT_RCQ_IDX(cqe_ring_prod); + WARN_ON(ring_prod <= i); + } + + fp->rx_bd_prod = ring_prod; + /* must not have more available CQEs than BDs */ + fp->rx_comp_prod = min_t(u16, NUM_RCQ_RINGS*RCQ_DESC_CNT, + cqe_ring_prod); + fp->rx_pkt = fp->rx_calls = 0; + + /* Warning! + * this will generate an interrupt (to the TSTORM) + * must only be done after chip is initialized + */ + bnx2x_update_rx_prod(bp, fp, ring_prod, fp->rx_comp_prod, + fp->rx_sge_prod); + if (j != 0) + continue; + + REG_WR(bp, BAR_USTRORM_INTMEM + + USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func), + U64_LO(fp->rx_comp_mapping)); + REG_WR(bp, BAR_USTRORM_INTMEM + + USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func) + 4, + U64_HI(fp->rx_comp_mapping)); + } +} +static void bnx2x_free_tx_skbs(struct bnx2x *bp) +{ + int i; + + for_each_queue(bp, i) { + struct bnx2x_fastpath *fp = &bp->fp[i]; + + u16 bd_cons = fp->tx_bd_cons; + u16 sw_prod = fp->tx_pkt_prod; + u16 sw_cons = fp->tx_pkt_cons; + + while (sw_cons != sw_prod) { + bd_cons = bnx2x_free_tx_pkt(bp, fp, TX_BD(sw_cons)); + sw_cons++; + } + } +} + +static void bnx2x_free_rx_skbs(struct bnx2x *bp) +{ + int i, j; + + for_each_queue(bp, j) { + struct bnx2x_fastpath *fp = &bp->fp[j]; + + for (i = 0; i < NUM_RX_BD; i++) { + struct sw_rx_bd *rx_buf = &fp->rx_buf_ring[i]; + struct sk_buff *skb = rx_buf->skb; + + if (skb == NULL) + continue; + + dma_unmap_single(&bp->pdev->dev, + dma_unmap_addr(rx_buf, mapping), + bp->rx_buf_size, DMA_FROM_DEVICE); + + rx_buf->skb = NULL; + dev_kfree_skb(skb); + } + if (!fp->disable_tpa) + bnx2x_free_tpa_pool(bp, fp, CHIP_IS_E1(bp) ? + ETH_MAX_AGGREGATION_QUEUES_E1 : + ETH_MAX_AGGREGATION_QUEUES_E1H); + } +} + +void bnx2x_free_skbs(struct bnx2x *bp) +{ + bnx2x_free_tx_skbs(bp); + bnx2x_free_rx_skbs(bp); +} + +static void bnx2x_free_msix_irqs(struct bnx2x *bp) +{ + int i, offset = 1; + + free_irq(bp->msix_table[0].vector, bp->dev); + DP(NETIF_MSG_IFDOWN, "released sp irq (%d)\n", + bp->msix_table[0].vector); + +#ifdef BCM_CNIC + offset++; +#endif + for_each_queue(bp, i) { + DP(NETIF_MSG_IFDOWN, "about to release fp #%d->%d irq " + "state %x\n", i, bp->msix_table[i + offset].vector, + bnx2x_fp(bp, i, state)); + + free_irq(bp->msix_table[i + offset].vector, &bp->fp[i]); + } +} + +void bnx2x_free_irq(struct bnx2x *bp, bool disable_only) +{ + if (bp->flags & USING_MSIX_FLAG) { + if (!disable_only) + bnx2x_free_msix_irqs(bp); + pci_disable_msix(bp->pdev); + bp->flags &= ~USING_MSIX_FLAG; + + } else if (bp->flags & USING_MSI_FLAG) { + if (!disable_only) + free_irq(bp->pdev->irq, bp->dev); + pci_disable_msi(bp->pdev); + bp->flags &= ~USING_MSI_FLAG; + + } else if (!disable_only) + free_irq(bp->pdev->irq, bp->dev); +} + +static int bnx2x_enable_msix(struct bnx2x *bp) +{ + int i, rc, offset = 1; + int igu_vec = 0; + + bp->msix_table[0].entry = igu_vec; + DP(NETIF_MSG_IFUP, "msix_table[0].entry = %d (slowpath)\n", igu_vec); + +#ifdef BCM_CNIC + igu_vec = BP_L_ID(bp) + offset; + bp->msix_table[1].entry = igu_vec; + DP(NETIF_MSG_IFUP, "msix_table[1].entry = %d (CNIC)\n", igu_vec); + offset++; +#endif + for_each_queue(bp, i) { + igu_vec = BP_L_ID(bp) + offset + i; + bp->msix_table[i + offset].entry = igu_vec; + DP(NETIF_MSG_IFUP, "msix_table[%d].entry = %d " + "(fastpath #%u)\n", i + offset, igu_vec, i); + } + + rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], + BNX2X_NUM_QUEUES(bp) + offset); + + /* + * reconfigure number of tx/rx queues according to available + * MSI-X vectors + */ + if (rc >= BNX2X_MIN_MSIX_VEC_CNT) { + /* vectors available for FP */ + int fp_vec = rc - BNX2X_MSIX_VEC_FP_START; + + DP(NETIF_MSG_IFUP, + "Trying to use less MSI-X vectors: %d\n", rc); + + rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], rc); + + if (rc) { + DP(NETIF_MSG_IFUP, + "MSI-X is not attainable rc %d\n", rc); + return rc; + } + + bp->num_queues = min(bp->num_queues, fp_vec); + + DP(NETIF_MSG_IFUP, "New queue configuration set: %d\n", + bp->num_queues); + } else if (rc) { + DP(NETIF_MSG_IFUP, "MSI-X is not attainable rc %d\n", rc); + return rc; + } + + bp->flags |= USING_MSIX_FLAG; + + return 0; +} + +static int bnx2x_req_msix_irqs(struct bnx2x *bp) +{ + int i, rc, offset = 1; + + rc = request_irq(bp->msix_table[0].vector, bnx2x_msix_sp_int, 0, + bp->dev->name, bp->dev); + if (rc) { + BNX2X_ERR("request sp irq failed\n"); + return -EBUSY; + } + +#ifdef BCM_CNIC + offset++; +#endif + for_each_queue(bp, i) { + struct bnx2x_fastpath *fp = &bp->fp[i]; + snprintf(fp->name, sizeof(fp->name), "%s-fp-%d", + bp->dev->name, i); + + rc = request_irq(bp->msix_table[i + offset].vector, + bnx2x_msix_fp_int, 0, fp->name, fp); + if (rc) { + BNX2X_ERR("request fp #%d irq failed rc %d\n", i, rc); + bnx2x_free_msix_irqs(bp); + return -EBUSY; + } + + fp->state = BNX2X_FP_STATE_IRQ; + } + + i = BNX2X_NUM_QUEUES(bp); + netdev_info(bp->dev, "using MSI-X IRQs: sp %d fp[%d] %d" + " ... fp[%d] %d\n", + bp->msix_table[0].vector, + 0, bp->msix_table[offset].vector, + i - 1, bp->msix_table[offset + i - 1].vector); + + return 0; +} + +static int bnx2x_enable_msi(struct bnx2x *bp) +{ + int rc; + + rc = pci_enable_msi(bp->pdev); + if (rc) { + DP(NETIF_MSG_IFUP, "MSI is not attainable\n"); + return -1; + } + bp->flags |= USING_MSI_FLAG; + + return 0; +} + +static int bnx2x_req_irq(struct bnx2x *bp) +{ + unsigned long flags; + int rc; + + if (bp->flags & USING_MSI_FLAG) + flags = 0; + else + flags = IRQF_SHARED; + + rc = request_irq(bp->pdev->irq, bnx2x_interrupt, flags, + bp->dev->name, bp->dev); + if (!rc) + bnx2x_fp(bp, 0, state) = BNX2X_FP_STATE_IRQ; + + return rc; +} + +static void bnx2x_napi_enable(struct bnx2x *bp) +{ + int i; + + for_each_queue(bp, i) + napi_enable(&bnx2x_fp(bp, i, napi)); +} + +static void bnx2x_napi_disable(struct bnx2x *bp) +{ + int i; + + for_each_queue(bp, i) + napi_disable(&bnx2x_fp(bp, i, napi)); +} + +void bnx2x_netif_start(struct bnx2x *bp) +{ + int intr_sem; + + intr_sem = atomic_dec_and_test(&bp->intr_sem); + smp_wmb(); /* Ensure that bp->intr_sem update is SMP-safe */ + + if (intr_sem) { + if (netif_running(bp->dev)) { + bnx2x_napi_enable(bp); + bnx2x_int_enable(bp); + if (bp->state == BNX2X_STATE_OPEN) + netif_tx_wake_all_queues(bp->dev); + } + } +} + +void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw) +{ + bnx2x_int_disable_sync(bp, disable_hw); + bnx2x_napi_disable(bp); + netif_tx_disable(bp->dev); +} +static int bnx2x_set_num_queues(struct bnx2x *bp) +{ + int rc = 0; + + switch (bp->int_mode) { + case INT_MODE_INTx: + case INT_MODE_MSI: + bp->num_queues = 1; + DP(NETIF_MSG_IFUP, "set number of queues to 1\n"); + break; + default: + /* Set number of queues according to bp->multi_mode value */ + bnx2x_set_num_queues_msix(bp); + + DP(NETIF_MSG_IFUP, "set number of queues to %d\n", + bp->num_queues); + + /* if we can't use MSI-X we only need one fp, + * so try to enable MSI-X with the requested number of fp's + * and fallback to MSI or legacy INTx with one fp + */ + rc = bnx2x_enable_msix(bp); + if (rc) + /* failed to enable MSI-X */ + bp->num_queues = 1; + break; + } + bp->dev->real_num_tx_queues = bp->num_queues; + return rc; +} + +/* must be called with rtnl_lock */ +int bnx2x_nic_load(struct bnx2x *bp, int load_mode) +{ + u32 load_code; + int i, rc; + +#ifdef BNX2X_STOP_ON_ERROR + if (unlikely(bp->panic)) + return -EPERM; +#endif + + bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD; + + rc = bnx2x_set_num_queues(bp); + + if (bnx2x_alloc_mem(bp)) { + bnx2x_free_irq(bp, true); + return -ENOMEM; + } + + for_each_queue(bp, i) + bnx2x_fp(bp, i, disable_tpa) = + ((bp->flags & TPA_ENABLE_FLAG) == 0); + + for_each_queue(bp, i) + netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi), + bnx2x_poll, 128); + + bnx2x_napi_enable(bp); + + if (bp->flags & USING_MSIX_FLAG) { + rc = bnx2x_req_msix_irqs(bp); + if (rc) { + bnx2x_free_irq(bp, true); + goto load_error1; + } + } else { + /* Fall to INTx if failed to enable MSI-X due to lack of + memory (in bnx2x_set_num_queues()) */ + if ((rc != -ENOMEM) && (bp->int_mode != INT_MODE_INTx)) + bnx2x_enable_msi(bp); + bnx2x_ack_int(bp); + rc = bnx2x_req_irq(bp); + if (rc) { + BNX2X_ERR("IRQ request failed rc %d, aborting\n", rc); + bnx2x_free_irq(bp, true); + goto load_error1; + } + if (bp->flags & USING_MSI_FLAG) { + bp->dev->irq = bp->pdev->irq; + netdev_info(bp->dev, "using MSI IRQ %d\n", + bp->pdev->irq); + } + } + + /* Send LOAD_REQUEST command to MCP + Returns the type of LOAD command: + if it is the first port to be initialized + common blocks should be initialized, otherwise - not + */ + if (!BP_NOMCP(bp)) { + load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ); + if (!load_code) { + BNX2X_ERR("MCP response failure, aborting\n"); + rc = -EBUSY; + goto load_error2; + } + if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED) { + rc = -EBUSY; /* other port in diagnostic mode */ + goto load_error2; + } + + } else { + int port = BP_PORT(bp); + + DP(NETIF_MSG_IFUP, "NO MCP - load counts %d, %d, %d\n", + load_count[0], load_count[1], load_count[2]); + load_count[0]++; + load_count[1 + port]++; + DP(NETIF_MSG_IFUP, "NO MCP - new load counts %d, %d, %d\n", + load_count[0], load_count[1], load_count[2]); + if (load_count[0] == 1) + load_code = FW_MSG_CODE_DRV_LOAD_COMMON; + else if (load_count[1 + port] == 1) + load_code = FW_MSG_CODE_DRV_LOAD_PORT; + else + load_code = FW_MSG_CODE_DRV_LOAD_FUNCTION; + } + + if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) || + (load_code == FW_MSG_CODE_DRV_LOAD_PORT)) + bp->port.pmf = 1; + else + bp->port.pmf = 0; + DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf); + + /* Initialize HW */ + rc = bnx2x_init_hw(bp, load_code); + if (rc) { + BNX2X_ERR("HW init failed, aborting\n"); + bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE); + bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP); + bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE); + goto load_error2; + } + + /* Setup NIC internals and enable interrupts */ + bnx2x_nic_init(bp, load_code); + + if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) && + (bp->common.shmem2_base)) + SHMEM2_WR(bp, dcc_support, + (SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV | + SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV)); + + /* Send LOAD_DONE command to MCP */ + if (!BP_NOMCP(bp)) { + load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE); + if (!load_code) { + BNX2X_ERR("MCP response failure, aborting\n"); + rc = -EBUSY; + goto load_error3; + } + } + + bp->state = BNX2X_STATE_OPENING_WAIT4_PORT; + + rc = bnx2x_setup_leading(bp); + if (rc) { + BNX2X_ERR("Setup leading failed!\n"); +#ifndef BNX2X_STOP_ON_ERROR + goto load_error3; +#else + bp->panic = 1; + return -EBUSY; +#endif + } + + if (CHIP_IS_E1H(bp)) + if (bp->mf_config & FUNC_MF_CFG_FUNC_DISABLED) { + DP(NETIF_MSG_IFUP, "mf_cfg function disabled\n"); + bp->flags |= MF_FUNC_DIS; + } + + if (bp->state == BNX2X_STATE_OPEN) { +#ifdef BCM_CNIC + /* Enable Timer scan */ + REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + BP_PORT(bp)*4, 1); +#endif + for_each_nondefault_queue(bp, i) { + rc = bnx2x_setup_multi(bp, i); + if (rc) +#ifdef BCM_CNIC + goto load_error4; +#else + goto load_error3; +#endif + } + + if (CHIP_IS_E1(bp)) + bnx2x_set_eth_mac_addr_e1(bp, 1); + else + bnx2x_set_eth_mac_addr_e1h(bp, 1); +#ifdef BCM_CNIC + /* Set iSCSI L2 MAC */ + mutex_lock(&bp->cnic_mutex); + if (bp->cnic_eth_dev.drv_state & CNIC_DRV_STATE_REGD) { + bnx2x_set_iscsi_eth_mac_addr(bp, 1); + bp->cnic_flags |= BNX2X_CNIC_FLAG_MAC_SET; + bnx2x_init_sb(bp, bp->cnic_sb, bp->cnic_sb_mapping, + CNIC_SB_ID(bp)); + } + mutex_unlock(&bp->cnic_mutex); +#endif + } + + if (bp->port.pmf) + bnx2x_initial_phy_init(bp, load_mode); + + /* Start fast path */ + switch (load_mode) { + case LOAD_NORMAL: + if (bp->state == BNX2X_STATE_OPEN) { + /* Tx queue should be only reenabled */ + netif_tx_wake_all_queues(bp->dev); + } + /* Initialize the receive filter. */ + bnx2x_set_rx_mode(bp->dev); + break; + + case LOAD_OPEN: + netif_tx_start_all_queues(bp->dev); + if (bp->state != BNX2X_STATE_OPEN) + netif_tx_disable(bp->dev); + /* Initialize the receive filter. */ + bnx2x_set_rx_mode(bp->dev); + break; + + case LOAD_DIAG: + /* Initialize the receive filter. */ + bnx2x_set_rx_mode(bp->dev); + bp->state = BNX2X_STATE_DIAG; + break; + + default: + break; + } + + if (!bp->port.pmf) + bnx2x__link_status_update(bp); + + /* start the timer */ + mod_timer(&bp->timer, jiffies + bp->current_interval); + +#ifdef BCM_CNIC + bnx2x_setup_cnic_irq_info(bp); + if (bp->state == BNX2X_STATE_OPEN) + bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD); +#endif + bnx2x_inc_load_cnt(bp); + + return 0; + +#ifdef BCM_CNIC +load_error4: + /* Disable Timer scan */ + REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + BP_PORT(bp)*4, 0); +#endif +load_error3: + bnx2x_int_disable_sync(bp, 1); + if (!BP_NOMCP(bp)) { + bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP); + bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE); + } + bp->port.pmf = 0; + /* Free SKBs, SGEs, TPA pool and driver internals */ + bnx2x_free_skbs(bp); + for_each_queue(bp, i) + bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); +load_error2: + /* Release IRQs */ + bnx2x_free_irq(bp, false); +load_error1: + bnx2x_napi_disable(bp); + for_each_queue(bp, i) + netif_napi_del(&bnx2x_fp(bp, i, napi)); + bnx2x_free_mem(bp); + + return rc; +} + +/* must be called with rtnl_lock */ +int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) +{ + int i; + + if (bp->state == BNX2X_STATE_CLOSED) { + /* Interface has been removed - nothing to recover */ + bp->recovery_state = BNX2X_RECOVERY_DONE; + bp->is_leader = 0; + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESERVED_08); + smp_wmb(); + + return -EINVAL; + } + +#ifdef BCM_CNIC + bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD); +#endif + bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT; + + /* Set "drop all" */ + bp->rx_mode = BNX2X_RX_MODE_NONE; + bnx2x_set_storm_rx_mode(bp); + + /* Disable HW interrupts, NAPI and Tx */ + bnx2x_netif_stop(bp, 1); + netif_carrier_off(bp->dev); + + del_timer_sync(&bp->timer); + SHMEM_WR(bp, func_mb[BP_FUNC(bp)].drv_pulse_mb, + (DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq)); + bnx2x_stats_handle(bp, STATS_EVENT_STOP); + + /* Release IRQs */ + bnx2x_free_irq(bp, false); + + /* Cleanup the chip if needed */ + if (unload_mode != UNLOAD_RECOVERY) + bnx2x_chip_cleanup(bp, unload_mode); + + bp->port.pmf = 0; + + /* Free SKBs, SGEs, TPA pool and driver internals */ + bnx2x_free_skbs(bp); + for_each_queue(bp, i) + bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); + for_each_queue(bp, i) + netif_napi_del(&bnx2x_fp(bp, i, napi)); + bnx2x_free_mem(bp); + + bp->state = BNX2X_STATE_CLOSED; + + /* The last driver must disable a "close the gate" if there is no + * parity attention or "process kill" pending. + */ + if ((!bnx2x_dec_load_cnt(bp)) && (!bnx2x_chk_parity_attn(bp)) && + bnx2x_reset_is_done(bp)) + bnx2x_disable_close_the_gate(bp); + + /* Reset MCP mail box sequence if there is on going recovery */ + if (unload_mode == UNLOAD_RECOVERY) + bp->fw_seq = 0; + + return 0; +} +int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state) +{ + u16 pmcsr; + + pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr); + + switch (state) { + case PCI_D0: + pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, + ((pmcsr & ~PCI_PM_CTRL_STATE_MASK) | + PCI_PM_CTRL_PME_STATUS)); + + if (pmcsr & PCI_PM_CTRL_STATE_MASK) + /* delay required during transition out of D3hot */ + msleep(20); + break; + + case PCI_D3hot: + /* If there are other clients above don't + shut down the power */ + if (atomic_read(&bp->pdev->enable_cnt) != 1) + return 0; + /* Don't shut down the power for emulation and FPGA */ + if (CHIP_REV_IS_SLOW(bp)) + return 0; + + pmcsr &= ~PCI_PM_CTRL_STATE_MASK; + pmcsr |= 3; + + if (bp->wol) + pmcsr |= PCI_PM_CTRL_PME_ENABLE; + + pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, + pmcsr); + + /* No more memory access after this point until + * device is brought back to D0. + */ + break; + + default: + return -EINVAL; + } + return 0; +} + + + +/* + * net_device service functions + */ + +static int bnx2x_poll(struct napi_struct *napi, int budget) +{ + int work_done = 0; + struct bnx2x_fastpath *fp = container_of(napi, struct bnx2x_fastpath, + napi); + struct bnx2x *bp = fp->bp; + + while (1) { +#ifdef BNX2X_STOP_ON_ERROR + if (unlikely(bp->panic)) { + napi_complete(napi); + return 0; + } +#endif + + if (bnx2x_has_tx_work(fp)) + bnx2x_tx_int(fp); + + if (bnx2x_has_rx_work(fp)) { + work_done += bnx2x_rx_int(fp, budget - work_done); + + /* must not complete if we consumed full budget */ + if (work_done >= budget) + break; + } + + /* Fall out from the NAPI loop if needed */ + if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) { + bnx2x_update_fpsb_idx(fp); + /* bnx2x_has_rx_work() reads the status block, thus we need + * to ensure that status block indices have been actually read + * (bnx2x_update_fpsb_idx) prior to this check + * (bnx2x_has_rx_work) so that we won't write the "newer" + * value of the status block to IGU (if there was a DMA right + * after bnx2x_has_rx_work and if there is no rmb, the memory + * reading (bnx2x_update_fpsb_idx) may be postponed to right + * before bnx2x_ack_sb). In this case there will never be + * another interrupt until there is another update of the + * status block, while there is still unhandled work. + */ + rmb(); + + if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) { + napi_complete(napi); + /* Re-enable interrupts */ + bnx2x_ack_sb(bp, fp->sb_id, CSTORM_ID, + le16_to_cpu(fp->fp_c_idx), + IGU_INT_NOP, 1); + bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID, + le16_to_cpu(fp->fp_u_idx), + IGU_INT_ENABLE, 1); + break; + } + } + } + + return work_done; +} + + +/* we split the first BD into headers and data BDs + * to ease the pain of our fellow microcode engineers + * we use one mapping for both BDs + * So far this has only been observed to happen + * in Other Operating Systems(TM) + */ +static noinline u16 bnx2x_tx_split(struct bnx2x *bp, + struct bnx2x_fastpath *fp, + struct sw_tx_bd *tx_buf, + struct eth_tx_start_bd **tx_bd, u16 hlen, + u16 bd_prod, int nbd) +{ + struct eth_tx_start_bd *h_tx_bd = *tx_bd; + struct eth_tx_bd *d_tx_bd; + dma_addr_t mapping; + int old_len = le16_to_cpu(h_tx_bd->nbytes); + + /* first fix first BD */ + h_tx_bd->nbd = cpu_to_le16(nbd); + h_tx_bd->nbytes = cpu_to_le16(hlen); + + DP(NETIF_MSG_TX_QUEUED, "TSO split header size is %d " + "(%x:%x) nbd %d\n", h_tx_bd->nbytes, h_tx_bd->addr_hi, + h_tx_bd->addr_lo, h_tx_bd->nbd); + + /* now get a new data BD + * (after the pbd) and fill it */ + bd_prod = TX_BD(NEXT_TX_IDX(bd_prod)); + d_tx_bd = &fp->tx_desc_ring[bd_prod].reg_bd; + + mapping = HILO_U64(le32_to_cpu(h_tx_bd->addr_hi), + le32_to_cpu(h_tx_bd->addr_lo)) + hlen; + + d_tx_bd->addr_hi = cpu_to_le32(U64_HI(mapping)); + d_tx_bd->addr_lo = cpu_to_le32(U64_LO(mapping)); + d_tx_bd->nbytes = cpu_to_le16(old_len - hlen); + + /* this marks the BD as one that has no individual mapping */ + tx_buf->flags |= BNX2X_TSO_SPLIT_BD; + + DP(NETIF_MSG_TX_QUEUED, + "TSO split data size is %d (%x:%x)\n", + d_tx_bd->nbytes, d_tx_bd->addr_hi, d_tx_bd->addr_lo); + + /* update tx_bd */ + *tx_bd = (struct eth_tx_start_bd *)d_tx_bd; + + return bd_prod; +} + +static inline u16 bnx2x_csum_fix(unsigned char *t_header, u16 csum, s8 fix) +{ + if (fix > 0) + csum = (u16) ~csum_fold(csum_sub(csum, + csum_partial(t_header - fix, fix, 0))); + + else if (fix < 0) + csum = (u16) ~csum_fold(csum_add(csum, + csum_partial(t_header, -fix, 0))); + + return swab16(csum); +} + +static inline u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb) +{ + u32 rc; + + if (skb->ip_summed != CHECKSUM_PARTIAL) + rc = XMIT_PLAIN; + + else { + if (skb->protocol == htons(ETH_P_IPV6)) { + rc = XMIT_CSUM_V6; + if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) + rc |= XMIT_CSUM_TCP; + + } else { + rc = XMIT_CSUM_V4; + if (ip_hdr(skb)->protocol == IPPROTO_TCP) + rc |= XMIT_CSUM_TCP; + } + } + + if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) + rc |= (XMIT_GSO_V4 | XMIT_CSUM_V4 | XMIT_CSUM_TCP); + + else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) + rc |= (XMIT_GSO_V6 | XMIT_CSUM_TCP | XMIT_CSUM_V6); + + return rc; +} + +#if (MAX_SKB_FRAGS >= MAX_FETCH_BD - 3) +/* check if packet requires linearization (packet is too fragmented) + no need to check fragmentation if page size > 8K (there will be no + violation to FW restrictions) */ +static int bnx2x_pkt_req_lin(struct bnx2x *bp, struct sk_buff *skb, + u32 xmit_type) +{ + int to_copy = 0; + int hlen = 0; + int first_bd_sz = 0; + + /* 3 = 1 (for linear data BD) + 2 (for PBD and last BD) */ + if (skb_shinfo(skb)->nr_frags >= (MAX_FETCH_BD - 3)) { + + if (xmit_type & XMIT_GSO) { + unsigned short lso_mss = skb_shinfo(skb)->gso_size; + /* Check if LSO packet needs to be copied: + 3 = 1 (for headers BD) + 2 (for PBD and last BD) */ + int wnd_size = MAX_FETCH_BD - 3; + /* Number of windows to check */ + int num_wnds = skb_shinfo(skb)->nr_frags - wnd_size; + int wnd_idx = 0; + int frag_idx = 0; + u32 wnd_sum = 0; + + /* Headers length */ + hlen = (int)(skb_transport_header(skb) - skb->data) + + tcp_hdrlen(skb); + + /* Amount of data (w/o headers) on linear part of SKB*/ + first_bd_sz = skb_headlen(skb) - hlen; + + wnd_sum = first_bd_sz; + + /* Calculate the first sum - it's special */ + for (frag_idx = 0; frag_idx < wnd_size - 1; frag_idx++) + wnd_sum += + skb_shinfo(skb)->frags[frag_idx].size; + + /* If there was data on linear skb data - check it */ + if (first_bd_sz > 0) { + if (unlikely(wnd_sum < lso_mss)) { + to_copy = 1; + goto exit_lbl; + } + + wnd_sum -= first_bd_sz; + } + + /* Others are easier: run through the frag list and + check all windows */ + for (wnd_idx = 0; wnd_idx <= num_wnds; wnd_idx++) { + wnd_sum += + skb_shinfo(skb)->frags[wnd_idx + wnd_size - 1].size; + + if (unlikely(wnd_sum < lso_mss)) { + to_copy = 1; + break; + } + wnd_sum -= + skb_shinfo(skb)->frags[wnd_idx].size; + } + } else { + /* in non-LSO too fragmented packet should always + be linearized */ + to_copy = 1; + } + } + +exit_lbl: + if (unlikely(to_copy)) + DP(NETIF_MSG_TX_QUEUED, + "Linearization IS REQUIRED for %s packet. " + "num_frags %d hlen %d first_bd_sz %d\n", + (xmit_type & XMIT_GSO) ? "LSO" : "non-LSO", + skb_shinfo(skb)->nr_frags, hlen, first_bd_sz); + + return to_copy; +} +#endif + +/* called with netif_tx_lock + * bnx2x_tx_int() runs without netif_tx_lock unless it needs to call + * netif_wake_queue() + */ +netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct bnx2x *bp = netdev_priv(dev); + struct bnx2x_fastpath *fp; + struct netdev_queue *txq; + struct sw_tx_bd *tx_buf; + struct eth_tx_start_bd *tx_start_bd; + struct eth_tx_bd *tx_data_bd, *total_pkt_bd = NULL; + struct eth_tx_parse_bd *pbd = NULL; + u16 pkt_prod, bd_prod; + int nbd, fp_index; + dma_addr_t mapping; + u32 xmit_type = bnx2x_xmit_type(bp, skb); + int i; + u8 hlen = 0; + __le16 pkt_size = 0; + struct ethhdr *eth; + u8 mac_type = UNICAST_ADDRESS; + +#ifdef BNX2X_STOP_ON_ERROR + if (unlikely(bp->panic)) + return NETDEV_TX_BUSY; +#endif + + fp_index = skb_get_queue_mapping(skb); + txq = netdev_get_tx_queue(dev, fp_index); + + fp = &bp->fp[fp_index]; + + if (unlikely(bnx2x_tx_avail(fp) < (skb_shinfo(skb)->nr_frags + 3))) { + fp->eth_q_stats.driver_xoff++; + netif_tx_stop_queue(txq); + BNX2X_ERR("BUG! Tx ring full when queue awake!\n"); + return NETDEV_TX_BUSY; + } + + DP(NETIF_MSG_TX_QUEUED, "SKB: summed %x protocol %x protocol(%x,%x)" + " gso type %x xmit_type %x\n", + skb->ip_summed, skb->protocol, ipv6_hdr(skb)->nexthdr, + ip_hdr(skb)->protocol, skb_shinfo(skb)->gso_type, xmit_type); + + eth = (struct ethhdr *)skb->data; + + /* set flag according to packet type (UNICAST_ADDRESS is default)*/ + if (unlikely(is_multicast_ether_addr(eth->h_dest))) { + if (is_broadcast_ether_addr(eth->h_dest)) + mac_type = BROADCAST_ADDRESS; + else + mac_type = MULTICAST_ADDRESS; + } + +#if (MAX_SKB_FRAGS >= MAX_FETCH_BD - 3) + /* First, check if we need to linearize the skb (due to FW + restrictions). No need to check fragmentation if page size > 8K + (there will be no violation to FW restrictions) */ + if (bnx2x_pkt_req_lin(bp, skb, xmit_type)) { + /* Statistics of linearization */ + bp->lin_cnt++; + if (skb_linearize(skb) != 0) { + DP(NETIF_MSG_TX_QUEUED, "SKB linearization failed - " + "silently dropping this SKB\n"); + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + } +#endif + + /* + Please read carefully. First we use one BD which we mark as start, + then we have a parsing info BD (used for TSO or xsum), + and only then we have the rest of the TSO BDs. + (don't forget to mark the last one as last, + and to unmap only AFTER you write to the BD ...) + And above all, all pdb sizes are in words - NOT DWORDS! + */ + + pkt_prod = fp->tx_pkt_prod++; + bd_prod = TX_BD(fp->tx_bd_prod); + + /* get a tx_buf and first BD */ + tx_buf = &fp->tx_buf_ring[TX_BD(pkt_prod)]; + tx_start_bd = &fp->tx_desc_ring[bd_prod].start_bd; + + tx_start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD; + tx_start_bd->general_data = (mac_type << + ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT); + /* header nbd */ + tx_start_bd->general_data |= (1 << ETH_TX_START_BD_HDR_NBDS_SHIFT); + + /* remember the first BD of the packet */ + tx_buf->first_bd = fp->tx_bd_prod; + tx_buf->skb = skb; + tx_buf->flags = 0; + + DP(NETIF_MSG_TX_QUEUED, + "sending pkt %u @%p next_idx %u bd %u @%p\n", + pkt_prod, tx_buf, fp->tx_pkt_prod, bd_prod, tx_start_bd); + +#ifdef BCM_VLAN + if ((bp->vlgrp != NULL) && vlan_tx_tag_present(skb) && + (bp->flags & HW_VLAN_TX_FLAG)) { + tx_start_bd->vlan = cpu_to_le16(vlan_tx_tag_get(skb)); + tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_VLAN_TAG; + } else +#endif + tx_start_bd->vlan = cpu_to_le16(pkt_prod); + + /* turn on parsing and get a BD */ + bd_prod = TX_BD(NEXT_TX_IDX(bd_prod)); + pbd = &fp->tx_desc_ring[bd_prod].parse_bd; + + memset(pbd, 0, sizeof(struct eth_tx_parse_bd)); + + if (xmit_type & XMIT_CSUM) { + hlen = (skb_network_header(skb) - skb->data) / 2; + + /* for now NS flag is not used in Linux */ + pbd->global_data = + (hlen | ((skb->protocol == cpu_to_be16(ETH_P_8021Q)) << + ETH_TX_PARSE_BD_LLC_SNAP_EN_SHIFT)); + + pbd->ip_hlen = (skb_transport_header(skb) - + skb_network_header(skb)) / 2; + + hlen += pbd->ip_hlen + tcp_hdrlen(skb) / 2; + + pbd->total_hlen = cpu_to_le16(hlen); + hlen = hlen*2; + + tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_L4_CSUM; + + if (xmit_type & XMIT_CSUM_V4) + tx_start_bd->bd_flags.as_bitfield |= + ETH_TX_BD_FLAGS_IP_CSUM; + else + tx_start_bd->bd_flags.as_bitfield |= + ETH_TX_BD_FLAGS_IPV6; + + if (xmit_type & XMIT_CSUM_TCP) { + pbd->tcp_pseudo_csum = swab16(tcp_hdr(skb)->check); + + } else { + s8 fix = SKB_CS_OFF(skb); /* signed! */ + + pbd->global_data |= ETH_TX_PARSE_BD_UDP_CS_FLG; + + DP(NETIF_MSG_TX_QUEUED, + "hlen %d fix %d csum before fix %x\n", + le16_to_cpu(pbd->total_hlen), fix, SKB_CS(skb)); + + /* HW bug: fixup the CSUM */ + pbd->tcp_pseudo_csum = + bnx2x_csum_fix(skb_transport_header(skb), + SKB_CS(skb), fix); + + DP(NETIF_MSG_TX_QUEUED, "csum after fix %x\n", + pbd->tcp_pseudo_csum); + } + } + + mapping = dma_map_single(&bp->pdev->dev, skb->data, + skb_headlen(skb), DMA_TO_DEVICE); + + tx_start_bd->addr_hi = cpu_to_le32(U64_HI(mapping)); + tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping)); + nbd = skb_shinfo(skb)->nr_frags + 2; /* start_bd + pbd + frags */ + tx_start_bd->nbd = cpu_to_le16(nbd); + tx_start_bd->nbytes = cpu_to_le16(skb_headlen(skb)); + pkt_size = tx_start_bd->nbytes; + + DP(NETIF_MSG_TX_QUEUED, "first bd @%p addr (%x:%x) nbd %d" + " nbytes %d flags %x vlan %x\n", + tx_start_bd, tx_start_bd->addr_hi, tx_start_bd->addr_lo, + le16_to_cpu(tx_start_bd->nbd), le16_to_cpu(tx_start_bd->nbytes), + tx_start_bd->bd_flags.as_bitfield, le16_to_cpu(tx_start_bd->vlan)); + + if (xmit_type & XMIT_GSO) { + + DP(NETIF_MSG_TX_QUEUED, + "TSO packet len %d hlen %d total len %d tso size %d\n", + skb->len, hlen, skb_headlen(skb), + skb_shinfo(skb)->gso_size); + + tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_SW_LSO; + + if (unlikely(skb_headlen(skb) > hlen)) + bd_prod = bnx2x_tx_split(bp, fp, tx_buf, &tx_start_bd, + hlen, bd_prod, ++nbd); + + pbd->lso_mss = cpu_to_le16(skb_shinfo(skb)->gso_size); + pbd->tcp_send_seq = swab32(tcp_hdr(skb)->seq); + pbd->tcp_flags = pbd_tcp_flags(skb); + + if (xmit_type & XMIT_GSO_V4) { + pbd->ip_id = swab16(ip_hdr(skb)->id); + pbd->tcp_pseudo_csum = + swab16(~csum_tcpudp_magic(ip_hdr(skb)->saddr, + ip_hdr(skb)->daddr, + 0, IPPROTO_TCP, 0)); + + } else + pbd->tcp_pseudo_csum = + swab16(~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, + &ipv6_hdr(skb)->daddr, + 0, IPPROTO_TCP, 0)); + + pbd->global_data |= ETH_TX_PARSE_BD_PSEUDO_CS_WITHOUT_LEN; + } + tx_data_bd = (struct eth_tx_bd *)tx_start_bd; + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + bd_prod = TX_BD(NEXT_TX_IDX(bd_prod)); + tx_data_bd = &fp->tx_desc_ring[bd_prod].reg_bd; + if (total_pkt_bd == NULL) + total_pkt_bd = &fp->tx_desc_ring[bd_prod].reg_bd; + + mapping = dma_map_page(&bp->pdev->dev, frag->page, + frag->page_offset, + frag->size, DMA_TO_DEVICE); + + tx_data_bd->addr_hi = cpu_to_le32(U64_HI(mapping)); + tx_data_bd->addr_lo = cpu_to_le32(U64_LO(mapping)); + tx_data_bd->nbytes = cpu_to_le16(frag->size); + le16_add_cpu(&pkt_size, frag->size); + + DP(NETIF_MSG_TX_QUEUED, + "frag %d bd @%p addr (%x:%x) nbytes %d\n", + i, tx_data_bd, tx_data_bd->addr_hi, tx_data_bd->addr_lo, + le16_to_cpu(tx_data_bd->nbytes)); + } + + DP(NETIF_MSG_TX_QUEUED, "last bd @%p\n", tx_data_bd); + + bd_prod = TX_BD(NEXT_TX_IDX(bd_prod)); + + /* now send a tx doorbell, counting the next BD + * if the packet contains or ends with it + */ + if (TX_BD_POFF(bd_prod) < nbd) + nbd++; + + if (total_pkt_bd != NULL) + total_pkt_bd->total_pkt_bytes = pkt_size; + + if (pbd) + DP(NETIF_MSG_TX_QUEUED, + "PBD @%p ip_data %x ip_hlen %u ip_id %u lso_mss %u" + " tcp_flags %x xsum %x seq %u hlen %u\n", + pbd, pbd->global_data, pbd->ip_hlen, pbd->ip_id, + pbd->lso_mss, pbd->tcp_flags, pbd->tcp_pseudo_csum, + pbd->tcp_send_seq, le16_to_cpu(pbd->total_hlen)); + + DP(NETIF_MSG_TX_QUEUED, "doorbell: nbd %d bd %u\n", nbd, bd_prod); + + /* + * Make sure that the BD data is updated before updating the producer + * since FW might read the BD right after the producer is updated. + * This is only applicable for weak-ordered memory model archs such + * as IA-64. The following barrier is also mandatory since FW will + * assumes packets must have BDs. + */ + wmb(); + + fp->tx_db.data.prod += nbd; + barrier(); + DOORBELL(bp, fp->index, fp->tx_db.raw); + + mmiowb(); + + fp->tx_bd_prod += nbd; + + if (unlikely(bnx2x_tx_avail(fp) < MAX_SKB_FRAGS + 3)) { + netif_tx_stop_queue(txq); + + /* paired memory barrier is in bnx2x_tx_int(), we have to keep + * ordering of set_bit() in netif_tx_stop_queue() and read of + * fp->bd_tx_cons */ + smp_mb(); + + fp->eth_q_stats.driver_xoff++; + if (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3) + netif_tx_wake_queue(txq); + } + fp->tx_pkt++; + + return NETDEV_TX_OK; +} +/* called with rtnl_lock */ +int bnx2x_change_mac_addr(struct net_device *dev, void *p) +{ + struct sockaddr *addr = p; + struct bnx2x *bp = netdev_priv(dev); + + if (!is_valid_ether_addr((u8 *)(addr->sa_data))) + return -EINVAL; + + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + if (netif_running(dev)) { + if (CHIP_IS_E1(bp)) + bnx2x_set_eth_mac_addr_e1(bp, 1); + else + bnx2x_set_eth_mac_addr_e1h(bp, 1); + } + + return 0; +} + +/* called with rtnl_lock */ +int bnx2x_change_mtu(struct net_device *dev, int new_mtu) +{ + struct bnx2x *bp = netdev_priv(dev); + int rc = 0; + + if (bp->recovery_state != BNX2X_RECOVERY_DONE) { + printk(KERN_ERR "Handling parity error recovery. Try again later\n"); + return -EAGAIN; + } + + if ((new_mtu > ETH_MAX_JUMBO_PACKET_SIZE) || + ((new_mtu + ETH_HLEN) < ETH_MIN_PACKET_SIZE)) + return -EINVAL; + + /* This does not race with packet allocation + * because the actual alloc size is + * only updated as part of load + */ + dev->mtu = new_mtu; + + if (netif_running(dev)) { + bnx2x_nic_unload(bp, UNLOAD_NORMAL); + rc = bnx2x_nic_load(bp, LOAD_NORMAL); + } + + return rc; +} + +void bnx2x_tx_timeout(struct net_device *dev) +{ + struct bnx2x *bp = netdev_priv(dev); + +#ifdef BNX2X_STOP_ON_ERROR + if (!bp->panic) + bnx2x_panic(); +#endif + /* This allows the netif to be shutdown gracefully before resetting */ + schedule_delayed_work(&bp->reset_task, 0); +} + +#ifdef BCM_VLAN +/* called with rtnl_lock */ +void bnx2x_vlan_rx_register(struct net_device *dev, + struct vlan_group *vlgrp) +{ + struct bnx2x *bp = netdev_priv(dev); + + bp->vlgrp = vlgrp; + + /* Set flags according to the required capabilities */ + bp->flags &= ~(HW_VLAN_RX_FLAG | HW_VLAN_TX_FLAG); + + if (dev->features & NETIF_F_HW_VLAN_TX) + bp->flags |= HW_VLAN_TX_FLAG; + + if (dev->features & NETIF_F_HW_VLAN_RX) + bp->flags |= HW_VLAN_RX_FLAG; + + if (netif_running(dev)) + bnx2x_set_client_config(bp); +} + +#endif +int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct bnx2x *bp; + + if (!dev) { + dev_err(&pdev->dev, "BAD net device from bnx2x_init_one\n"); + return -ENODEV; + } + bp = netdev_priv(dev); + + rtnl_lock(); + + pci_save_state(pdev); + + if (!netif_running(dev)) { + rtnl_unlock(); + return 0; + } + + netif_device_detach(dev); + + bnx2x_nic_unload(bp, UNLOAD_CLOSE); + + bnx2x_set_power_state(bp, pci_choose_state(pdev, state)); + + rtnl_unlock(); + + return 0; +} + +int bnx2x_resume(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct bnx2x *bp; + int rc; + + if (!dev) { + dev_err(&pdev->dev, "BAD net device from bnx2x_init_one\n"); + return -ENODEV; + } + bp = netdev_priv(dev); + + if (bp->recovery_state != BNX2X_RECOVERY_DONE) { + printk(KERN_ERR "Handling parity error recovery. Try again later\n"); + return -EAGAIN; + } + + rtnl_lock(); + + pci_restore_state(pdev); + + if (!netif_running(dev)) { + rtnl_unlock(); + return 0; + } + + bnx2x_set_power_state(bp, PCI_D0); + netif_device_attach(dev); + + rc = bnx2x_nic_load(bp, LOAD_OPEN); + + rtnl_unlock(); + + return rc; +} diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h new file mode 100644 index 00000000000..d1979b1a7ed --- /dev/null +++ b/drivers/net/bnx2x/bnx2x_cmn.h @@ -0,0 +1,652 @@ +/* bnx2x_cmn.h: Broadcom Everest network driver. + * + * Copyright (c) 2007-2010 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * Maintained by: Eilon Greenstein <eilong@broadcom.com> + * Written by: Eliezer Tamir + * Based on code from Michael Chan's bnx2 driver + * UDP CSUM errata workaround by Arik Gendelman + * Slowpath and fastpath rework by Vladislav Zolotarov + * Statistics and Link management by Yitchak Gertner + * + */ +#ifndef BNX2X_CMN_H +#define BNX2X_CMN_H + +#include <linux/types.h> +#include <linux/netdevice.h> + + +#include "bnx2x.h" + + +/*********************** Interfaces **************************** + * Functions that need to be implemented by each driver version + */ + +/** + * Initialize link parameters structure variables. + * + * @param bp + * @param load_mode + * + * @return u8 + */ +u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode); + +/** + * Configure hw according to link parameters structure. + * + * @param bp + */ +void bnx2x_link_set(struct bnx2x *bp); + +/** + * Query link status + * + * @param bp + * + * @return 0 - link is UP + */ +u8 bnx2x_link_test(struct bnx2x *bp); + +/** + * Handles link status change + * + * @param bp + */ +void bnx2x__link_status_update(struct bnx2x *bp); + +/** + * MSI-X slowpath interrupt handler + * + * @param irq + * @param dev_instance + * + * @return irqreturn_t + */ +irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance); + +/** + * non MSI-X interrupt handler + * + * @param irq + * @param dev_instance + * + * @return irqreturn_t + */ +irqreturn_t bnx2x_interrupt(int irq, void *dev_instance); +#ifdef BCM_CNIC + +/** + * Send command to cnic driver + * + * @param bp + * @param cmd + */ +int bnx2x_cnic_notify(struct bnx2x *bp, int cmd); + +/** + * Provides cnic information for proper interrupt handling + * + * @param bp + */ +void bnx2x_setup_cnic_irq_info(struct bnx2x *bp); +#endif + +/** + * Enable HW interrupts. + * + * @param bp + */ +void bnx2x_int_enable(struct bnx2x *bp); + +/** + * Disable interrupts. This function ensures that there are no + * ISRs or SP DPCs (sp_task) are running after it returns. + * + * @param bp + * @param disable_hw if true, disable HW interrupts. + */ +void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw); + +/** + * Init HW blocks according to current initialization stage: + * COMMON, PORT or FUNCTION. + * + * @param bp + * @param load_code: COMMON, PORT or FUNCTION + * + * @return int + */ +int bnx2x_init_hw(struct bnx2x *bp, u32 load_code); + +/** + * Init driver internals: + * - rings + * - status blocks + * - etc. + * + * @param bp + * @param load_code COMMON, PORT or FUNCTION + */ +void bnx2x_nic_init(struct bnx2x *bp, u32 load_code); + +/** + * Allocate driver's memory. + * + * @param bp + * + * @return int + */ +int bnx2x_alloc_mem(struct bnx2x *bp); + +/** + * Release driver's memory. + * + * @param bp + */ +void bnx2x_free_mem(struct bnx2x *bp); + +/** + * Bring up a leading (the first) eth Client. + * + * @param bp + * + * @return int + */ +int bnx2x_setup_leading(struct bnx2x *bp); + +/** + * Setup non-leading eth Client. + * + * @param bp + * @param fp + * + * @return int + */ +int bnx2x_setup_multi(struct bnx2x *bp, int index); + +/** + * Set number of quueus according to mode and number of available + * msi-x vectors + * + * @param bp + * + */ +void bnx2x_set_num_queues_msix(struct bnx2x *bp); + +/** + * Cleanup chip internals: + * - Cleanup MAC configuration. + * - Close clients. + * - etc. + * + * @param bp + * @param unload_mode + */ +void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode); + +/** + * Acquire HW lock. + * + * @param bp + * @param resource Resource bit which was locked + * + * @return int + */ +int bnx2x_acquire_hw_lock(struct bnx2x *bp, u32 resource); + +/** + * Release HW lock. + * + * @param bp driver handle + * @param resource Resource bit which was locked + * + * @return int + */ +int bnx2x_release_hw_lock(struct bnx2x *bp, u32 resource); + +/** + * Configure eth MAC address in the HW according to the value in + * netdev->dev_addr for 57711 + * + * @param bp driver handle + * @param set + */ +void bnx2x_set_eth_mac_addr_e1h(struct bnx2x *bp, int set); + +/** + * Configure eth MAC address in the HW according to the value in + * netdev->dev_addr for 57710 + * + * @param bp driver handle + * @param set + */ +void bnx2x_set_eth_mac_addr_e1(struct bnx2x *bp, int set); + +#ifdef BCM_CNIC +/** + * Set iSCSI MAC(s) at the next enties in the CAM after the ETH + * MAC(s). The function will wait until the ramrod completion + * returns. + * + * @param bp driver handle + * @param set set or clear the CAM entry + * + * @return 0 if cussess, -ENODEV if ramrod doesn't return. + */ +int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set); +#endif + +/** + * Initialize status block in FW and HW + * + * @param bp driver handle + * @param sb host_status_block + * @param dma_addr_t mapping + * @param int sb_id + */ +void bnx2x_init_sb(struct bnx2x *bp, struct host_status_block *sb, + dma_addr_t mapping, int sb_id); + +/** + * Reconfigure FW/HW according to dev->flags rx mode + * + * @param dev net_device + * + */ +void bnx2x_set_rx_mode(struct net_device *dev); + +/** + * Configure MAC filtering rules in a FW. + * + * @param bp driver handle + */ +void bnx2x_set_storm_rx_mode(struct bnx2x *bp); + +/* Parity errors related */ +void bnx2x_inc_load_cnt(struct bnx2x *bp); +u32 bnx2x_dec_load_cnt(struct bnx2x *bp); +bool bnx2x_chk_parity_attn(struct bnx2x *bp); +bool bnx2x_reset_is_done(struct bnx2x *bp); +void bnx2x_disable_close_the_gate(struct bnx2x *bp); + +/** + * Perform statistics handling according to event + * + * @param bp driver handle + * @param even tbnx2x_stats_event + */ +void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event); + +/** + * Configures FW with client paramteres (like HW VLAN removal) + * for each active client. + * + * @param bp + */ +void bnx2x_set_client_config(struct bnx2x *bp); + +/** + * Handle sp events + * + * @param fp fastpath handle for the event + * @param rr_cqe eth_rx_cqe + */ +void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe); + + +static inline void bnx2x_update_fpsb_idx(struct bnx2x_fastpath *fp) +{ + struct host_status_block *fpsb = fp->status_blk; + + barrier(); /* status block is written to by the chip */ + fp->fp_c_idx = fpsb->c_status_block.status_block_index; + fp->fp_u_idx = fpsb->u_status_block.status_block_index; +} + +static inline void bnx2x_update_rx_prod(struct bnx2x *bp, + struct bnx2x_fastpath *fp, + u16 bd_prod, u16 rx_comp_prod, + u16 rx_sge_prod) +{ + struct ustorm_eth_rx_producers rx_prods = {0}; + int i; + + /* Update producers */ + rx_prods.bd_prod = bd_prod; + rx_prods.cqe_prod = rx_comp_prod; + rx_prods.sge_prod = rx_sge_prod; + + /* + * Make sure that the BD and SGE data is updated before updating the + * producers since FW might read the BD/SGE right after the producer + * is updated. + * This is only applicable for weak-ordered memory model archs such + * as IA-64. The following barrier is also mandatory since FW will + * assumes BDs must have buffers. + */ + wmb(); + + for (i = 0; i < sizeof(struct ustorm_eth_rx_producers)/4; i++) + REG_WR(bp, BAR_USTRORM_INTMEM + + USTORM_RX_PRODS_OFFSET(BP_PORT(bp), fp->cl_id) + i*4, + ((u32 *)&rx_prods)[i]); + + mmiowb(); /* keep prod updates ordered */ + + DP(NETIF_MSG_RX_STATUS, + "queue[%d]: wrote bd_prod %u cqe_prod %u sge_prod %u\n", + fp->index, bd_prod, rx_comp_prod, rx_sge_prod); +} + + + +static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 sb_id, + u8 storm, u16 index, u8 op, u8 update) +{ + u32 hc_addr = (HC_REG_COMMAND_REG + BP_PORT(bp)*32 + + COMMAND_REG_INT_ACK); + struct igu_ack_register igu_ack; + + igu_ack.status_block_index = index; + igu_ack.sb_id_and_flags = + ((sb_id << IGU_ACK_REGISTER_STATUS_BLOCK_ID_SHIFT) | + (storm << IGU_ACK_REGISTER_STORM_ID_SHIFT) | + (update << IGU_ACK_REGISTER_UPDATE_INDEX_SHIFT) | + (op << IGU_ACK_REGISTER_INTERRUPT_MODE_SHIFT)); + + DP(BNX2X_MSG_OFF, "write 0x%08x to HC addr 0x%x\n", + (*(u32 *)&igu_ack), hc_addr); + REG_WR(bp, hc_addr, (*(u32 *)&igu_ack)); + + /* Make sure that ACK is written */ + mmiowb(); + barrier(); +} +static inline u16 bnx2x_ack_int(struct bnx2x *bp) +{ + u32 hc_addr = (HC_REG_COMMAND_REG + BP_PORT(bp)*32 + + COMMAND_REG_SIMD_MASK); + u32 result = REG_RD(bp, hc_addr); + + DP(BNX2X_MSG_OFF, "read 0x%08x from HC addr 0x%x\n", + result, hc_addr); + + return result; +} + +/* + * fast path service functions + */ + +static inline int bnx2x_has_tx_work_unload(struct bnx2x_fastpath *fp) +{ + /* Tell compiler that consumer and producer can change */ + barrier(); + return (fp->tx_pkt_prod != fp->tx_pkt_cons); +} + +static inline u16 bnx2x_tx_avail(struct bnx2x_fastpath *fp) +{ + s16 used; + u16 prod; + u16 cons; + + prod = fp->tx_bd_prod; + cons = fp->tx_bd_cons; + + /* NUM_TX_RINGS = number of "next-page" entries + It will be used as a threshold */ + used = SUB_S16(prod, cons) + (s16)NUM_TX_RINGS; + +#ifdef BNX2X_STOP_ON_ERROR + WARN_ON(used < 0); + WARN_ON(used > fp->bp->tx_ring_size); + WARN_ON((fp->bp->tx_ring_size - used) > MAX_TX_AVAIL); +#endif + + return (s16)(fp->bp->tx_ring_size) - used; +} + +static inline int bnx2x_has_tx_work(struct bnx2x_fastpath *fp) +{ + u16 hw_cons; + + /* Tell compiler that status block fields can change */ + barrier(); + hw_cons = le16_to_cpu(*fp->tx_cons_sb); + return hw_cons != fp->tx_pkt_cons; +} + +static inline void bnx2x_free_rx_sge(struct bnx2x *bp, + struct bnx2x_fastpath *fp, u16 index) +{ + struct sw_rx_page *sw_buf = &fp->rx_page_ring[index]; + struct page *page = sw_buf->page; + struct eth_rx_sge *sge = &fp->rx_sge_ring[index]; + + /* Skip "next page" elements */ + if (!page) + return; + + dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(sw_buf, mapping), + SGE_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE); + __free_pages(page, PAGES_PER_SGE_SHIFT); + + sw_buf->page = NULL; + sge->addr_hi = 0; + sge->addr_lo = 0; +} + +static inline void bnx2x_free_rx_sge_range(struct bnx2x *bp, + struct bnx2x_fastpath *fp, int last) +{ + int i; + + for (i = 0; i < last; i++) + bnx2x_free_rx_sge(bp, fp, i); +} + +static inline int bnx2x_alloc_rx_sge(struct bnx2x *bp, + struct bnx2x_fastpath *fp, u16 index) +{ + struct page *page = alloc_pages(GFP_ATOMIC, PAGES_PER_SGE_SHIFT); + struct sw_rx_page *sw_buf = &fp->rx_page_ring[index]; + struct eth_rx_sge *sge = &fp->rx_sge_ring[index]; + dma_addr_t mapping; + + if (unlikely(page == NULL)) + return -ENOMEM; + + mapping = dma_map_page(&bp->pdev->dev, page, 0, + SGE_PAGE_SIZE*PAGES_PER_SGE, DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) { + __free_pages(page, PAGES_PER_SGE_SHIFT); + return -ENOMEM; + } + + sw_buf->page = page; + dma_unmap_addr_set(sw_buf, mapping, mapping); + + sge->addr_hi = cpu_to_le32(U64_HI(mapping)); + sge->addr_lo = cpu_to_le32(U64_LO(mapping)); + + return 0; +} +static inline int bnx2x_alloc_rx_skb(struct bnx2x *bp, + struct bnx2x_fastpath *fp, u16 index) +{ + struct sk_buff *skb; + struct sw_rx_bd *rx_buf = &fp->rx_buf_ring[index]; + struct eth_rx_bd *rx_bd = &fp->rx_desc_ring[index]; + dma_addr_t mapping; + + skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size); + if (unlikely(skb == NULL)) + return -ENOMEM; + + mapping = dma_map_single(&bp->pdev->dev, skb->data, bp->rx_buf_size, + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) { + dev_kfree_skb(skb); + return -ENOMEM; + } + + rx_buf->skb = skb; + dma_unmap_addr_set(rx_buf, mapping, mapping); + + rx_bd->addr_hi = cpu_to_le32(U64_HI(mapping)); + rx_bd->addr_lo = cpu_to_le32(U64_LO(mapping)); + + return 0; +} + +/* note that we are not allocating a new skb, + * we are just moving one from cons to prod + * we are not creating a new mapping, + * so there is no need to check for dma_mapping_error(). + */ +static inline void bnx2x_reuse_rx_skb(struct bnx2x_fastpath *fp, + struct sk_buff *skb, u16 cons, u16 prod) +{ + struct bnx2x *bp = fp->bp; + struct sw_rx_bd *cons_rx_buf = &fp->rx_buf_ring[cons]; + struct sw_rx_bd *prod_rx_buf = &fp->rx_buf_ring[prod]; + struct eth_rx_bd *cons_bd = &fp->rx_desc_ring[cons]; + struct eth_rx_bd *prod_bd = &fp->rx_desc_ring[prod]; + + dma_sync_single_for_device(&bp->pdev->dev, + dma_unmap_addr(cons_rx_buf, mapping), + RX_COPY_THRESH, DMA_FROM_DEVICE); + + prod_rx_buf->skb = cons_rx_buf->skb; + dma_unmap_addr_set(prod_rx_buf, mapping, + dma_unmap_addr(cons_rx_buf, mapping)); + *prod_bd = *cons_bd; +} + +static inline void bnx2x_clear_sge_mask_next_elems(struct bnx2x_fastpath *fp) +{ + int i, j; + + for (i = 1; i <= NUM_RX_SGE_PAGES; i++) { + int idx = RX_SGE_CNT * i - 1; + + for (j = 0; j < 2; j++) { + SGE_MASK_CLEAR_BIT(fp, idx); + idx--; + } + } +} + +static inline void bnx2x_init_sge_ring_bit_mask(struct bnx2x_fastpath *fp) +{ + /* Set the mask to all 1-s: it's faster to compare to 0 than to 0xf-s */ + memset(fp->sge_mask, 0xff, + (NUM_RX_SGE >> RX_SGE_MASK_ELEM_SHIFT)*sizeof(u64)); + + /* Clear the two last indices in the page to 1: + these are the indices that correspond to the "next" element, + hence will never be indicated and should be removed from + the calculations. */ + bnx2x_clear_sge_mask_next_elems(fp); +} +static inline void bnx2x_free_tpa_pool(struct bnx2x *bp, + struct bnx2x_fastpath *fp, int last) +{ + int i; + + for (i = 0; i < last; i++) { + struct sw_rx_bd *rx_buf = &(fp->tpa_pool[i]); + struct sk_buff *skb = rx_buf->skb; + + if (skb == NULL) { + DP(NETIF_MSG_IFDOWN, "tpa bin %d empty on free\n", i); + continue; + } + + if (fp->tpa_state[i] == BNX2X_TPA_START) + dma_unmap_single(&bp->pdev->dev, + dma_unmap_addr(rx_buf, mapping), + bp->rx_buf_size, DMA_FROM_DEVICE); + + dev_kfree_skb(skb); + rx_buf->skb = NULL; + } +} + + +static inline void bnx2x_init_tx_ring(struct bnx2x *bp) +{ + int i, j; + + for_each_queue(bp, j) { + struct bnx2x_fastpath *fp = &bp->fp[j]; + + for (i = 1; i <= NUM_TX_RINGS; i++) { + struct eth_tx_next_bd *tx_next_bd = + &fp->tx_desc_ring[TX_DESC_CNT * i - 1].next_bd; + + tx_next_bd->addr_hi = + cpu_to_le32(U64_HI(fp->tx_desc_mapping + + BCM_PAGE_SIZE*(i % NUM_TX_RINGS))); + tx_next_bd->addr_lo = + cpu_to_le32(U64_LO(fp->tx_desc_mapping + + BCM_PAGE_SIZE*(i % NUM_TX_RINGS))); + } + + fp->tx_db.data.header.header = DOORBELL_HDR_DB_TYPE; + fp->tx_db.data.zero_fill1 = 0; + fp->tx_db.data.prod = 0; + + fp->tx_pkt_prod = 0; + fp->tx_pkt_cons = 0; + fp->tx_bd_prod = 0; + fp->tx_bd_cons = 0; + fp->tx_cons_sb = BNX2X_TX_SB_INDEX; + fp->tx_pkt = 0; + } +} +static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp) +{ + u16 rx_cons_sb; + + /* Tell compiler that status block fields can change */ + barrier(); + rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb); + if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT) + rx_cons_sb++; + return (fp->rx_comp_cons != rx_cons_sb); +} + +/* HW Lock for shared dual port PHYs */ +void bnx2x_acquire_phy_lock(struct bnx2x *bp); +void bnx2x_release_phy_lock(struct bnx2x *bp); + +void bnx2x_link_report(struct bnx2x *bp); +int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget); +int bnx2x_tx_int(struct bnx2x_fastpath *fp); +void bnx2x_init_rx_rings(struct bnx2x *bp); +netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev); + +int bnx2x_change_mac_addr(struct net_device *dev, void *p); +void bnx2x_tx_timeout(struct net_device *dev); +void bnx2x_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp); +void bnx2x_netif_start(struct bnx2x *bp); +void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw); +void bnx2x_free_irq(struct bnx2x *bp, bool disable_only); +int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state); +int bnx2x_resume(struct pci_dev *pdev); +void bnx2x_free_skbs(struct bnx2x *bp); +int bnx2x_change_mtu(struct net_device *dev, int new_mtu); +int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode); +int bnx2x_nic_load(struct bnx2x *bp, int load_mode); +int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state); + +#endif /* BNX2X_CMN_H */ diff --git a/drivers/net/bnx2x_dump.h b/drivers/net/bnx2x/bnx2x_dump.h index 3bb9a91bb3f..3bb9a91bb3f 100644 --- a/drivers/net/bnx2x_dump.h +++ b/drivers/net/bnx2x/bnx2x_dump.h diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c new file mode 100644 index 00000000000..8b75b05e34c --- /dev/null +++ b/drivers/net/bnx2x/bnx2x_ethtool.c @@ -0,0 +1,1971 @@ +/* bnx2x_ethtool.c: Broadcom Everest network driver. + * + * Copyright (c) 2007-2010 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * Maintained by: Eilon Greenstein <eilong@broadcom.com> + * Written by: Eliezer Tamir + * Based on code from Michael Chan's bnx2 driver + * UDP CSUM errata workaround by Arik Gendelman + * Slowpath and fastpath rework by Vladislav Zolotarov + * Statistics and Link management by Yitchak Gertner + * + */ +#include <linux/ethtool.h> +#include <linux/netdevice.h> +#include <linux/types.h> +#include <linux/sched.h> +#include <linux/crc32.h> + + +#include "bnx2x.h" +#include "bnx2x_cmn.h" +#include "bnx2x_dump.h" + + +static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct bnx2x *bp = netdev_priv(dev); + + cmd->supported = bp->port.supported; + cmd->advertising = bp->port.advertising; + + if ((bp->state == BNX2X_STATE_OPEN) && + !(bp->flags & MF_FUNC_DIS) && + (bp->link_vars.link_up)) { + cmd->speed = bp->link_vars.line_speed; + cmd->duplex = bp->link_vars.duplex; + if (IS_E1HMF(bp)) { + u16 vn_max_rate; + + vn_max_rate = + ((bp->mf_config & FUNC_MF_CFG_MAX_BW_MASK) >> + FUNC_MF_CFG_MAX_BW_SHIFT) * 100; + if (vn_max_rate < cmd->speed) + cmd->speed = vn_max_rate; + } + } else { + cmd->speed = -1; + cmd->duplex = -1; + } + + if (bp->link_params.switch_cfg == SWITCH_CFG_10G) { + u32 ext_phy_type = + XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config); + + switch (ext_phy_type) { + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727: + cmd->port = PORT_FIBRE; + break; + + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481: + cmd->port = PORT_TP; + break; + + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE: + BNX2X_ERR("XGXS PHY Failure detected 0x%x\n", + bp->link_params.ext_phy_config); + break; + + default: + DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n", + bp->link_params.ext_phy_config); + break; + } + } else + cmd->port = PORT_TP; + + cmd->phy_address = bp->mdio.prtad; + cmd->transceiver = XCVR_INTERNAL; + + if (bp->link_params.req_line_speed == SPEED_AUTO_NEG) + cmd->autoneg = AUTONEG_ENABLE; + else + cmd->autoneg = AUTONEG_DISABLE; + + cmd->maxtxpkt = 0; + cmd->maxrxpkt = 0; + + DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n" + DP_LEVEL " supported 0x%x advertising 0x%x speed %d\n" + DP_LEVEL " duplex %d port %d phy_address %d transceiver %d\n" + DP_LEVEL " autoneg %d maxtxpkt %d maxrxpkt %d\n", + cmd->cmd, cmd->supported, cmd->advertising, cmd->speed, + cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver, + cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt); + + return 0; +} + +static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct bnx2x *bp = netdev_priv(dev); + u32 advertising; + + if (IS_E1HMF(bp)) + return 0; + + DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n" + DP_LEVEL " supported 0x%x advertising 0x%x speed %d\n" + DP_LEVEL " duplex %d port %d phy_address %d transceiver %d\n" + DP_LEVEL " autoneg %d maxtxpkt %d maxrxpkt %d\n", + cmd->cmd, cmd->supported, cmd->advertising, cmd->speed, + cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver, + cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt); + + if (cmd->autoneg == AUTONEG_ENABLE) { + if (!(bp->port.supported & SUPPORTED_Autoneg)) { + DP(NETIF_MSG_LINK, "Autoneg not supported\n"); + return -EINVAL; + } + + /* advertise the requested speed and duplex if supported */ + cmd->advertising &= bp->port.supported; + + bp->link_params.req_line_speed = SPEED_AUTO_NEG; + bp->link_params.req_duplex = DUPLEX_FULL; + bp->port.advertising |= (ADVERTISED_Autoneg | + cmd->advertising); + + } else { /* forced speed */ + /* advertise the requested speed and duplex if supported */ + switch (cmd->speed) { + case SPEED_10: + if (cmd->duplex == DUPLEX_FULL) { + if (!(bp->port.supported & + SUPPORTED_10baseT_Full)) { + DP(NETIF_MSG_LINK, + "10M full not supported\n"); + return -EINVAL; + } + + advertising = (ADVERTISED_10baseT_Full | + ADVERTISED_TP); + } else { + if (!(bp->port.supported & + SUPPORTED_10baseT_Half)) { + DP(NETIF_MSG_LINK, + "10M half not supported\n"); + return -EINVAL; + } + + advertising = (ADVERTISED_10baseT_Half | + ADVERTISED_TP); + } + break; + + case SPEED_100: + if (cmd->duplex == DUPLEX_FULL) { + if (!(bp->port.supported & + SUPPORTED_100baseT_Full)) { + DP(NETIF_MSG_LINK, + "100M full not supported\n"); + return -EINVAL; + } + + advertising = (ADVERTISED_100baseT_Full | + ADVERTISED_TP); + } else { + if (!(bp->port.supported & + SUPPORTED_100baseT_Half)) { + DP(NETIF_MSG_LINK, + "100M half not supported\n"); + return -EINVAL; + } + + advertising = (ADVERTISED_100baseT_Half | + ADVERTISED_TP); + } + break; + + case SPEED_1000: + if (cmd->duplex != DUPLEX_FULL) { + DP(NETIF_MSG_LINK, "1G half not supported\n"); + return -EINVAL; + } + + if (!(bp->port.supported & SUPPORTED_1000baseT_Full)) { + DP(NETIF_MSG_LINK, "1G full not supported\n"); + return -EINVAL; + } + + advertising = (ADVERTISED_1000baseT_Full | + ADVERTISED_TP); + break; + + case SPEED_2500: + if (cmd->duplex != DUPLEX_FULL) { + DP(NETIF_MSG_LINK, + "2.5G half not supported\n"); + return -EINVAL; + } + + if (!(bp->port.supported & SUPPORTED_2500baseX_Full)) { + DP(NETIF_MSG_LINK, + "2.5G full not supported\n"); + return -EINVAL; + } + + advertising = (ADVERTISED_2500baseX_Full | + ADVERTISED_TP); + break; + + case SPEED_10000: + if (cmd->duplex != DUPLEX_FULL) { + DP(NETIF_MSG_LINK, "10G half not supported\n"); + return -EINVAL; + } + + if (!(bp->port.supported & SUPPORTED_10000baseT_Full)) { + DP(NETIF_MSG_LINK, "10G full not supported\n"); + return -EINVAL; + } + + advertising = (ADVERTISED_10000baseT_Full | + ADVERTISED_FIBRE); + break; + + default: + DP(NETIF_MSG_LINK, "Unsupported speed\n"); + return -EINVAL; + } + + bp->link_params.req_line_speed = cmd->speed; + bp->link_params.req_duplex = cmd->duplex; + bp->port.advertising = advertising; + } + + DP(NETIF_MSG_LINK, "req_line_speed %d\n" + DP_LEVEL " req_duplex %d advertising 0x%x\n", + bp->link_params.req_line_speed, bp->link_params.req_duplex, + bp->port.advertising); + + if (netif_running(dev)) { + bnx2x_stats_handle(bp, STATS_EVENT_STOP); + bnx2x_link_set(bp); + } + + return 0; +} + +#define IS_E1_ONLINE(info) (((info) & RI_E1_ONLINE) == RI_E1_ONLINE) +#define IS_E1H_ONLINE(info) (((info) & RI_E1H_ONLINE) == RI_E1H_ONLINE) + +static int bnx2x_get_regs_len(struct net_device *dev) +{ + struct bnx2x *bp = netdev_priv(dev); + int regdump_len = 0; + int i; + + if (CHIP_IS_E1(bp)) { + for (i = 0; i < REGS_COUNT; i++) + if (IS_E1_ONLINE(reg_addrs[i].info)) + regdump_len += reg_addrs[i].size; + + for (i = 0; i < WREGS_COUNT_E1; i++) + if (IS_E1_ONLINE(wreg_addrs_e1[i].info)) + regdump_len += wreg_addrs_e1[i].size * + (1 + wreg_addrs_e1[i].read_regs_count); + + } else { /* E1H */ + for (i = 0; i < REGS_COUNT; i++) + if (IS_E1H_ONLINE(reg_addrs[i].info)) + regdump_len += reg_addrs[i].size; + + for (i = 0; i < WREGS_COUNT_E1H; i++) + if (IS_E1H_ONLINE(wreg_addrs_e1h[i].info)) + regdump_len += wreg_addrs_e1h[i].size * + (1 + wreg_addrs_e1h[i].read_regs_count); + } + regdump_len *= 4; + regdump_len += sizeof(struct dump_hdr); + + return regdump_len; +} + +static void bnx2x_get_regs(struct net_device *dev, + struct ethtool_regs *regs, void *_p) +{ + u32 *p = _p, i, j; + struct bnx2x *bp = netdev_priv(dev); + struct dump_hdr dump_hdr = {0}; + + regs->version = 0; + memset(p, 0, regs->len); + + if (!netif_running(bp->dev)) + return; + + dump_hdr.hdr_size = (sizeof(struct dump_hdr) / 4) - 1; + dump_hdr.dump_sign = dump_sign_all; + dump_hdr.xstorm_waitp = REG_RD(bp, XSTORM_WAITP_ADDR); + dump_hdr.tstorm_waitp = REG_RD(bp, TSTORM_WAITP_ADDR); + dump_hdr.ustorm_waitp = REG_RD(bp, USTORM_WAITP_ADDR); + dump_hdr.cstorm_waitp = REG_RD(bp, CSTORM_WAITP_ADDR); + dump_hdr.info = CHIP_IS_E1(bp) ? RI_E1_ONLINE : RI_E1H_ONLINE; + + memcpy(p, &dump_hdr, sizeof(struct dump_hdr)); + p += dump_hdr.hdr_size + 1; + + if (CHIP_IS_E1(bp)) { + for (i = 0; i < REGS_COUNT; i++) + if (IS_E1_ONLINE(reg_addrs[i].info)) + for (j = 0; j < reg_addrs[i].size; j++) + *p++ = REG_RD(bp, + reg_addrs[i].addr + j*4); + + } else { /* E1H */ + for (i = 0; i < REGS_COUNT; i++) + if (IS_E1H_ONLINE(reg_addrs[i].info)) + for (j = 0; j < reg_addrs[i].size; j++) + *p++ = REG_RD(bp, + reg_addrs[i].addr + j*4); + } +} + +#define PHY_FW_VER_LEN 10 + +static void bnx2x_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + struct bnx2x *bp = netdev_priv(dev); + u8 phy_fw_ver[PHY_FW_VER_LEN]; + + strcpy(info->driver, DRV_MODULE_NAME); + strcpy(info->version, DRV_MODULE_VERSION); + + phy_fw_ver[0] = '\0'; + if (bp->port.pmf) { + bnx2x_acquire_phy_lock(bp); + bnx2x_get_ext_phy_fw_version(&bp->link_params, + (bp->state != BNX2X_STATE_CLOSED), + phy_fw_ver, PHY_FW_VER_LEN); + bnx2x_release_phy_lock(bp); + } + + strncpy(info->fw_version, bp->fw_ver, 32); + snprintf(info->fw_version + strlen(bp->fw_ver), 32 - strlen(bp->fw_ver), + "bc %d.%d.%d%s%s", + (bp->common.bc_ver & 0xff0000) >> 16, + (bp->common.bc_ver & 0xff00) >> 8, + (bp->common.bc_ver & 0xff), + ((phy_fw_ver[0] != '\0') ? " phy " : ""), phy_fw_ver); + strcpy(info->bus_info, pci_name(bp->pdev)); + info->n_stats = BNX2X_NUM_STATS; + info->testinfo_len = BNX2X_NUM_TESTS; + info->eedump_len = bp->common.flash_size; + info->regdump_len = bnx2x_get_regs_len(dev); +} + +static void bnx2x_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct bnx2x *bp = netdev_priv(dev); + + if (bp->flags & NO_WOL_FLAG) { + wol->supported = 0; + wol->wolopts = 0; + } else { + wol->supported = WAKE_MAGIC; + if (bp->wol) + wol->wolopts = WAKE_MAGIC; + else + wol->wolopts = 0; + } + memset(&wol->sopass, 0, sizeof(wol->sopass)); +} + +static int bnx2x_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct bnx2x *bp = netdev_priv(dev); + + if (wol->wolopts & ~WAKE_MAGIC) + return -EINVAL; + + if (wol->wolopts & WAKE_MAGIC) { + if (bp->flags & NO_WOL_FLAG) + return -EINVAL; + + bp->wol = 1; + } else + bp->wol = 0; + + return 0; +} + +static u32 bnx2x_get_msglevel(struct net_device *dev) +{ + struct bnx2x *bp = netdev_priv(dev); + + return bp->msg_enable; +} + +static void bnx2x_set_msglevel(struct net_device *dev, u32 level) +{ + struct bnx2x *bp = netdev_priv(dev); + + if (capable(CAP_NET_ADMIN)) + bp->msg_enable = level; +} + +static int bnx2x_nway_reset(struct net_device *dev) +{ + struct bnx2x *bp = netdev_priv(dev); + + if (!bp->port.pmf) + return 0; + + if (netif_running(dev)) { + bnx2x_stats_handle(bp, STATS_EVENT_STOP); + bnx2x_link_set(bp); + } + + return 0; +} + +static u32 bnx2x_get_link(struct net_device *dev) +{ + struct bnx2x *bp = netdev_priv(dev); + + if (bp->flags & MF_FUNC_DIS) + return 0; + + return bp->link_vars.link_up; +} + +static int bnx2x_get_eeprom_len(struct net_device *dev) +{ + struct bnx2x *bp = netdev_priv(dev); + + return bp->common.flash_size; +} + +static int bnx2x_acquire_nvram_lock(struct bnx2x *bp) +{ + int port = BP_PORT(bp); + int count, i; + u32 val = 0; + + /* adjust timeout for emulation/FPGA */ + count = NVRAM_TIMEOUT_COUNT; + if (CHIP_REV_IS_SLOW(bp)) + count *= 100; + + /* request access to nvram interface */ + REG_WR(bp, MCP_REG_MCPR_NVM_SW_ARB, + (MCPR_NVM_SW_ARB_ARB_REQ_SET1 << port)); + + for (i = 0; i < count*10; i++) { + val = REG_RD(bp, MCP_REG_MCPR_NVM_SW_ARB); + if (val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port)) + break; + + udelay(5); + } + + if (!(val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port))) { + DP(BNX2X_MSG_NVM, "cannot get access to nvram interface\n"); + return -EBUSY; + } + + return 0; +} + +static int bnx2x_release_nvram_lock(struct bnx2x *bp) +{ + int port = BP_PORT(bp); + int count, i; + u32 val = 0; + + /* adjust timeout for emulation/FPGA */ + count = NVRAM_TIMEOUT_COUNT; + if (CHIP_REV_IS_SLOW(bp)) + count *= 100; + + /* relinquish nvram interface */ + REG_WR(bp, MCP_REG_MCPR_NVM_SW_ARB, + (MCPR_NVM_SW_ARB_ARB_REQ_CLR1 << port)); + + for (i = 0; i < count*10; i++) { + val = REG_RD(bp, MCP_REG_MCPR_NVM_SW_ARB); + if (!(val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port))) + break; + + udelay(5); + } + + if (val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port)) { + DP(BNX2X_MSG_NVM, "cannot free access to nvram interface\n"); + return -EBUSY; + } + + return 0; +} + +static void bnx2x_enable_nvram_access(struct bnx2x *bp) +{ + u32 val; + + val = REG_RD(bp, MCP_REG_MCPR_NVM_ACCESS_ENABLE); + + /* enable both bits, even on read */ + REG_WR(bp, MCP_REG_MCPR_NVM_ACCESS_ENABLE, + (val | MCPR_NVM_ACCESS_ENABLE_EN | + MCPR_NVM_ACCESS_ENABLE_WR_EN)); +} + +static void bnx2x_disable_nvram_access(struct bnx2x *bp) +{ + u32 val; + + val = REG_RD(bp, MCP_REG_MCPR_NVM_ACCESS_ENABLE); + + /* disable both bits, even after read */ + REG_WR(bp, MCP_REG_MCPR_NVM_ACCESS_ENABLE, + (val & ~(MCPR_NVM_ACCESS_ENABLE_EN | + MCPR_NVM_ACCESS_ENABLE_WR_EN))); +} + +static int bnx2x_nvram_read_dword(struct bnx2x *bp, u32 offset, __be32 *ret_val, + u32 cmd_flags) +{ + int count, i, rc; + u32 val; + + /* build the command word */ + cmd_flags |= MCPR_NVM_COMMAND_DOIT; + + /* need to clear DONE bit separately */ + REG_WR(bp, MCP_REG_MCPR_NVM_COMMAND, MCPR_NVM_COMMAND_DONE); + + /* address of the NVRAM to read from */ + REG_WR(bp, MCP_REG_MCPR_NVM_ADDR, + (offset & MCPR_NVM_ADDR_NVM_ADDR_VALUE)); + + /* issue a read command */ + REG_WR(bp, MCP_REG_MCPR_NVM_COMMAND, cmd_flags); + + /* adjust timeout for emulation/FPGA */ + count = NVRAM_TIMEOUT_COUNT; + if (CHIP_REV_IS_SLOW(bp)) + count *= 100; + + /* wait for completion */ + *ret_val = 0; + rc = -EBUSY; + for (i = 0; i < count; i++) { + udelay(5); + val = REG_RD(bp, MCP_REG_MCPR_NVM_COMMAND); + + if (val & MCPR_NVM_COMMAND_DONE) { + val = REG_RD(bp, MCP_REG_MCPR_NVM_READ); + /* we read nvram data in cpu order + * but ethtool sees it as an array of bytes + * converting to big-endian will do the work */ + *ret_val = cpu_to_be32(val); + rc = 0; + break; + } + } + + return rc; +} + +static int bnx2x_nvram_read(struct bnx2x *bp, u32 offset, u8 *ret_buf, + int buf_size) +{ + int rc; + u32 cmd_flags; + __be32 val; + + if ((offset & 0x03) || (buf_size & 0x03) || (buf_size == 0)) { + DP(BNX2X_MSG_NVM, + "Invalid parameter: offset 0x%x buf_size 0x%x\n", + offset, buf_size); + return -EINVAL; + } + + if (offset + buf_size > bp->common.flash_size) { + DP(BNX2X_MSG_NVM, "Invalid parameter: offset (0x%x) +" + " buf_size (0x%x) > flash_size (0x%x)\n", + offset, buf_size, bp->common.flash_size); + return -EINVAL; + } + + /* request access to nvram interface */ + rc = bnx2x_acquire_nvram_lock(bp); + if (rc) + return rc; + + /* enable access to nvram interface */ + bnx2x_enable_nvram_access(bp); + + /* read the first word(s) */ + cmd_flags = MCPR_NVM_COMMAND_FIRST; + while ((buf_size > sizeof(u32)) && (rc == 0)) { + rc = bnx2x_nvram_read_dword(bp, offset, &val, cmd_flags); + memcpy(ret_buf, &val, 4); + + /* advance to the next dword */ + offset += sizeof(u32); + ret_buf += sizeof(u32); + buf_size -= sizeof(u32); + cmd_flags = 0; + } + + if (rc == 0) { + cmd_flags |= MCPR_NVM_COMMAND_LAST; + rc = bnx2x_nvram_read_dword(bp, offset, &val, cmd_flags); + memcpy(ret_buf, &val, 4); + } + + /* disable access to nvram interface */ + bnx2x_disable_nvram_access(bp); + bnx2x_release_nvram_lock(bp); + + return rc; +} + +static int bnx2x_get_eeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *eebuf) +{ + struct bnx2x *bp = netdev_priv(dev); + int rc; + + if (!netif_running(dev)) + return -EAGAIN; + + DP(BNX2X_MSG_NVM, "ethtool_eeprom: cmd %d\n" + DP_LEVEL " magic 0x%x offset 0x%x (%d) len 0x%x (%d)\n", + eeprom->cmd, eeprom->magic, eeprom->offset, eeprom->offset, + eeprom->len, eeprom->len); + + /* parameters already validated in ethtool_get_eeprom */ + + rc = bnx2x_nvram_read(bp, eeprom->offset, eebuf, eeprom->len); + + return rc; +} + +static int bnx2x_nvram_write_dword(struct bnx2x *bp, u32 offset, u32 val, + u32 cmd_flags) +{ + int count, i, rc; + + /* build the command word */ + cmd_flags |= MCPR_NVM_COMMAND_DOIT | MCPR_NVM_COMMAND_WR; + + /* need to clear DONE bit separately */ + REG_WR(bp, MCP_REG_MCPR_NVM_COMMAND, MCPR_NVM_COMMAND_DONE); + + /* write the data */ + REG_WR(bp, MCP_REG_MCPR_NVM_WRITE, val); + + /* address of the NVRAM to write to */ + REG_WR(bp, MCP_REG_MCPR_NVM_ADDR, + (offset & MCPR_NVM_ADDR_NVM_ADDR_VALUE)); + + /* issue the write command */ + REG_WR(bp, MCP_REG_MCPR_NVM_COMMAND, cmd_flags); + + /* adjust timeout for emulation/FPGA */ + count = NVRAM_TIMEOUT_COUNT; + if (CHIP_REV_IS_SLOW(bp)) + count *= 100; + + /* wait for completion */ + rc = -EBUSY; + for (i = 0; i < count; i++) { + udelay(5); + val = REG_RD(bp, MCP_REG_MCPR_NVM_COMMAND); + if (val & MCPR_NVM_COMMAND_DONE) { + rc = 0; + break; + } + } + + return rc; +} + +#define BYTE_OFFSET(offset) (8 * (offset & 0x03)) + +static int bnx2x_nvram_write1(struct bnx2x *bp, u32 offset, u8 *data_buf, + int buf_size) +{ + int rc; + u32 cmd_flags; + u32 align_offset; + __be32 val; + + if (offset + buf_size > bp->common.flash_size) { + DP(BNX2X_MSG_NVM, "Invalid parameter: offset (0x%x) +" + " buf_size (0x%x) > flash_size (0x%x)\n", + offset, buf_size, bp->common.flash_size); + return -EINVAL; + } + + /* request access to nvram interface */ + rc = bnx2x_acquire_nvram_lock(bp); + if (rc) + return rc; + + /* enable access to nvram interface */ + bnx2x_enable_nvram_access(bp); + + cmd_flags = (MCPR_NVM_COMMAND_FIRST | MCPR_NVM_COMMAND_LAST); + align_offset = (offset & ~0x03); + rc = bnx2x_nvram_read_dword(bp, align_offset, &val, cmd_flags); + + if (rc == 0) { + val &= ~(0xff << BYTE_OFFSET(offset)); + val |= (*data_buf << BYTE_OFFSET(offset)); + + /* nvram data is returned as an array of bytes + * convert it back to cpu order */ + val = be32_to_cpu(val); + + rc = bnx2x_nvram_write_dword(bp, align_offset, val, + cmd_flags); + } + + /* disable access to nvram interface */ + bnx2x_disable_nvram_access(bp); + bnx2x_release_nvram_lock(bp); + + return rc; +} + +static int bnx2x_nvram_write(struct bnx2x *bp, u32 offset, u8 *data_buf, + int buf_size) +{ + int rc; + u32 cmd_flags; + u32 val; + u32 written_so_far; + + if (buf_size == 1) /* ethtool */ + return bnx2x_nvram_write1(bp, offset, data_buf, buf_size); + + if ((offset & 0x03) || (buf_size & 0x03) || (buf_size == 0)) { + DP(BNX2X_MSG_NVM, + "Invalid parameter: offset 0x%x buf_size 0x%x\n", + offset, buf_size); + return -EINVAL; + } + + if (offset + buf_size > bp->common.flash_size) { + DP(BNX2X_MSG_NVM, "Invalid parameter: offset (0x%x) +" + " buf_size (0x%x) > flash_size (0x%x)\n", + offset, buf_size, bp->common.flash_size); + return -EINVAL; + } + + /* request access to nvram interface */ + rc = bnx2x_acquire_nvram_lock(bp); + if (rc) + return rc; + + /* enable access to nvram interface */ + bnx2x_enable_nvram_access(bp); + + written_so_far = 0; + cmd_flags = MCPR_NVM_COMMAND_FIRST; + while ((written_so_far < buf_size) && (rc == 0)) { + if (written_so_far == (buf_size - sizeof(u32))) + cmd_flags |= MCPR_NVM_COMMAND_LAST; + else if (((offset + 4) % NVRAM_PAGE_SIZE) == 0) + cmd_flags |= MCPR_NVM_COMMAND_LAST; + else if ((offset % NVRAM_PAGE_SIZE) == 0) + cmd_flags |= MCPR_NVM_COMMAND_FIRST; + + memcpy(&val, data_buf, 4); + + rc = bnx2x_nvram_write_dword(bp, offset, val, cmd_flags); + + /* advance to the next dword */ + offset += sizeof(u32); + data_buf += sizeof(u32); + written_so_far += sizeof(u32); + cmd_flags = 0; + } + + /* disable access to nvram interface */ + bnx2x_disable_nvram_access(bp); + bnx2x_release_nvram_lock(bp); + + return rc; +} + +static int bnx2x_set_eeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *eebuf) +{ + struct bnx2x *bp = netdev_priv(dev); + int port = BP_PORT(bp); + int rc = 0; + + if (!netif_running(dev)) + return -EAGAIN; + + DP(BNX2X_MSG_NVM, "ethtool_eeprom: cmd %d\n" + DP_LEVEL " magic 0x%x offset 0x%x (%d) len 0x%x (%d)\n", + eeprom->cmd, eeprom->magic, eeprom->offset, eeprom->offset, + eeprom->len, eeprom->len); + + /* parameters already validated in ethtool_set_eeprom */ + + /* PHY eeprom can be accessed only by the PMF */ + if ((eeprom->magic >= 0x50485900) && (eeprom->magic <= 0x504859FF) && + !bp->port.pmf) + return -EINVAL; + + if (eeprom->magic == 0x50485950) { + /* 'PHYP' (0x50485950): prepare phy for FW upgrade */ + bnx2x_stats_handle(bp, STATS_EVENT_STOP); + + bnx2x_acquire_phy_lock(bp); + rc |= bnx2x_link_reset(&bp->link_params, + &bp->link_vars, 0); + if (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config) == + PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101) + bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, + MISC_REGISTERS_GPIO_HIGH, port); + bnx2x_release_phy_lock(bp); + bnx2x_link_report(bp); + + } else if (eeprom->magic == 0x50485952) { + /* 'PHYR' (0x50485952): re-init link after FW upgrade */ + if (bp->state == BNX2X_STATE_OPEN) { + bnx2x_acquire_phy_lock(bp); + rc |= bnx2x_link_reset(&bp->link_params, + &bp->link_vars, 1); + + rc |= bnx2x_phy_init(&bp->link_params, + &bp->link_vars); + bnx2x_release_phy_lock(bp); + bnx2x_calc_fc_adv(bp); + } + } else if (eeprom->magic == 0x53985943) { + /* 'PHYC' (0x53985943): PHY FW upgrade completed */ + if (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config) == + PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101) { + u8 ext_phy_addr = + XGXS_EXT_PHY_ADDR(bp->link_params.ext_phy_config); + + /* DSP Remove Download Mode */ + bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, + MISC_REGISTERS_GPIO_LOW, port); + + bnx2x_acquire_phy_lock(bp); + + bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr); + + /* wait 0.5 sec to allow it to run */ + msleep(500); + bnx2x_ext_phy_hw_reset(bp, port); + msleep(500); + bnx2x_release_phy_lock(bp); + } + } else + rc = bnx2x_nvram_write(bp, eeprom->offset, eebuf, eeprom->len); + + return rc; +} +static int bnx2x_get_coalesce(struct net_device *dev, + struct ethtool_coalesce *coal) +{ + struct bnx2x *bp = netdev_priv(dev); + + memset(coal, 0, sizeof(struct ethtool_coalesce)); + + coal->rx_coalesce_usecs = bp->rx_ticks; + coal->tx_coalesce_usecs = bp->tx_ticks; + + return 0; +} + +static int bnx2x_set_coalesce(struct net_device *dev, + struct ethtool_coalesce *coal) +{ + struct bnx2x *bp = netdev_priv(dev); + + bp->rx_ticks = (u16)coal->rx_coalesce_usecs; + if (bp->rx_ticks > BNX2X_MAX_COALESCE_TOUT) + bp->rx_ticks = BNX2X_MAX_COALESCE_TOUT; + + bp->tx_ticks = (u16)coal->tx_coalesce_usecs; + if (bp->tx_ticks > BNX2X_MAX_COALESCE_TOUT) + bp->tx_ticks = BNX2X_MAX_COALESCE_TOUT; + + if (netif_running(dev)) + bnx2x_update_coalesce(bp); + + return 0; +} + +static void bnx2x_get_ringparam(struct net_device *dev, + struct ethtool_ringparam *ering) +{ + struct bnx2x *bp = netdev_priv(dev); + + ering->rx_max_pending = MAX_RX_AVAIL; + ering->rx_mini_max_pending = 0; + ering->rx_jumbo_max_pending = 0; + + ering->rx_pending = bp->rx_ring_size; + ering->rx_mini_pending = 0; + ering->rx_jumbo_pending = 0; + + ering->tx_max_pending = MAX_TX_AVAIL; + ering->tx_pending = bp->tx_ring_size; +} + +static int bnx2x_set_ringparam(struct net_device *dev, + struct ethtool_ringparam *ering) +{ + struct bnx2x *bp = netdev_priv(dev); + int rc = 0; + + if (bp->recovery_state != BNX2X_RECOVERY_DONE) { + printk(KERN_ERR "Handling parity error recovery. Try again later\n"); + return -EAGAIN; + } + + if ((ering->rx_pending > MAX_RX_AVAIL) || + (ering->tx_pending > MAX_TX_AVAIL) || + (ering->tx_pending <= MAX_SKB_FRAGS + 4)) + return -EINVAL; + + bp->rx_ring_size = ering->rx_pending; + bp->tx_ring_size = ering->tx_pending; + + if (netif_running(dev)) { + bnx2x_nic_unload(bp, UNLOAD_NORMAL); + rc = bnx2x_nic_load(bp, LOAD_NORMAL); + } + + return rc; +} + +static void bnx2x_get_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *epause) +{ + struct bnx2x *bp = netdev_priv(dev); + + epause->autoneg = (bp->link_params.req_flow_ctrl == + BNX2X_FLOW_CTRL_AUTO) && + (bp->link_params.req_line_speed == SPEED_AUTO_NEG); + + epause->rx_pause = ((bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) == + BNX2X_FLOW_CTRL_RX); + epause->tx_pause = ((bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX) == + BNX2X_FLOW_CTRL_TX); + + DP(NETIF_MSG_LINK, "ethtool_pauseparam: cmd %d\n" + DP_LEVEL " autoneg %d rx_pause %d tx_pause %d\n", + epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause); +} + +static int bnx2x_set_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *epause) +{ + struct bnx2x *bp = netdev_priv(dev); + + if (IS_E1HMF(bp)) + return 0; + + DP(NETIF_MSG_LINK, "ethtool_pauseparam: cmd %d\n" + DP_LEVEL " autoneg %d rx_pause %d tx_pause %d\n", + epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause); + + bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO; + + if (epause->rx_pause) + bp->link_params.req_flow_ctrl |= BNX2X_FLOW_CTRL_RX; + + if (epause->tx_pause) + bp->link_params.req_flow_ctrl |= BNX2X_FLOW_CTRL_TX; + + if (bp->link_params.req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) + bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_NONE; + + if (epause->autoneg) { + if (!(bp->port.supported & SUPPORTED_Autoneg)) { + DP(NETIF_MSG_LINK, "autoneg not supported\n"); + return -EINVAL; + } + + if (bp->link_params.req_line_speed == SPEED_AUTO_NEG) + bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO; + } + + DP(NETIF_MSG_LINK, + "req_flow_ctrl 0x%x\n", bp->link_params.req_flow_ctrl); + + if (netif_running(dev)) { + bnx2x_stats_handle(bp, STATS_EVENT_STOP); + bnx2x_link_set(bp); + } + + return 0; +} + +static int bnx2x_set_flags(struct net_device *dev, u32 data) +{ + struct bnx2x *bp = netdev_priv(dev); + int changed = 0; + int rc = 0; + + if (data & ~(ETH_FLAG_LRO | ETH_FLAG_RXHASH)) + return -EINVAL; + + if (bp->recovery_state != BNX2X_RECOVERY_DONE) { + printk(KERN_ERR "Handling parity error recovery. Try again later\n"); + return -EAGAIN; + } + + /* TPA requires Rx CSUM offloading */ + if ((data & ETH_FLAG_LRO) && bp->rx_csum) { + if (!bp->disable_tpa) { + if (!(dev->features & NETIF_F_LRO)) { + dev->features |= NETIF_F_LRO; + bp->flags |= TPA_ENABLE_FLAG; + changed = 1; + } + } else + rc = -EINVAL; + } else if (dev->features & NETIF_F_LRO) { + dev->features &= ~NETIF_F_LRO; + bp->flags &= ~TPA_ENABLE_FLAG; + changed = 1; + } + + if (data & ETH_FLAG_RXHASH) + dev->features |= NETIF_F_RXHASH; + else + dev->features &= ~NETIF_F_RXHASH; + + if (changed && netif_running(dev)) { + bnx2x_nic_unload(bp, UNLOAD_NORMAL); + rc = bnx2x_nic_load(bp, LOAD_NORMAL); + } + + return rc; +} + +static u32 bnx2x_get_rx_csum(struct net_device *dev) +{ + struct bnx2x *bp = netdev_priv(dev); + + return bp->rx_csum; +} + +static int bnx2x_set_rx_csum(struct net_device *dev, u32 data) +{ + struct bnx2x *bp = netdev_priv(dev); + int rc = 0; + + if (bp->recovery_state != BNX2X_RECOVERY_DONE) { + printk(KERN_ERR "Handling parity error recovery. Try again later\n"); + return -EAGAIN; + } + + bp->rx_csum = data; + + /* Disable TPA, when Rx CSUM is disabled. Otherwise all + TPA'ed packets will be discarded due to wrong TCP CSUM */ + if (!data) { + u32 flags = ethtool_op_get_flags(dev); + + rc = bnx2x_set_flags(dev, (flags & ~ETH_FLAG_LRO)); + } + + return rc; +} + +static int bnx2x_set_tso(struct net_device *dev, u32 data) +{ + if (data) { + dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN); + dev->features |= NETIF_F_TSO6; + } else { + dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO_ECN); + dev->features &= ~NETIF_F_TSO6; + } + + return 0; +} + +static const struct { + char string[ETH_GSTRING_LEN]; +} bnx2x_tests_str_arr[BNX2X_NUM_TESTS] = { + { "register_test (offline)" }, + { "memory_test (offline)" }, + { "loopback_test (offline)" }, + { "nvram_test (online)" }, + { "interrupt_test (online)" }, + { "link_test (online)" }, + { "idle check (online)" } +}; + +static int bnx2x_test_registers(struct bnx2x *bp) +{ + int idx, i, rc = -ENODEV; + u32 wr_val = 0; + int port = BP_PORT(bp); + static const struct { + u32 offset0; + u32 offset1; + u32 mask; + } reg_tbl[] = { +/* 0 */ { BRB1_REG_PAUSE_LOW_THRESHOLD_0, 4, 0x000003ff }, + { DORQ_REG_DB_ADDR0, 4, 0xffffffff }, + { HC_REG_AGG_INT_0, 4, 0x000003ff }, + { PBF_REG_MAC_IF0_ENABLE, 4, 0x00000001 }, + { PBF_REG_P0_INIT_CRD, 4, 0x000007ff }, + { PRS_REG_CID_PORT_0, 4, 0x00ffffff }, + { PXP2_REG_PSWRQ_CDU0_L2P, 4, 0x000fffff }, + { PXP2_REG_RQ_CDU0_EFIRST_MEM_ADDR, 8, 0x0003ffff }, + { PXP2_REG_PSWRQ_TM0_L2P, 4, 0x000fffff }, + { PXP2_REG_RQ_USDM0_EFIRST_MEM_ADDR, 8, 0x0003ffff }, +/* 10 */ { PXP2_REG_PSWRQ_TSDM0_L2P, 4, 0x000fffff }, + { QM_REG_CONNNUM_0, 4, 0x000fffff }, + { TM_REG_LIN0_MAX_ACTIVE_CID, 4, 0x0003ffff }, + { SRC_REG_KEYRSS0_0, 40, 0xffffffff }, + { SRC_REG_KEYRSS0_7, 40, 0xffffffff }, + { XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 4, 0x00000001 }, + { XCM_REG_WU_DA_CNT_CMD00, 4, 0x00000003 }, + { XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 4, 0x000000ff }, + { NIG_REG_LLH0_T_BIT, 4, 0x00000001 }, + { NIG_REG_EMAC0_IN_EN, 4, 0x00000001 }, +/* 20 */ { NIG_REG_BMAC0_IN_EN, 4, 0x00000001 }, + { NIG_REG_XCM0_OUT_EN, 4, 0x00000001 }, + { NIG_REG_BRB0_OUT_EN, 4, 0x00000001 }, + { NIG_REG_LLH0_XCM_MASK, 4, 0x00000007 }, + { NIG_REG_LLH0_ACPI_PAT_6_LEN, 68, 0x000000ff }, + { NIG_REG_LLH0_ACPI_PAT_0_CRC, 68, 0xffffffff }, + { NIG_REG_LLH0_DEST_MAC_0_0, 160, 0xffffffff }, + { NIG_REG_LLH0_DEST_IP_0_1, 160, 0xffffffff }, + { NIG_REG_LLH0_IPV4_IPV6_0, 160, 0x00000001 }, + { NIG_REG_LLH0_DEST_UDP_0, 160, 0x0000ffff }, +/* 30 */ { NIG_REG_LLH0_DEST_TCP_0, 160, 0x0000ffff }, + { NIG_REG_LLH0_VLAN_ID_0, 160, 0x00000fff }, + { NIG_REG_XGXS_SERDES0_MODE_SEL, 4, 0x00000001 }, + { NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0, 4, 0x00000001 }, + { NIG_REG_STATUS_INTERRUPT_PORT0, 4, 0x07ffffff }, + { NIG_REG_XGXS0_CTRL_EXTREMOTEMDIOST, 24, 0x00000001 }, + { NIG_REG_SERDES0_CTRL_PHY_ADDR, 16, 0x0000001f }, + + { 0xffffffff, 0, 0x00000000 } + }; + + if (!netif_running(bp->dev)) + return rc; + + /* Repeat the test twice: + First by writing 0x00000000, second by writing 0xffffffff */ + for (idx = 0; idx < 2; idx++) { + + switch (idx) { + case 0: + wr_val = 0; + break; + case 1: + wr_val = 0xffffffff; + break; + } + + for (i = 0; reg_tbl[i].offset0 != 0xffffffff; i++) { + u32 offset, mask, save_val, val; + + offset = reg_tbl[i].offset0 + port*reg_tbl[i].offset1; + mask = reg_tbl[i].mask; + + save_val = REG_RD(bp, offset); + + REG_WR(bp, offset, (wr_val & mask)); + val = REG_RD(bp, offset); + + /* Restore the original register's value */ + REG_WR(bp, offset, save_val); + + /* verify value is as expected */ + if ((val & mask) != (wr_val & mask)) { + DP(NETIF_MSG_PROBE, + "offset 0x%x: val 0x%x != 0x%x mask 0x%x\n", + offset, val, wr_val, mask); + goto test_reg_exit; + } + } + } + + rc = 0; + +test_reg_exit: + return rc; +} + +static int bnx2x_test_memory(struct bnx2x *bp) +{ + int i, j, rc = -ENODEV; + u32 val; + static const struct { + u32 offset; + int size; + } mem_tbl[] = { + { CCM_REG_XX_DESCR_TABLE, CCM_REG_XX_DESCR_TABLE_SIZE }, + { CFC_REG_ACTIVITY_COUNTER, CFC_REG_ACTIVITY_COUNTER_SIZE }, + { CFC_REG_LINK_LIST, CFC_REG_LINK_LIST_SIZE }, + { DMAE_REG_CMD_MEM, DMAE_REG_CMD_MEM_SIZE }, + { TCM_REG_XX_DESCR_TABLE, TCM_REG_XX_DESCR_TABLE_SIZE }, + { UCM_REG_XX_DESCR_TABLE, UCM_REG_XX_DESCR_TABLE_SIZE }, + { XCM_REG_XX_DESCR_TABLE, XCM_REG_XX_DESCR_TABLE_SIZE }, + + { 0xffffffff, 0 } + }; + static const struct { + char *name; + u32 offset; + u32 e1_mask; + u32 e1h_mask; + } prty_tbl[] = { + { "CCM_PRTY_STS", CCM_REG_CCM_PRTY_STS, 0x3ffc0, 0 }, + { "CFC_PRTY_STS", CFC_REG_CFC_PRTY_STS, 0x2, 0x2 }, + { "DMAE_PRTY_STS", DMAE_REG_DMAE_PRTY_STS, 0, 0 }, + { "TCM_PRTY_STS", TCM_REG_TCM_PRTY_STS, 0x3ffc0, 0 }, + { "UCM_PRTY_STS", UCM_REG_UCM_PRTY_STS, 0x3ffc0, 0 }, + { "XCM_PRTY_STS", XCM_REG_XCM_PRTY_STS, 0x3ffc1, 0 }, + + { NULL, 0xffffffff, 0, 0 } + }; + + if (!netif_running(bp->dev)) + return rc; + + /* Go through all the memories */ + for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) + for (j = 0; j < mem_tbl[i].size; j++) + REG_RD(bp, mem_tbl[i].offset + j*4); + + /* Check the parity status */ + for (i = 0; prty_tbl[i].offset != 0xffffffff; i++) { + val = REG_RD(bp, prty_tbl[i].offset); + if ((CHIP_IS_E1(bp) && (val & ~(prty_tbl[i].e1_mask))) || + (CHIP_IS_E1H(bp) && (val & ~(prty_tbl[i].e1h_mask)))) { + DP(NETIF_MSG_HW, + "%s is 0x%x\n", prty_tbl[i].name, val); + goto test_mem_exit; + } + } + + rc = 0; + +test_mem_exit: + return rc; +} + +static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up) +{ + int cnt = 1000; + + if (link_up) + while (bnx2x_link_test(bp) && cnt--) + msleep(10); +} + +static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up) +{ + unsigned int pkt_size, num_pkts, i; + struct sk_buff *skb; + unsigned char *packet; + struct bnx2x_fastpath *fp_rx = &bp->fp[0]; + struct bnx2x_fastpath *fp_tx = &bp->fp[0]; + u16 tx_start_idx, tx_idx; + u16 rx_start_idx, rx_idx; + u16 pkt_prod, bd_prod; + struct sw_tx_bd *tx_buf; + struct eth_tx_start_bd *tx_start_bd; + struct eth_tx_parse_bd *pbd = NULL; + dma_addr_t mapping; + union eth_rx_cqe *cqe; + u8 cqe_fp_flags; + struct sw_rx_bd *rx_buf; + u16 len; + int rc = -ENODEV; + + /* check the loopback mode */ + switch (loopback_mode) { + case BNX2X_PHY_LOOPBACK: + if (bp->link_params.loopback_mode != LOOPBACK_XGXS_10) + return -EINVAL; + break; + case BNX2X_MAC_LOOPBACK: + bp->link_params.loopback_mode = LOOPBACK_BMAC; + bnx2x_phy_init(&bp->link_params, &bp->link_vars); + break; + default: + return -EINVAL; + } + + /* prepare the loopback packet */ + pkt_size = (((bp->dev->mtu < ETH_MAX_PACKET_SIZE) ? + bp->dev->mtu : ETH_MAX_PACKET_SIZE) + ETH_HLEN); + skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size); + if (!skb) { + rc = -ENOMEM; + goto test_loopback_exit; + } + packet = skb_put(skb, pkt_size); + memcpy(packet, bp->dev->dev_addr, ETH_ALEN); + memset(packet + ETH_ALEN, 0, ETH_ALEN); + memset(packet + 2*ETH_ALEN, 0x77, (ETH_HLEN - 2*ETH_ALEN)); + for (i = ETH_HLEN; i < pkt_size; i++) + packet[i] = (unsigned char) (i & 0xff); + + /* send the loopback packet */ + num_pkts = 0; + tx_start_idx = le16_to_cpu(*fp_tx->tx_cons_sb); + rx_start_idx = le16_to_cpu(*fp_rx->rx_cons_sb); + + pkt_prod = fp_tx->tx_pkt_prod++; + tx_buf = &fp_tx->tx_buf_ring[TX_BD(pkt_prod)]; + tx_buf->first_bd = fp_tx->tx_bd_prod; + tx_buf->skb = skb; + tx_buf->flags = 0; + + bd_prod = TX_BD(fp_tx->tx_bd_prod); + tx_start_bd = &fp_tx->tx_desc_ring[bd_prod].start_bd; + mapping = dma_map_single(&bp->pdev->dev, skb->data, + skb_headlen(skb), DMA_TO_DEVICE); + tx_start_bd->addr_hi = cpu_to_le32(U64_HI(mapping)); + tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping)); + tx_start_bd->nbd = cpu_to_le16(2); /* start + pbd */ + tx_start_bd->nbytes = cpu_to_le16(skb_headlen(skb)); + tx_start_bd->vlan = cpu_to_le16(pkt_prod); + tx_start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD; + tx_start_bd->general_data = ((UNICAST_ADDRESS << + ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT) | 1); + + /* turn on parsing and get a BD */ + bd_prod = TX_BD(NEXT_TX_IDX(bd_prod)); + pbd = &fp_tx->tx_desc_ring[bd_prod].parse_bd; + + memset(pbd, 0, sizeof(struct eth_tx_parse_bd)); + + wmb(); + + fp_tx->tx_db.data.prod += 2; + barrier(); + DOORBELL(bp, fp_tx->index, fp_tx->tx_db.raw); + + mmiowb(); + + num_pkts++; + fp_tx->tx_bd_prod += 2; /* start + pbd */ + + udelay(100); + + tx_idx = le16_to_cpu(*fp_tx->tx_cons_sb); + if (tx_idx != tx_start_idx + num_pkts) + goto test_loopback_exit; + + rx_idx = le16_to_cpu(*fp_rx->rx_cons_sb); + if (rx_idx != rx_start_idx + num_pkts) + goto test_loopback_exit; + + cqe = &fp_rx->rx_comp_ring[RCQ_BD(fp_rx->rx_comp_cons)]; + cqe_fp_flags = cqe->fast_path_cqe.type_error_flags; + if (CQE_TYPE(cqe_fp_flags) || (cqe_fp_flags & ETH_RX_ERROR_FALGS)) + goto test_loopback_rx_exit; + + len = le16_to_cpu(cqe->fast_path_cqe.pkt_len); + if (len != pkt_size) + goto test_loopback_rx_exit; + + rx_buf = &fp_rx->rx_buf_ring[RX_BD(fp_rx->rx_bd_cons)]; + skb = rx_buf->skb; + skb_reserve(skb, cqe->fast_path_cqe.placement_offset); + for (i = ETH_HLEN; i < pkt_size; i++) + if (*(skb->data + i) != (unsigned char) (i & 0xff)) + goto test_loopback_rx_exit; + + rc = 0; + +test_loopback_rx_exit: + + fp_rx->rx_bd_cons = NEXT_RX_IDX(fp_rx->rx_bd_cons); + fp_rx->rx_bd_prod = NEXT_RX_IDX(fp_rx->rx_bd_prod); + fp_rx->rx_comp_cons = NEXT_RCQ_IDX(fp_rx->rx_comp_cons); + fp_rx->rx_comp_prod = NEXT_RCQ_IDX(fp_rx->rx_comp_prod); + + /* Update producers */ + bnx2x_update_rx_prod(bp, fp_rx, fp_rx->rx_bd_prod, fp_rx->rx_comp_prod, + fp_rx->rx_sge_prod); + +test_loopback_exit: + bp->link_params.loopback_mode = LOOPBACK_NONE; + + return rc; +} + +static int bnx2x_test_loopback(struct bnx2x *bp, u8 link_up) +{ + int rc = 0, res; + + if (BP_NOMCP(bp)) + return rc; + + if (!netif_running(bp->dev)) + return BNX2X_LOOPBACK_FAILED; + + bnx2x_netif_stop(bp, 1); + bnx2x_acquire_phy_lock(bp); + + res = bnx2x_run_loopback(bp, BNX2X_PHY_LOOPBACK, link_up); + if (res) { + DP(NETIF_MSG_PROBE, " PHY loopback failed (res %d)\n", res); + rc |= BNX2X_PHY_LOOPBACK_FAILED; + } + + res = bnx2x_run_loopback(bp, BNX2X_MAC_LOOPBACK, link_up); + if (res) { + DP(NETIF_MSG_PROBE, " MAC loopback failed (res %d)\n", res); + rc |= BNX2X_MAC_LOOPBACK_FAILED; + } + + bnx2x_release_phy_lock(bp); + bnx2x_netif_start(bp); + + return rc; +} + +#define CRC32_RESIDUAL 0xdebb20e3 + +static int bnx2x_test_nvram(struct bnx2x *bp) +{ + static const struct { + int offset; + int size; + } nvram_tbl[] = { + { 0, 0x14 }, /* bootstrap */ + { 0x14, 0xec }, /* dir */ + { 0x100, 0x350 }, /* manuf_info */ + { 0x450, 0xf0 }, /* feature_info */ + { 0x640, 0x64 }, /* upgrade_key_info */ + { 0x6a4, 0x64 }, + { 0x708, 0x70 }, /* manuf_key_info */ + { 0x778, 0x70 }, + { 0, 0 } + }; + __be32 buf[0x350 / 4]; + u8 *data = (u8 *)buf; + int i, rc; + u32 magic, crc; + + if (BP_NOMCP(bp)) + return 0; + + rc = bnx2x_nvram_read(bp, 0, data, 4); + if (rc) { + DP(NETIF_MSG_PROBE, "magic value read (rc %d)\n", rc); + goto test_nvram_exit; + } + + magic = be32_to_cpu(buf[0]); + if (magic != 0x669955aa) { + DP(NETIF_MSG_PROBE, "magic value (0x%08x)\n", magic); + rc = -ENODEV; + goto test_nvram_exit; + } + + for (i = 0; nvram_tbl[i].size; i++) { + + rc = bnx2x_nvram_read(bp, nvram_tbl[i].offset, data, + nvram_tbl[i].size); + if (rc) { + DP(NETIF_MSG_PROBE, + "nvram_tbl[%d] read data (rc %d)\n", i, rc); + goto test_nvram_exit; + } + + crc = ether_crc_le(nvram_tbl[i].size, data); + if (crc != CRC32_RESIDUAL) { + DP(NETIF_MSG_PROBE, + "nvram_tbl[%d] crc value (0x%08x)\n", i, crc); + rc = -ENODEV; + goto test_nvram_exit; + } + } + +test_nvram_exit: + return rc; +} + +static int bnx2x_test_intr(struct bnx2x *bp) +{ + struct mac_configuration_cmd *config = bnx2x_sp(bp, mac_config); + int i, rc; + + if (!netif_running(bp->dev)) + return -ENODEV; + + config->hdr.length = 0; + if (CHIP_IS_E1(bp)) + /* use last unicast entries */ + config->hdr.offset = (BP_PORT(bp) ? 63 : 31); + else + config->hdr.offset = BP_FUNC(bp); + config->hdr.client_id = bp->fp->cl_id; + config->hdr.reserved1 = 0; + + bp->set_mac_pending++; + smp_wmb(); + rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0, + U64_HI(bnx2x_sp_mapping(bp, mac_config)), + U64_LO(bnx2x_sp_mapping(bp, mac_config)), 0); + if (rc == 0) { + for (i = 0; i < 10; i++) { + if (!bp->set_mac_pending) + break; + smp_rmb(); + msleep_interruptible(10); + } + if (i == 10) + rc = -ENODEV; + } + + return rc; +} + +static void bnx2x_self_test(struct net_device *dev, + struct ethtool_test *etest, u64 *buf) +{ + struct bnx2x *bp = netdev_priv(dev); + + if (bp->recovery_state != BNX2X_RECOVERY_DONE) { + printk(KERN_ERR "Handling parity error recovery. Try again later\n"); + etest->flags |= ETH_TEST_FL_FAILED; + return; + } + + memset(buf, 0, sizeof(u64) * BNX2X_NUM_TESTS); + + if (!netif_running(dev)) + return; + + /* offline tests are not supported in MF mode */ + if (IS_E1HMF(bp)) + etest->flags &= ~ETH_TEST_FL_OFFLINE; + + if (etest->flags & ETH_TEST_FL_OFFLINE) { + int port = BP_PORT(bp); + u32 val; + u8 link_up; + + /* save current value of input enable for TX port IF */ + val = REG_RD(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4); + /* disable input for TX port IF */ + REG_WR(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4, 0); + + link_up = (bnx2x_link_test(bp) == 0); + bnx2x_nic_unload(bp, UNLOAD_NORMAL); + bnx2x_nic_load(bp, LOAD_DIAG); + /* wait until link state is restored */ + bnx2x_wait_for_link(bp, link_up); + + if (bnx2x_test_registers(bp) != 0) { + buf[0] = 1; + etest->flags |= ETH_TEST_FL_FAILED; + } + if (bnx2x_test_memory(bp) != 0) { + buf[1] = 1; + etest->flags |= ETH_TEST_FL_FAILED; + } + buf[2] = bnx2x_test_loopback(bp, link_up); + if (buf[2] != 0) + etest->flags |= ETH_TEST_FL_FAILED; + + bnx2x_nic_unload(bp, UNLOAD_NORMAL); + + /* restore input for TX port IF */ + REG_WR(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4, val); + + bnx2x_nic_load(bp, LOAD_NORMAL); + /* wait until link state is restored */ + bnx2x_wait_for_link(bp, link_up); + } + if (bnx2x_test_nvram(bp) != 0) { + buf[3] = 1; + etest->flags |= ETH_TEST_FL_FAILED; + } + if (bnx2x_test_intr(bp) != 0) { + buf[4] = 1; + etest->flags |= ETH_TEST_FL_FAILED; + } + if (bp->port.pmf) + if (bnx2x_link_test(bp) != 0) { + buf[5] = 1; + etest->flags |= ETH_TEST_FL_FAILED; + } + +#ifdef BNX2X_EXTRA_DEBUG + bnx2x_panic_dump(bp); +#endif +} + +static const struct { + long offset; + int size; + u8 string[ETH_GSTRING_LEN]; +} bnx2x_q_stats_arr[BNX2X_NUM_Q_STATS] = { +/* 1 */ { Q_STATS_OFFSET32(total_bytes_received_hi), 8, "[%d]: rx_bytes" }, + { Q_STATS_OFFSET32(error_bytes_received_hi), + 8, "[%d]: rx_error_bytes" }, + { Q_STATS_OFFSET32(total_unicast_packets_received_hi), + 8, "[%d]: rx_ucast_packets" }, + { Q_STATS_OFFSET32(total_multicast_packets_received_hi), + 8, "[%d]: rx_mcast_packets" }, + { Q_STATS_OFFSET32(total_broadcast_packets_received_hi), + 8, "[%d]: rx_bcast_packets" }, + { Q_STATS_OFFSET32(no_buff_discard_hi), 8, "[%d]: rx_discards" }, + { Q_STATS_OFFSET32(rx_err_discard_pkt), + 4, "[%d]: rx_phy_ip_err_discards"}, + { Q_STATS_OFFSET32(rx_skb_alloc_failed), + 4, "[%d]: rx_skb_alloc_discard" }, + { Q_STATS_OFFSET32(hw_csum_err), 4, "[%d]: rx_csum_offload_errors" }, + +/* 10 */{ Q_STATS_OFFSET32(total_bytes_transmitted_hi), 8, "[%d]: tx_bytes" }, + { Q_STATS_OFFSET32(total_unicast_packets_transmitted_hi), + 8, "[%d]: tx_ucast_packets" }, + { Q_STATS_OFFSET32(total_multicast_packets_transmitted_hi), + 8, "[%d]: tx_mcast_packets" }, + { Q_STATS_OFFSET32(total_broadcast_packets_transmitted_hi), + 8, "[%d]: tx_bcast_packets" } +}; + +static const struct { + long offset; + int size; + u32 flags; +#define STATS_FLAGS_PORT 1 +#define STATS_FLAGS_FUNC 2 +#define STATS_FLAGS_BOTH (STATS_FLAGS_FUNC | STATS_FLAGS_PORT) + u8 string[ETH_GSTRING_LEN]; +} bnx2x_stats_arr[BNX2X_NUM_STATS] = { +/* 1 */ { STATS_OFFSET32(total_bytes_received_hi), + 8, STATS_FLAGS_BOTH, "rx_bytes" }, + { STATS_OFFSET32(error_bytes_received_hi), + 8, STATS_FLAGS_BOTH, "rx_error_bytes" }, + { STATS_OFFSET32(total_unicast_packets_received_hi), + 8, STATS_FLAGS_BOTH, "rx_ucast_packets" }, + { STATS_OFFSET32(total_multicast_packets_received_hi), + 8, STATS_FLAGS_BOTH, "rx_mcast_packets" }, + { STATS_OFFSET32(total_broadcast_packets_received_hi), + 8, STATS_FLAGS_BOTH, "rx_bcast_packets" }, + { STATS_OFFSET32(rx_stat_dot3statsfcserrors_hi), + 8, STATS_FLAGS_PORT, "rx_crc_errors" }, + { STATS_OFFSET32(rx_stat_dot3statsalignmenterrors_hi), + 8, STATS_FLAGS_PORT, "rx_align_errors" }, + { STATS_OFFSET32(rx_stat_etherstatsundersizepkts_hi), + 8, STATS_FLAGS_PORT, "rx_undersize_packets" }, + { STATS_OFFSET32(etherstatsoverrsizepkts_hi), + 8, STATS_FLAGS_PORT, "rx_oversize_packets" }, +/* 10 */{ STATS_OFFSET32(rx_stat_etherstatsfragments_hi), + 8, STATS_FLAGS_PORT, "rx_fragments" }, + { STATS_OFFSET32(rx_stat_etherstatsjabbers_hi), + 8, STATS_FLAGS_PORT, "rx_jabbers" }, + { STATS_OFFSET32(no_buff_discard_hi), + 8, STATS_FLAGS_BOTH, "rx_discards" }, + { STATS_OFFSET32(mac_filter_discard), + 4, STATS_FLAGS_PORT, "rx_filtered_packets" }, + { STATS_OFFSET32(xxoverflow_discard), + 4, STATS_FLAGS_PORT, "rx_fw_discards" }, + { STATS_OFFSET32(brb_drop_hi), + 8, STATS_FLAGS_PORT, "rx_brb_discard" }, + { STATS_OFFSET32(brb_truncate_hi), + 8, STATS_FLAGS_PORT, "rx_brb_truncate" }, + { STATS_OFFSET32(pause_frames_received_hi), + 8, STATS_FLAGS_PORT, "rx_pause_frames" }, + { STATS_OFFSET32(rx_stat_maccontrolframesreceived_hi), + 8, STATS_FLAGS_PORT, "rx_mac_ctrl_frames" }, + { STATS_OFFSET32(nig_timer_max), + 4, STATS_FLAGS_PORT, "rx_constant_pause_events" }, +/* 20 */{ STATS_OFFSET32(rx_err_discard_pkt), + 4, STATS_FLAGS_BOTH, "rx_phy_ip_err_discards"}, + { STATS_OFFSET32(rx_skb_alloc_failed), + 4, STATS_FLAGS_BOTH, "rx_skb_alloc_discard" }, + { STATS_OFFSET32(hw_csum_err), + 4, STATS_FLAGS_BOTH, "rx_csum_offload_errors" }, + + { STATS_OFFSET32(total_bytes_transmitted_hi), + 8, STATS_FLAGS_BOTH, "tx_bytes" }, + { STATS_OFFSET32(tx_stat_ifhcoutbadoctets_hi), + 8, STATS_FLAGS_PORT, "tx_error_bytes" }, + { STATS_OFFSET32(total_unicast_packets_transmitted_hi), + 8, STATS_FLAGS_BOTH, "tx_ucast_packets" }, + { STATS_OFFSET32(total_multicast_packets_transmitted_hi), + 8, STATS_FLAGS_BOTH, "tx_mcast_packets" }, + { STATS_OFFSET32(total_broadcast_packets_transmitted_hi), + 8, STATS_FLAGS_BOTH, "tx_bcast_packets" }, + { STATS_OFFSET32(tx_stat_dot3statsinternalmactransmiterrors_hi), + 8, STATS_FLAGS_PORT, "tx_mac_errors" }, + { STATS_OFFSET32(rx_stat_dot3statscarriersenseerrors_hi), + 8, STATS_FLAGS_PORT, "tx_carrier_errors" }, +/* 30 */{ STATS_OFFSET32(tx_stat_dot3statssinglecollisionframes_hi), + 8, STATS_FLAGS_PORT, "tx_single_collisions" }, + { STATS_OFFSET32(tx_stat_dot3statsmultiplecollisionframes_hi), + 8, STATS_FLAGS_PORT, "tx_multi_collisions" }, + { STATS_OFFSET32(tx_stat_dot3statsdeferredtransmissions_hi), + 8, STATS_FLAGS_PORT, "tx_deferred" }, + { STATS_OFFSET32(tx_stat_dot3statsexcessivecollisions_hi), + 8, STATS_FLAGS_PORT, "tx_excess_collisions" }, + { STATS_OFFSET32(tx_stat_dot3statslatecollisions_hi), + 8, STATS_FLAGS_PORT, "tx_late_collisions" }, + { STATS_OFFSET32(tx_stat_etherstatscollisions_hi), + 8, STATS_FLAGS_PORT, "tx_total_collisions" }, + { STATS_OFFSET32(tx_stat_etherstatspkts64octets_hi), + 8, STATS_FLAGS_PORT, "tx_64_byte_packets" }, + { STATS_OFFSET32(tx_stat_etherstatspkts65octetsto127octets_hi), + 8, STATS_FLAGS_PORT, "tx_65_to_127_byte_packets" }, + { STATS_OFFSET32(tx_stat_etherstatspkts128octetsto255octets_hi), + 8, STATS_FLAGS_PORT, "tx_128_to_255_byte_packets" }, + { STATS_OFFSET32(tx_stat_etherstatspkts256octetsto511octets_hi), + 8, STATS_FLAGS_PORT, "tx_256_to_511_byte_packets" }, +/* 40 */{ STATS_OFFSET32(tx_stat_etherstatspkts512octetsto1023octets_hi), + 8, STATS_FLAGS_PORT, "tx_512_to_1023_byte_packets" }, + { STATS_OFFSET32(etherstatspkts1024octetsto1522octets_hi), + 8, STATS_FLAGS_PORT, "tx_1024_to_1522_byte_packets" }, + { STATS_OFFSET32(etherstatspktsover1522octets_hi), + 8, STATS_FLAGS_PORT, "tx_1523_to_9022_byte_packets" }, + { STATS_OFFSET32(pause_frames_sent_hi), + 8, STATS_FLAGS_PORT, "tx_pause_frames" } +}; + +#define IS_PORT_STAT(i) \ + ((bnx2x_stats_arr[i].flags & STATS_FLAGS_BOTH) == STATS_FLAGS_PORT) +#define IS_FUNC_STAT(i) (bnx2x_stats_arr[i].flags & STATS_FLAGS_FUNC) +#define IS_E1HMF_MODE_STAT(bp) \ + (IS_E1HMF(bp) && !(bp->msg_enable & BNX2X_MSG_STATS)) + +static int bnx2x_get_sset_count(struct net_device *dev, int stringset) +{ + struct bnx2x *bp = netdev_priv(dev); + int i, num_stats; + + switch (stringset) { + case ETH_SS_STATS: + if (is_multi(bp)) { + num_stats = BNX2X_NUM_Q_STATS * bp->num_queues; + if (!IS_E1HMF_MODE_STAT(bp)) + num_stats += BNX2X_NUM_STATS; + } else { + if (IS_E1HMF_MODE_STAT(bp)) { + num_stats = 0; + for (i = 0; i < BNX2X_NUM_STATS; i++) + if (IS_FUNC_STAT(i)) + num_stats++; + } else + num_stats = BNX2X_NUM_STATS; + } + return num_stats; + + case ETH_SS_TEST: + return BNX2X_NUM_TESTS; + + default: + return -EINVAL; + } +} + +static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf) +{ + struct bnx2x *bp = netdev_priv(dev); + int i, j, k; + + switch (stringset) { + case ETH_SS_STATS: + if (is_multi(bp)) { + k = 0; + for_each_queue(bp, i) { + for (j = 0; j < BNX2X_NUM_Q_STATS; j++) + sprintf(buf + (k + j)*ETH_GSTRING_LEN, + bnx2x_q_stats_arr[j].string, i); + k += BNX2X_NUM_Q_STATS; + } + if (IS_E1HMF_MODE_STAT(bp)) + break; + for (j = 0; j < BNX2X_NUM_STATS; j++) + strcpy(buf + (k + j)*ETH_GSTRING_LEN, + bnx2x_stats_arr[j].string); + } else { + for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) { + if (IS_E1HMF_MODE_STAT(bp) && IS_PORT_STAT(i)) + continue; + strcpy(buf + j*ETH_GSTRING_LEN, + bnx2x_stats_arr[i].string); + j++; + } + } + break; + + case ETH_SS_TEST: + memcpy(buf, bnx2x_tests_str_arr, sizeof(bnx2x_tests_str_arr)); + break; + } +} + +static void bnx2x_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *buf) +{ + struct bnx2x *bp = netdev_priv(dev); + u32 *hw_stats, *offset; + int i, j, k; + + if (is_multi(bp)) { + k = 0; + for_each_queue(bp, i) { + hw_stats = (u32 *)&bp->fp[i].eth_q_stats; + for (j = 0; j < BNX2X_NUM_Q_STATS; j++) { + if (bnx2x_q_stats_arr[j].size == 0) { + /* skip this counter */ + buf[k + j] = 0; + continue; + } + offset = (hw_stats + + bnx2x_q_stats_arr[j].offset); + if (bnx2x_q_stats_arr[j].size == 4) { + /* 4-byte counter */ + buf[k + j] = (u64) *offset; + continue; + } + /* 8-byte counter */ + buf[k + j] = HILO_U64(*offset, *(offset + 1)); + } + k += BNX2X_NUM_Q_STATS; + } + if (IS_E1HMF_MODE_STAT(bp)) + return; + hw_stats = (u32 *)&bp->eth_stats; + for (j = 0; j < BNX2X_NUM_STATS; j++) { + if (bnx2x_stats_arr[j].size == 0) { + /* skip this counter */ + buf[k + j] = 0; + continue; + } + offset = (hw_stats + bnx2x_stats_arr[j].offset); + if (bnx2x_stats_arr[j].size == 4) { + /* 4-byte counter */ + buf[k + j] = (u64) *offset; + continue; + } + /* 8-byte counter */ + buf[k + j] = HILO_U64(*offset, *(offset + 1)); + } + } else { + hw_stats = (u32 *)&bp->eth_stats; + for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) { + if (IS_E1HMF_MODE_STAT(bp) && IS_PORT_STAT(i)) + continue; + if (bnx2x_stats_arr[i].size == 0) { + /* skip this counter */ + buf[j] = 0; + j++; + continue; + } + offset = (hw_stats + bnx2x_stats_arr[i].offset); + if (bnx2x_stats_arr[i].size == 4) { + /* 4-byte counter */ + buf[j] = (u64) *offset; + j++; + continue; + } + /* 8-byte counter */ + buf[j] = HILO_U64(*offset, *(offset + 1)); + j++; + } + } +} + +static int bnx2x_phys_id(struct net_device *dev, u32 data) +{ + struct bnx2x *bp = netdev_priv(dev); + int i; + + if (!netif_running(dev)) + return 0; + + if (!bp->port.pmf) + return 0; + + if (data == 0) + data = 2; + + for (i = 0; i < (data * 2); i++) { + if ((i % 2) == 0) + bnx2x_set_led(&bp->link_params, LED_MODE_OPER, + SPEED_1000); + else + bnx2x_set_led(&bp->link_params, LED_MODE_OFF, 0); + + msleep_interruptible(500); + if (signal_pending(current)) + break; + } + + if (bp->link_vars.link_up) + bnx2x_set_led(&bp->link_params, LED_MODE_OPER, + bp->link_vars.line_speed); + + return 0; +} + +static const struct ethtool_ops bnx2x_ethtool_ops = { + .get_settings = bnx2x_get_settings, + .set_settings = bnx2x_set_settings, + .get_drvinfo = bnx2x_get_drvinfo, + .get_regs_len = bnx2x_get_regs_len, + .get_regs = bnx2x_get_regs, + .get_wol = bnx2x_get_wol, + .set_wol = bnx2x_set_wol, + .get_msglevel = bnx2x_get_msglevel, + .set_msglevel = bnx2x_set_msglevel, + .nway_reset = bnx2x_nway_reset, + .get_link = bnx2x_get_link, + .get_eeprom_len = bnx2x_get_eeprom_len, + .get_eeprom = bnx2x_get_eeprom, + .set_eeprom = bnx2x_set_eeprom, + .get_coalesce = bnx2x_get_coalesce, + .set_coalesce = bnx2x_set_coalesce, + .get_ringparam = bnx2x_get_ringparam, + .set_ringparam = bnx2x_set_ringparam, + .get_pauseparam = bnx2x_get_pauseparam, + .set_pauseparam = bnx2x_set_pauseparam, + .get_rx_csum = bnx2x_get_rx_csum, + .set_rx_csum = bnx2x_set_rx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_hw_csum, + .set_flags = bnx2x_set_flags, + .get_flags = ethtool_op_get_flags, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = bnx2x_set_tso, + .self_test = bnx2x_self_test, + .get_sset_count = bnx2x_get_sset_count, + .get_strings = bnx2x_get_strings, + .phys_id = bnx2x_phys_id, + .get_ethtool_stats = bnx2x_get_ethtool_stats, +}; + +void bnx2x_set_ethtool_ops(struct net_device *netdev) +{ + SET_ETHTOOL_OPS(netdev, &bnx2x_ethtool_ops); +} diff --git a/drivers/net/bnx2x_fw_defs.h b/drivers/net/bnx2x/bnx2x_fw_defs.h index 08d71bf438d..08d71bf438d 100644 --- a/drivers/net/bnx2x_fw_defs.h +++ b/drivers/net/bnx2x/bnx2x_fw_defs.h diff --git a/drivers/net/bnx2x_fw_file_hdr.h b/drivers/net/bnx2x/bnx2x_fw_file_hdr.h index 3f5ee5d7cc2..3f5ee5d7cc2 100644 --- a/drivers/net/bnx2x_fw_file_hdr.h +++ b/drivers/net/bnx2x/bnx2x_fw_file_hdr.h diff --git a/drivers/net/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h index fd1f29e0317..fd1f29e0317 100644 --- a/drivers/net/bnx2x_hsi.h +++ b/drivers/net/bnx2x/bnx2x_hsi.h diff --git a/drivers/net/bnx2x_init.h b/drivers/net/bnx2x/bnx2x_init.h index 65b26cbfe3e..65b26cbfe3e 100644 --- a/drivers/net/bnx2x_init.h +++ b/drivers/net/bnx2x/bnx2x_init.h diff --git a/drivers/net/bnx2x_init_ops.h b/drivers/net/bnx2x/bnx2x_init_ops.h index 2b1363a6fe7..2b1363a6fe7 100644 --- a/drivers/net/bnx2x_init_ops.h +++ b/drivers/net/bnx2x/bnx2x_init_ops.h diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c index 0383e306631..0383e306631 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x/bnx2x_link.c diff --git a/drivers/net/bnx2x_link.h b/drivers/net/bnx2x/bnx2x_link.h index 40c2981de8e..40c2981de8e 100644 --- a/drivers/net/bnx2x_link.h +++ b/drivers/net/bnx2x/bnx2x_link.h diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 51b788339c9..b4ec2b02a46 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -51,15 +51,12 @@ #include <linux/io.h> #include <linux/stringify.h> - +#define BNX2X_MAIN #include "bnx2x.h" #include "bnx2x_init.h" #include "bnx2x_init_ops.h" -#include "bnx2x_dump.h" +#include "bnx2x_cmn.h" -#define DRV_MODULE_VERSION "1.52.53-1" -#define DRV_MODULE_RELDATE "2010/18/04" -#define BNX2X_BC_VER 0x040200 #include <linux/firmware.h> #include "bnx2x_fw_file_hdr.h" @@ -121,8 +118,6 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, " Default debug msglevel"); -static int load_count[3]; /* 0-common, 1-port0, 2-port1 */ - static struct workqueue_struct *bnx2x_wq; enum bnx2x_board_type { @@ -177,7 +172,7 @@ static u32 bnx2x_reg_rd_ind(struct bnx2x *bp, u32 addr) return val; } -static const u32 dmae_reg_go_c[] = { +const u32 dmae_reg_go_c[] = { DMAE_REG_GO_C0, DMAE_REG_GO_C1, DMAE_REG_GO_C2, DMAE_REG_GO_C3, DMAE_REG_GO_C4, DMAE_REG_GO_C5, DMAE_REG_GO_C6, DMAE_REG_GO_C7, DMAE_REG_GO_C8, DMAE_REG_GO_C9, DMAE_REG_GO_C10, DMAE_REG_GO_C11, @@ -185,8 +180,7 @@ static const u32 dmae_reg_go_c[] = { }; /* copy command into DMAE command memory and set DMAE command go */ -static void bnx2x_post_dmae(struct bnx2x *bp, struct dmae_command *dmae, - int idx) +void bnx2x_post_dmae(struct bnx2x *bp, struct dmae_command *dmae, int idx) { u32 cmd_offset; int i; @@ -541,7 +535,7 @@ static void bnx2x_fw_dump(struct bnx2x *bp) pr_err("end of fw dump\n"); } -static void bnx2x_panic_dump(struct bnx2x *bp) +void bnx2x_panic_dump(struct bnx2x *bp) { int i; u16 j, start, end; @@ -654,7 +648,7 @@ static void bnx2x_panic_dump(struct bnx2x *bp) BNX2X_ERR("end crash dump -----------------\n"); } -static void bnx2x_int_enable(struct bnx2x *bp) +void bnx2x_int_enable(struct bnx2x *bp) { int port = BP_PORT(bp); u32 addr = port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0; @@ -736,7 +730,7 @@ static void bnx2x_int_disable(struct bnx2x *bp) BNX2X_ERR("BUG! proper val not read from IGU!\n"); } -static void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw) +void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw) { int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0; int i, offset; @@ -806,235 +800,12 @@ static bool bnx2x_trylock_hw_lock(struct bnx2x *bp, u32 resource) return false; } -static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 sb_id, - u8 storm, u16 index, u8 op, u8 update) -{ - u32 hc_addr = (HC_REG_COMMAND_REG + BP_PORT(bp)*32 + - COMMAND_REG_INT_ACK); - struct igu_ack_register igu_ack; - - igu_ack.status_block_index = index; - igu_ack.sb_id_and_flags = - ((sb_id << IGU_ACK_REGISTER_STATUS_BLOCK_ID_SHIFT) | - (storm << IGU_ACK_REGISTER_STORM_ID_SHIFT) | - (update << IGU_ACK_REGISTER_UPDATE_INDEX_SHIFT) | - (op << IGU_ACK_REGISTER_INTERRUPT_MODE_SHIFT)); - - DP(BNX2X_MSG_OFF, "write 0x%08x to HC addr 0x%x\n", - (*(u32 *)&igu_ack), hc_addr); - REG_WR(bp, hc_addr, (*(u32 *)&igu_ack)); - - /* Make sure that ACK is written */ - mmiowb(); - barrier(); -} - -static inline void bnx2x_update_fpsb_idx(struct bnx2x_fastpath *fp) -{ - struct host_status_block *fpsb = fp->status_blk; - - barrier(); /* status block is written to by the chip */ - fp->fp_c_idx = fpsb->c_status_block.status_block_index; - fp->fp_u_idx = fpsb->u_status_block.status_block_index; -} - -static u16 bnx2x_ack_int(struct bnx2x *bp) -{ - u32 hc_addr = (HC_REG_COMMAND_REG + BP_PORT(bp)*32 + - COMMAND_REG_SIMD_MASK); - u32 result = REG_RD(bp, hc_addr); - - DP(BNX2X_MSG_OFF, "read 0x%08x from HC addr 0x%x\n", - result, hc_addr); - - return result; -} - - -/* - * fast path service functions - */ - -static inline int bnx2x_has_tx_work_unload(struct bnx2x_fastpath *fp) -{ - /* Tell compiler that consumer and producer can change */ - barrier(); - return (fp->tx_pkt_prod != fp->tx_pkt_cons); -} - -/* free skb in the packet ring at pos idx - * return idx of last bd freed - */ -static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp, - u16 idx) -{ - struct sw_tx_bd *tx_buf = &fp->tx_buf_ring[idx]; - struct eth_tx_start_bd *tx_start_bd; - struct eth_tx_bd *tx_data_bd; - struct sk_buff *skb = tx_buf->skb; - u16 bd_idx = TX_BD(tx_buf->first_bd), new_cons; - int nbd; - - /* prefetch skb end pointer to speedup dev_kfree_skb() */ - prefetch(&skb->end); - - DP(BNX2X_MSG_OFF, "pkt_idx %d buff @(%p)->skb %p\n", - idx, tx_buf, skb); - - /* unmap first bd */ - DP(BNX2X_MSG_OFF, "free bd_idx %d\n", bd_idx); - tx_start_bd = &fp->tx_desc_ring[bd_idx].start_bd; - dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd), - BD_UNMAP_LEN(tx_start_bd), PCI_DMA_TODEVICE); - - nbd = le16_to_cpu(tx_start_bd->nbd) - 1; -#ifdef BNX2X_STOP_ON_ERROR - if ((nbd - 1) > (MAX_SKB_FRAGS + 2)) { - BNX2X_ERR("BAD nbd!\n"); - bnx2x_panic(); - } -#endif - new_cons = nbd + tx_buf->first_bd; - - /* Get the next bd */ - bd_idx = TX_BD(NEXT_TX_IDX(bd_idx)); - - /* Skip a parse bd... */ - --nbd; - bd_idx = TX_BD(NEXT_TX_IDX(bd_idx)); - - /* ...and the TSO split header bd since they have no mapping */ - if (tx_buf->flags & BNX2X_TSO_SPLIT_BD) { - --nbd; - bd_idx = TX_BD(NEXT_TX_IDX(bd_idx)); - } - - /* now free frags */ - while (nbd > 0) { - - DP(BNX2X_MSG_OFF, "free frag bd_idx %d\n", bd_idx); - tx_data_bd = &fp->tx_desc_ring[bd_idx].reg_bd; - dma_unmap_page(&bp->pdev->dev, BD_UNMAP_ADDR(tx_data_bd), - BD_UNMAP_LEN(tx_data_bd), DMA_TO_DEVICE); - if (--nbd) - bd_idx = TX_BD(NEXT_TX_IDX(bd_idx)); - } - - /* release skb */ - WARN_ON(!skb); - dev_kfree_skb(skb); - tx_buf->first_bd = 0; - tx_buf->skb = NULL; - - return new_cons; -} - -static inline u16 bnx2x_tx_avail(struct bnx2x_fastpath *fp) -{ - s16 used; - u16 prod; - u16 cons; - - prod = fp->tx_bd_prod; - cons = fp->tx_bd_cons; - - /* NUM_TX_RINGS = number of "next-page" entries - It will be used as a threshold */ - used = SUB_S16(prod, cons) + (s16)NUM_TX_RINGS; - -#ifdef BNX2X_STOP_ON_ERROR - WARN_ON(used < 0); - WARN_ON(used > fp->bp->tx_ring_size); - WARN_ON((fp->bp->tx_ring_size - used) > MAX_TX_AVAIL); -#endif - - return (s16)(fp->bp->tx_ring_size) - used; -} - -static inline int bnx2x_has_tx_work(struct bnx2x_fastpath *fp) -{ - u16 hw_cons; - - /* Tell compiler that status block fields can change */ - barrier(); - hw_cons = le16_to_cpu(*fp->tx_cons_sb); - return hw_cons != fp->tx_pkt_cons; -} - -static int bnx2x_tx_int(struct bnx2x_fastpath *fp) -{ - struct bnx2x *bp = fp->bp; - struct netdev_queue *txq; - u16 hw_cons, sw_cons, bd_cons = fp->tx_bd_cons; - -#ifdef BNX2X_STOP_ON_ERROR - if (unlikely(bp->panic)) - return -1; -#endif - - txq = netdev_get_tx_queue(bp->dev, fp->index); - hw_cons = le16_to_cpu(*fp->tx_cons_sb); - sw_cons = fp->tx_pkt_cons; - - while (sw_cons != hw_cons) { - u16 pkt_cons; - - pkt_cons = TX_BD(sw_cons); - - /* prefetch(bp->tx_buf_ring[pkt_cons].skb); */ - - DP(NETIF_MSG_TX_DONE, "hw_cons %u sw_cons %u pkt_cons %u\n", - hw_cons, sw_cons, pkt_cons); - -/* if (NEXT_TX_IDX(sw_cons) != hw_cons) { - rmb(); - prefetch(fp->tx_buf_ring[NEXT_TX_IDX(sw_cons)].skb); - } -*/ - bd_cons = bnx2x_free_tx_pkt(bp, fp, pkt_cons); - sw_cons++; - } - - fp->tx_pkt_cons = sw_cons; - fp->tx_bd_cons = bd_cons; - - /* Need to make the tx_bd_cons update visible to start_xmit() - * before checking for netif_tx_queue_stopped(). Without the - * memory barrier, there is a small possibility that - * start_xmit() will miss it and cause the queue to be stopped - * forever. - */ - smp_mb(); - - /* TBD need a thresh? */ - if (unlikely(netif_tx_queue_stopped(txq))) { - /* Taking tx_lock() is needed to prevent reenabling the queue - * while it's empty. This could have happen if rx_action() gets - * suspended in bnx2x_tx_int() after the condition before - * netif_tx_wake_queue(), while tx_action (bnx2x_start_xmit()): - * - * stops the queue->sees fresh tx_bd_cons->releases the queue-> - * sends some packets consuming the whole queue again-> - * stops the queue - */ - - __netif_tx_lock(txq, smp_processor_id()); - - if ((netif_tx_queue_stopped(txq)) && - (bp->state == BNX2X_STATE_OPEN) && - (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3)) - netif_tx_wake_queue(txq); - - __netif_tx_unlock(txq); - } - return 0; -} #ifdef BCM_CNIC static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid); #endif -static void bnx2x_sp_event(struct bnx2x_fastpath *fp, +void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe) { struct bnx2x *bp = fp->bp; @@ -1118,717 +889,7 @@ static void bnx2x_sp_event(struct bnx2x_fastpath *fp, mb(); /* force bnx2x_wait_ramrod() to see the change */ } -static inline void bnx2x_free_rx_sge(struct bnx2x *bp, - struct bnx2x_fastpath *fp, u16 index) -{ - struct sw_rx_page *sw_buf = &fp->rx_page_ring[index]; - struct page *page = sw_buf->page; - struct eth_rx_sge *sge = &fp->rx_sge_ring[index]; - - /* Skip "next page" elements */ - if (!page) - return; - - dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(sw_buf, mapping), - SGE_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE); - __free_pages(page, PAGES_PER_SGE_SHIFT); - - sw_buf->page = NULL; - sge->addr_hi = 0; - sge->addr_lo = 0; -} - -static inline void bnx2x_free_rx_sge_range(struct bnx2x *bp, - struct bnx2x_fastpath *fp, int last) -{ - int i; - - for (i = 0; i < last; i++) - bnx2x_free_rx_sge(bp, fp, i); -} - -static inline int bnx2x_alloc_rx_sge(struct bnx2x *bp, - struct bnx2x_fastpath *fp, u16 index) -{ - struct page *page = alloc_pages(GFP_ATOMIC, PAGES_PER_SGE_SHIFT); - struct sw_rx_page *sw_buf = &fp->rx_page_ring[index]; - struct eth_rx_sge *sge = &fp->rx_sge_ring[index]; - dma_addr_t mapping; - - if (unlikely(page == NULL)) - return -ENOMEM; - - mapping = dma_map_page(&bp->pdev->dev, page, 0, - SGE_PAGE_SIZE*PAGES_PER_SGE, DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) { - __free_pages(page, PAGES_PER_SGE_SHIFT); - return -ENOMEM; - } - - sw_buf->page = page; - dma_unmap_addr_set(sw_buf, mapping, mapping); - - sge->addr_hi = cpu_to_le32(U64_HI(mapping)); - sge->addr_lo = cpu_to_le32(U64_LO(mapping)); - - return 0; -} - -static inline int bnx2x_alloc_rx_skb(struct bnx2x *bp, - struct bnx2x_fastpath *fp, u16 index) -{ - struct sk_buff *skb; - struct sw_rx_bd *rx_buf = &fp->rx_buf_ring[index]; - struct eth_rx_bd *rx_bd = &fp->rx_desc_ring[index]; - dma_addr_t mapping; - - skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size); - if (unlikely(skb == NULL)) - return -ENOMEM; - - mapping = dma_map_single(&bp->pdev->dev, skb->data, bp->rx_buf_size, - DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) { - dev_kfree_skb(skb); - return -ENOMEM; - } - - rx_buf->skb = skb; - dma_unmap_addr_set(rx_buf, mapping, mapping); - - rx_bd->addr_hi = cpu_to_le32(U64_HI(mapping)); - rx_bd->addr_lo = cpu_to_le32(U64_LO(mapping)); - - return 0; -} - -/* note that we are not allocating a new skb, - * we are just moving one from cons to prod - * we are not creating a new mapping, - * so there is no need to check for dma_mapping_error(). - */ -static void bnx2x_reuse_rx_skb(struct bnx2x_fastpath *fp, - struct sk_buff *skb, u16 cons, u16 prod) -{ - struct bnx2x *bp = fp->bp; - struct sw_rx_bd *cons_rx_buf = &fp->rx_buf_ring[cons]; - struct sw_rx_bd *prod_rx_buf = &fp->rx_buf_ring[prod]; - struct eth_rx_bd *cons_bd = &fp->rx_desc_ring[cons]; - struct eth_rx_bd *prod_bd = &fp->rx_desc_ring[prod]; - - dma_sync_single_for_device(&bp->pdev->dev, - dma_unmap_addr(cons_rx_buf, mapping), - RX_COPY_THRESH, DMA_FROM_DEVICE); - - prod_rx_buf->skb = cons_rx_buf->skb; - dma_unmap_addr_set(prod_rx_buf, mapping, - dma_unmap_addr(cons_rx_buf, mapping)); - *prod_bd = *cons_bd; -} - -static inline void bnx2x_update_last_max_sge(struct bnx2x_fastpath *fp, - u16 idx) -{ - u16 last_max = fp->last_max_sge; - - if (SUB_S16(idx, last_max) > 0) - fp->last_max_sge = idx; -} - -static void bnx2x_clear_sge_mask_next_elems(struct bnx2x_fastpath *fp) -{ - int i, j; - - for (i = 1; i <= NUM_RX_SGE_PAGES; i++) { - int idx = RX_SGE_CNT * i - 1; - - for (j = 0; j < 2; j++) { - SGE_MASK_CLEAR_BIT(fp, idx); - idx--; - } - } -} - -static void bnx2x_update_sge_prod(struct bnx2x_fastpath *fp, - struct eth_fast_path_rx_cqe *fp_cqe) -{ - struct bnx2x *bp = fp->bp; - u16 sge_len = SGE_PAGE_ALIGN(le16_to_cpu(fp_cqe->pkt_len) - - le16_to_cpu(fp_cqe->len_on_bd)) >> - SGE_PAGE_SHIFT; - u16 last_max, last_elem, first_elem; - u16 delta = 0; - u16 i; - - if (!sge_len) - return; - - /* First mark all used pages */ - for (i = 0; i < sge_len; i++) - SGE_MASK_CLEAR_BIT(fp, RX_SGE(le16_to_cpu(fp_cqe->sgl[i]))); - - DP(NETIF_MSG_RX_STATUS, "fp_cqe->sgl[%d] = %d\n", - sge_len - 1, le16_to_cpu(fp_cqe->sgl[sge_len - 1])); - - /* Here we assume that the last SGE index is the biggest */ - prefetch((void *)(fp->sge_mask)); - bnx2x_update_last_max_sge(fp, le16_to_cpu(fp_cqe->sgl[sge_len - 1])); - - last_max = RX_SGE(fp->last_max_sge); - last_elem = last_max >> RX_SGE_MASK_ELEM_SHIFT; - first_elem = RX_SGE(fp->rx_sge_prod) >> RX_SGE_MASK_ELEM_SHIFT; - - /* If ring is not full */ - if (last_elem + 1 != first_elem) - last_elem++; - - /* Now update the prod */ - for (i = first_elem; i != last_elem; i = NEXT_SGE_MASK_ELEM(i)) { - if (likely(fp->sge_mask[i])) - break; - - fp->sge_mask[i] = RX_SGE_MASK_ELEM_ONE_MASK; - delta += RX_SGE_MASK_ELEM_SZ; - } - - if (delta > 0) { - fp->rx_sge_prod += delta; - /* clear page-end entries */ - bnx2x_clear_sge_mask_next_elems(fp); - } - - DP(NETIF_MSG_RX_STATUS, - "fp->last_max_sge = %d fp->rx_sge_prod = %d\n", - fp->last_max_sge, fp->rx_sge_prod); -} - -static inline void bnx2x_init_sge_ring_bit_mask(struct bnx2x_fastpath *fp) -{ - /* Set the mask to all 1-s: it's faster to compare to 0 than to 0xf-s */ - memset(fp->sge_mask, 0xff, - (NUM_RX_SGE >> RX_SGE_MASK_ELEM_SHIFT)*sizeof(u64)); - - /* Clear the two last indices in the page to 1: - these are the indices that correspond to the "next" element, - hence will never be indicated and should be removed from - the calculations. */ - bnx2x_clear_sge_mask_next_elems(fp); -} - -static void bnx2x_tpa_start(struct bnx2x_fastpath *fp, u16 queue, - struct sk_buff *skb, u16 cons, u16 prod) -{ - struct bnx2x *bp = fp->bp; - struct sw_rx_bd *cons_rx_buf = &fp->rx_buf_ring[cons]; - struct sw_rx_bd *prod_rx_buf = &fp->rx_buf_ring[prod]; - struct eth_rx_bd *prod_bd = &fp->rx_desc_ring[prod]; - dma_addr_t mapping; - - /* move empty skb from pool to prod and map it */ - prod_rx_buf->skb = fp->tpa_pool[queue].skb; - mapping = dma_map_single(&bp->pdev->dev, fp->tpa_pool[queue].skb->data, - bp->rx_buf_size, DMA_FROM_DEVICE); - dma_unmap_addr_set(prod_rx_buf, mapping, mapping); - - /* move partial skb from cons to pool (don't unmap yet) */ - fp->tpa_pool[queue] = *cons_rx_buf; - - /* mark bin state as start - print error if current state != stop */ - if (fp->tpa_state[queue] != BNX2X_TPA_STOP) - BNX2X_ERR("start of bin not in stop [%d]\n", queue); - - fp->tpa_state[queue] = BNX2X_TPA_START; - - /* point prod_bd to new skb */ - prod_bd->addr_hi = cpu_to_le32(U64_HI(mapping)); - prod_bd->addr_lo = cpu_to_le32(U64_LO(mapping)); - -#ifdef BNX2X_STOP_ON_ERROR - fp->tpa_queue_used |= (1 << queue); -#ifdef _ASM_GENERIC_INT_L64_H - DP(NETIF_MSG_RX_STATUS, "fp->tpa_queue_used = 0x%lx\n", -#else - DP(NETIF_MSG_RX_STATUS, "fp->tpa_queue_used = 0x%llx\n", -#endif - fp->tpa_queue_used); -#endif -} - -static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp, - struct sk_buff *skb, - struct eth_fast_path_rx_cqe *fp_cqe, - u16 cqe_idx) -{ - struct sw_rx_page *rx_pg, old_rx_pg; - u16 len_on_bd = le16_to_cpu(fp_cqe->len_on_bd); - u32 i, frag_len, frag_size, pages; - int err; - int j; - - frag_size = le16_to_cpu(fp_cqe->pkt_len) - len_on_bd; - pages = SGE_PAGE_ALIGN(frag_size) >> SGE_PAGE_SHIFT; - - /* This is needed in order to enable forwarding support */ - if (frag_size) - skb_shinfo(skb)->gso_size = min((u32)SGE_PAGE_SIZE, - max(frag_size, (u32)len_on_bd)); - -#ifdef BNX2X_STOP_ON_ERROR - if (pages > min_t(u32, 8, MAX_SKB_FRAGS)*SGE_PAGE_SIZE*PAGES_PER_SGE) { - BNX2X_ERR("SGL length is too long: %d. CQE index is %d\n", - pages, cqe_idx); - BNX2X_ERR("fp_cqe->pkt_len = %d fp_cqe->len_on_bd = %d\n", - fp_cqe->pkt_len, len_on_bd); - bnx2x_panic(); - return -EINVAL; - } -#endif - - /* Run through the SGL and compose the fragmented skb */ - for (i = 0, j = 0; i < pages; i += PAGES_PER_SGE, j++) { - u16 sge_idx = RX_SGE(le16_to_cpu(fp_cqe->sgl[j])); - - /* FW gives the indices of the SGE as if the ring is an array - (meaning that "next" element will consume 2 indices) */ - frag_len = min(frag_size, (u32)(SGE_PAGE_SIZE*PAGES_PER_SGE)); - rx_pg = &fp->rx_page_ring[sge_idx]; - old_rx_pg = *rx_pg; - - /* If we fail to allocate a substitute page, we simply stop - where we are and drop the whole packet */ - err = bnx2x_alloc_rx_sge(bp, fp, sge_idx); - if (unlikely(err)) { - fp->eth_q_stats.rx_skb_alloc_failed++; - return err; - } - - /* Unmap the page as we r going to pass it to the stack */ - dma_unmap_page(&bp->pdev->dev, - dma_unmap_addr(&old_rx_pg, mapping), - SGE_PAGE_SIZE*PAGES_PER_SGE, DMA_FROM_DEVICE); - - /* Add one frag and update the appropriate fields in the skb */ - skb_fill_page_desc(skb, j, old_rx_pg.page, 0, frag_len); - - skb->data_len += frag_len; - skb->truesize += frag_len; - skb->len += frag_len; - - frag_size -= frag_len; - } - - return 0; -} - -static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp, - u16 queue, int pad, int len, union eth_rx_cqe *cqe, - u16 cqe_idx) -{ - struct sw_rx_bd *rx_buf = &fp->tpa_pool[queue]; - struct sk_buff *skb = rx_buf->skb; - /* alloc new skb */ - struct sk_buff *new_skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size); - - /* Unmap skb in the pool anyway, as we are going to change - pool entry status to BNX2X_TPA_STOP even if new skb allocation - fails. */ - dma_unmap_single(&bp->pdev->dev, dma_unmap_addr(rx_buf, mapping), - bp->rx_buf_size, DMA_FROM_DEVICE); - - if (likely(new_skb)) { - /* fix ip xsum and give it to the stack */ - /* (no need to map the new skb) */ -#ifdef BCM_VLAN - int is_vlan_cqe = - (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) & - PARSING_FLAGS_VLAN); - int is_not_hwaccel_vlan_cqe = - (is_vlan_cqe && (!(bp->flags & HW_VLAN_RX_FLAG))); -#endif - - prefetch(skb); - prefetch(((char *)(skb)) + 128); - -#ifdef BNX2X_STOP_ON_ERROR - if (pad + len > bp->rx_buf_size) { - BNX2X_ERR("skb_put is about to fail... " - "pad %d len %d rx_buf_size %d\n", - pad, len, bp->rx_buf_size); - bnx2x_panic(); - return; - } -#endif - - skb_reserve(skb, pad); - skb_put(skb, len); - - skb->protocol = eth_type_trans(skb, bp->dev); - skb->ip_summed = CHECKSUM_UNNECESSARY; - - { - struct iphdr *iph; - - iph = (struct iphdr *)skb->data; -#ifdef BCM_VLAN - /* If there is no Rx VLAN offloading - - take VLAN tag into an account */ - if (unlikely(is_not_hwaccel_vlan_cqe)) - iph = (struct iphdr *)((u8 *)iph + VLAN_HLEN); -#endif - iph->check = 0; - iph->check = ip_fast_csum((u8 *)iph, iph->ihl); - } - - if (!bnx2x_fill_frag_skb(bp, fp, skb, - &cqe->fast_path_cqe, cqe_idx)) { -#ifdef BCM_VLAN - if ((bp->vlgrp != NULL) && is_vlan_cqe && - (!is_not_hwaccel_vlan_cqe)) - vlan_gro_receive(&fp->napi, bp->vlgrp, - le16_to_cpu(cqe->fast_path_cqe. - vlan_tag), skb); - else -#endif - napi_gro_receive(&fp->napi, skb); - } else { - DP(NETIF_MSG_RX_STATUS, "Failed to allocate new pages" - " - dropping packet!\n"); - dev_kfree_skb(skb); - } - - - /* put new skb in bin */ - fp->tpa_pool[queue].skb = new_skb; - - } else { - /* else drop the packet and keep the buffer in the bin */ - DP(NETIF_MSG_RX_STATUS, - "Failed to allocate new skb - dropping packet!\n"); - fp->eth_q_stats.rx_skb_alloc_failed++; - } - - fp->tpa_state[queue] = BNX2X_TPA_STOP; -} - -static inline void bnx2x_update_rx_prod(struct bnx2x *bp, - struct bnx2x_fastpath *fp, - u16 bd_prod, u16 rx_comp_prod, - u16 rx_sge_prod) -{ - struct ustorm_eth_rx_producers rx_prods = {0}; - int i; - - /* Update producers */ - rx_prods.bd_prod = bd_prod; - rx_prods.cqe_prod = rx_comp_prod; - rx_prods.sge_prod = rx_sge_prod; - - /* - * Make sure that the BD and SGE data is updated before updating the - * producers since FW might read the BD/SGE right after the producer - * is updated. - * This is only applicable for weak-ordered memory model archs such - * as IA-64. The following barrier is also mandatory since FW will - * assumes BDs must have buffers. - */ - wmb(); - - for (i = 0; i < sizeof(struct ustorm_eth_rx_producers)/4; i++) - REG_WR(bp, BAR_USTRORM_INTMEM + - USTORM_RX_PRODS_OFFSET(BP_PORT(bp), fp->cl_id) + i*4, - ((u32 *)&rx_prods)[i]); - - mmiowb(); /* keep prod updates ordered */ - - DP(NETIF_MSG_RX_STATUS, - "queue[%d]: wrote bd_prod %u cqe_prod %u sge_prod %u\n", - fp->index, bd_prod, rx_comp_prod, rx_sge_prod); -} - -/* Set Toeplitz hash value in the skb using the value from the - * CQE (calculated by HW). - */ -static inline void bnx2x_set_skb_rxhash(struct bnx2x *bp, union eth_rx_cqe *cqe, - struct sk_buff *skb) -{ - /* Set Toeplitz hash from CQE */ - if ((bp->dev->features & NETIF_F_RXHASH) && - (cqe->fast_path_cqe.status_flags & - ETH_FAST_PATH_RX_CQE_RSS_HASH_FLG)) - skb->rxhash = - le32_to_cpu(cqe->fast_path_cqe.rss_hash_result); -} - -static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) -{ - struct bnx2x *bp = fp->bp; - u16 bd_cons, bd_prod, bd_prod_fw, comp_ring_cons; - u16 hw_comp_cons, sw_comp_cons, sw_comp_prod; - int rx_pkt = 0; - -#ifdef BNX2X_STOP_ON_ERROR - if (unlikely(bp->panic)) - return 0; -#endif - - /* CQ "next element" is of the size of the regular element, - that's why it's ok here */ - hw_comp_cons = le16_to_cpu(*fp->rx_cons_sb); - if ((hw_comp_cons & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT) - hw_comp_cons++; - - bd_cons = fp->rx_bd_cons; - bd_prod = fp->rx_bd_prod; - bd_prod_fw = bd_prod; - sw_comp_cons = fp->rx_comp_cons; - sw_comp_prod = fp->rx_comp_prod; - - /* Memory barrier necessary as speculative reads of the rx - * buffer can be ahead of the index in the status block - */ - rmb(); - - DP(NETIF_MSG_RX_STATUS, - "queue[%d]: hw_comp_cons %u sw_comp_cons %u\n", - fp->index, hw_comp_cons, sw_comp_cons); - - while (sw_comp_cons != hw_comp_cons) { - struct sw_rx_bd *rx_buf = NULL; - struct sk_buff *skb; - union eth_rx_cqe *cqe; - u8 cqe_fp_flags; - u16 len, pad; - - comp_ring_cons = RCQ_BD(sw_comp_cons); - bd_prod = RX_BD(bd_prod); - bd_cons = RX_BD(bd_cons); - - /* Prefetch the page containing the BD descriptor - at producer's index. It will be needed when new skb is - allocated */ - prefetch((void *)(PAGE_ALIGN((unsigned long) - (&fp->rx_desc_ring[bd_prod])) - - PAGE_SIZE + 1)); - - cqe = &fp->rx_comp_ring[comp_ring_cons]; - cqe_fp_flags = cqe->fast_path_cqe.type_error_flags; - - DP(NETIF_MSG_RX_STATUS, "CQE type %x err %x status %x" - " queue %x vlan %x len %u\n", CQE_TYPE(cqe_fp_flags), - cqe_fp_flags, cqe->fast_path_cqe.status_flags, - le32_to_cpu(cqe->fast_path_cqe.rss_hash_result), - le16_to_cpu(cqe->fast_path_cqe.vlan_tag), - le16_to_cpu(cqe->fast_path_cqe.pkt_len)); - - /* is this a slowpath msg? */ - if (unlikely(CQE_TYPE(cqe_fp_flags))) { - bnx2x_sp_event(fp, cqe); - goto next_cqe; - - /* this is an rx packet */ - } else { - rx_buf = &fp->rx_buf_ring[bd_cons]; - skb = rx_buf->skb; - prefetch(skb); - len = le16_to_cpu(cqe->fast_path_cqe.pkt_len); - pad = cqe->fast_path_cqe.placement_offset; - - /* If CQE is marked both TPA_START and TPA_END - it is a non-TPA CQE */ - if ((!fp->disable_tpa) && - (TPA_TYPE(cqe_fp_flags) != - (TPA_TYPE_START | TPA_TYPE_END))) { - u16 queue = cqe->fast_path_cqe.queue_index; - - if (TPA_TYPE(cqe_fp_flags) == TPA_TYPE_START) { - DP(NETIF_MSG_RX_STATUS, - "calling tpa_start on queue %d\n", - queue); - - bnx2x_tpa_start(fp, queue, skb, - bd_cons, bd_prod); - - /* Set Toeplitz hash for an LRO skb */ - bnx2x_set_skb_rxhash(bp, cqe, skb); - - goto next_rx; - } - - if (TPA_TYPE(cqe_fp_flags) == TPA_TYPE_END) { - DP(NETIF_MSG_RX_STATUS, - "calling tpa_stop on queue %d\n", - queue); - - if (!BNX2X_RX_SUM_FIX(cqe)) - BNX2X_ERR("STOP on none TCP " - "data\n"); - - /* This is a size of the linear data - on this skb */ - len = le16_to_cpu(cqe->fast_path_cqe. - len_on_bd); - bnx2x_tpa_stop(bp, fp, queue, pad, - len, cqe, comp_ring_cons); -#ifdef BNX2X_STOP_ON_ERROR - if (bp->panic) - return 0; -#endif - - bnx2x_update_sge_prod(fp, - &cqe->fast_path_cqe); - goto next_cqe; - } - } - - dma_sync_single_for_device(&bp->pdev->dev, - dma_unmap_addr(rx_buf, mapping), - pad + RX_COPY_THRESH, - DMA_FROM_DEVICE); - prefetch(((char *)(skb)) + 128); - - /* is this an error packet? */ - if (unlikely(cqe_fp_flags & ETH_RX_ERROR_FALGS)) { - DP(NETIF_MSG_RX_ERR, - "ERROR flags %x rx packet %u\n", - cqe_fp_flags, sw_comp_cons); - fp->eth_q_stats.rx_err_discard_pkt++; - goto reuse_rx; - } - - /* Since we don't have a jumbo ring - * copy small packets if mtu > 1500 - */ - if ((bp->dev->mtu > ETH_MAX_PACKET_SIZE) && - (len <= RX_COPY_THRESH)) { - struct sk_buff *new_skb; - - new_skb = netdev_alloc_skb(bp->dev, - len + pad); - if (new_skb == NULL) { - DP(NETIF_MSG_RX_ERR, - "ERROR packet dropped " - "because of alloc failure\n"); - fp->eth_q_stats.rx_skb_alloc_failed++; - goto reuse_rx; - } - - /* aligned copy */ - skb_copy_from_linear_data_offset(skb, pad, - new_skb->data + pad, len); - skb_reserve(new_skb, pad); - skb_put(new_skb, len); - - bnx2x_reuse_rx_skb(fp, skb, bd_cons, bd_prod); - - skb = new_skb; - - } else - if (likely(bnx2x_alloc_rx_skb(bp, fp, bd_prod) == 0)) { - dma_unmap_single(&bp->pdev->dev, - dma_unmap_addr(rx_buf, mapping), - bp->rx_buf_size, - DMA_FROM_DEVICE); - skb_reserve(skb, pad); - skb_put(skb, len); - - } else { - DP(NETIF_MSG_RX_ERR, - "ERROR packet dropped because " - "of alloc failure\n"); - fp->eth_q_stats.rx_skb_alloc_failed++; -reuse_rx: - bnx2x_reuse_rx_skb(fp, skb, bd_cons, bd_prod); - goto next_rx; - } - - skb->protocol = eth_type_trans(skb, bp->dev); - - /* Set Toeplitz hash for a none-LRO skb */ - bnx2x_set_skb_rxhash(bp, cqe, skb); - - skb->ip_summed = CHECKSUM_NONE; - if (bp->rx_csum) { - if (likely(BNX2X_RX_CSUM_OK(cqe))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - fp->eth_q_stats.hw_csum_err++; - } - } - - skb_record_rx_queue(skb, fp->index); - -#ifdef BCM_VLAN - if ((bp->vlgrp != NULL) && (bp->flags & HW_VLAN_RX_FLAG) && - (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) & - PARSING_FLAGS_VLAN)) - vlan_gro_receive(&fp->napi, bp->vlgrp, - le16_to_cpu(cqe->fast_path_cqe.vlan_tag), skb); - else -#endif - napi_gro_receive(&fp->napi, skb); - - -next_rx: - rx_buf->skb = NULL; - - bd_cons = NEXT_RX_IDX(bd_cons); - bd_prod = NEXT_RX_IDX(bd_prod); - bd_prod_fw = NEXT_RX_IDX(bd_prod_fw); - rx_pkt++; -next_cqe: - sw_comp_prod = NEXT_RCQ_IDX(sw_comp_prod); - sw_comp_cons = NEXT_RCQ_IDX(sw_comp_cons); - - if (rx_pkt == budget) - break; - } /* while */ - - fp->rx_bd_cons = bd_cons; - fp->rx_bd_prod = bd_prod_fw; - fp->rx_comp_cons = sw_comp_cons; - fp->rx_comp_prod = sw_comp_prod; - - /* Update producers */ - bnx2x_update_rx_prod(bp, fp, bd_prod_fw, sw_comp_prod, - fp->rx_sge_prod); - - fp->rx_pkt += rx_pkt; - fp->rx_calls++; - - return rx_pkt; -} - -static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie) -{ - struct bnx2x_fastpath *fp = fp_cookie; - struct bnx2x *bp = fp->bp; - - /* Return here if interrupt is disabled */ - if (unlikely(atomic_read(&bp->intr_sem) != 0)) { - DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n"); - return IRQ_HANDLED; - } - - DP(BNX2X_MSG_FP, "got an MSI-X interrupt on IDX:SB [%d:%d]\n", - fp->index, fp->sb_id); - bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID, 0, IGU_INT_DISABLE, 0); - -#ifdef BNX2X_STOP_ON_ERROR - if (unlikely(bp->panic)) - return IRQ_HANDLED; -#endif - - /* Handle Rx and Tx according to MSI-X vector */ - prefetch(fp->rx_cons_sb); - prefetch(fp->tx_cons_sb); - prefetch(&fp->status_blk->u_status_block.status_block_index); - prefetch(&fp->status_blk->c_status_block.status_block_index); - napi_schedule(&bnx2x_fp(bp, fp->index, napi)); - - return IRQ_HANDLED; -} - -static irqreturn_t bnx2x_interrupt(int irq, void *dev_instance) +irqreturn_t bnx2x_interrupt(int irq, void *dev_instance) { struct bnx2x *bp = netdev_priv(dev_instance); u16 status = bnx2x_ack_int(bp); @@ -1902,7 +963,6 @@ static irqreturn_t bnx2x_interrupt(int irq, void *dev_instance) /* end of fast path */ -static void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event); /* Link */ @@ -1910,7 +970,7 @@ static void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event); * General service functions */ -static int bnx2x_acquire_hw_lock(struct bnx2x *bp, u32 resource) +int bnx2x_acquire_hw_lock(struct bnx2x *bp, u32 resource) { u32 lock_status; u32 resource_bit = (1 << resource); @@ -1955,7 +1015,7 @@ static int bnx2x_acquire_hw_lock(struct bnx2x *bp, u32 resource) return -EAGAIN; } -static int bnx2x_release_hw_lock(struct bnx2x *bp, u32 resource) +int bnx2x_release_hw_lock(struct bnx2x *bp, u32 resource) { u32 lock_status; u32 resource_bit = (1 << resource); @@ -1991,22 +1051,6 @@ static int bnx2x_release_hw_lock(struct bnx2x *bp, u32 resource) return 0; } -/* HW Lock for shared dual port PHYs */ -static void bnx2x_acquire_phy_lock(struct bnx2x *bp) -{ - mutex_lock(&bp->port.phy_mutex); - - if (bp->port.need_hw_lock) - bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_MDIO); -} - -static void bnx2x_release_phy_lock(struct bnx2x *bp) -{ - if (bp->port.need_hw_lock) - bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_MDIO); - - mutex_unlock(&bp->port.phy_mutex); -} int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port) { @@ -2183,7 +1227,7 @@ static int bnx2x_set_spio(struct bnx2x *bp, int spio_num, u32 mode) return 0; } -static void bnx2x_calc_fc_adv(struct bnx2x *bp) +void bnx2x_calc_fc_adv(struct bnx2x *bp) { switch (bp->link_vars.ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK) { @@ -2208,58 +1252,8 @@ static void bnx2x_calc_fc_adv(struct bnx2x *bp) } } -static void bnx2x_link_report(struct bnx2x *bp) -{ - if (bp->flags & MF_FUNC_DIS) { - netif_carrier_off(bp->dev); - netdev_err(bp->dev, "NIC Link is Down\n"); - return; - } - - if (bp->link_vars.link_up) { - u16 line_speed; - if (bp->state == BNX2X_STATE_OPEN) - netif_carrier_on(bp->dev); - netdev_info(bp->dev, "NIC Link is Up, "); - - line_speed = bp->link_vars.line_speed; - if (IS_E1HMF(bp)) { - u16 vn_max_rate; - - vn_max_rate = - ((bp->mf_config & FUNC_MF_CFG_MAX_BW_MASK) >> - FUNC_MF_CFG_MAX_BW_SHIFT) * 100; - if (vn_max_rate < line_speed) - line_speed = vn_max_rate; - } - pr_cont("%d Mbps ", line_speed); - - if (bp->link_vars.duplex == DUPLEX_FULL) - pr_cont("full duplex"); - else - pr_cont("half duplex"); - - if (bp->link_vars.flow_ctrl != BNX2X_FLOW_CTRL_NONE) { - if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) { - pr_cont(", receive "); - if (bp->link_vars.flow_ctrl & - BNX2X_FLOW_CTRL_TX) - pr_cont("& transmit "); - } else { - pr_cont(", transmit "); - } - pr_cont("flow control ON"); - } - pr_cont("\n"); - - } else { /* link_down */ - netif_carrier_off(bp->dev); - netdev_err(bp->dev, "NIC Link is Down\n"); - } -} - -static u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode) +u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode) { if (!BP_NOMCP(bp)) { u8 rc; @@ -2294,7 +1288,7 @@ static u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode) return -EINVAL; } -static void bnx2x_link_set(struct bnx2x *bp) +void bnx2x_link_set(struct bnx2x *bp) { if (!BP_NOMCP(bp)) { bnx2x_acquire_phy_lock(bp); @@ -2316,7 +1310,7 @@ static void bnx2x__link_reset(struct bnx2x *bp) BNX2X_ERR("Bootcode is missing - can not reset link\n"); } -static u8 bnx2x_link_test(struct bnx2x *bp) +u8 bnx2x_link_test(struct bnx2x *bp) { u8 rc = 0; @@ -2548,7 +1542,7 @@ static void bnx2x_link_attn(struct bnx2x *bp) } } -static void bnx2x__link_status_update(struct bnx2x *bp) +void bnx2x__link_status_update(struct bnx2x *bp) { if ((bp->state != BNX2X_STATE_OPEN) || (bp->flags & MF_FUNC_DIS)) return; @@ -2629,9 +1623,6 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command) return rc; } -static void bnx2x_set_eth_mac_addr_e1h(struct bnx2x *bp, int set); -static void bnx2x_set_rx_mode(struct net_device *dev); - static void bnx2x_e1h_disable(struct bnx2x *bp) { int port = BP_PORT(bp); @@ -2759,7 +1750,7 @@ static inline void bnx2x_sp_prod_update(struct bnx2x *bp) } /* the slow path queue is odd since completions arrive on the fastpath ring */ -static int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, +int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, u32 data_hi, u32 data_lo, int common) { struct eth_spe *spe; @@ -3171,10 +2162,6 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn) } } -static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode); -static int bnx2x_nic_load(struct bnx2x *bp, int load_mode); - - #define BNX2X_MISC_GEN_REG MISC_REG_GENERIC_POR_1 #define LOAD_COUNTER_BITS 16 /* Number of bits for load counter */ #define LOAD_COUNTER_MASK (((u32)0x1 << LOAD_COUNTER_BITS) - 1) @@ -3208,7 +2195,7 @@ static inline void bnx2x_set_reset_in_progress(struct bnx2x *bp) /* * should be run under rtnl lock */ -static inline bool bnx2x_reset_is_done(struct bnx2x *bp) +bool bnx2x_reset_is_done(struct bnx2x *bp) { u32 val = REG_RD(bp, BNX2X_MISC_GEN_REG); DP(NETIF_MSG_HW, "GEN_REG_VAL=0x%08x\n", val); @@ -3218,7 +2205,7 @@ static inline bool bnx2x_reset_is_done(struct bnx2x *bp) /* * should be run under rtnl lock */ -static inline void bnx2x_inc_load_cnt(struct bnx2x *bp) +inline void bnx2x_inc_load_cnt(struct bnx2x *bp) { u32 val1, val = REG_RD(bp, BNX2X_MISC_GEN_REG); @@ -3233,7 +2220,7 @@ static inline void bnx2x_inc_load_cnt(struct bnx2x *bp) /* * should be run under rtnl lock */ -static inline u32 bnx2x_dec_load_cnt(struct bnx2x *bp) +u32 bnx2x_dec_load_cnt(struct bnx2x *bp) { u32 val1, val = REG_RD(bp, BNX2X_MISC_GEN_REG); @@ -3451,7 +2438,7 @@ static inline bool bnx2x_parity_attn(struct bnx2x *bp, u32 sig0, u32 sig1, return false; } -static bool bnx2x_chk_parity_attn(struct bnx2x *bp) +bool bnx2x_chk_parity_attn(struct bnx2x *bp) { struct attn_route attn; int port = BP_PORT(bp); @@ -3629,7 +2616,7 @@ static void bnx2x_sp_task(struct work_struct *work) IGU_INT_ENABLE, 1); } -static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance) +irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance) { struct net_device *dev = dev_instance; struct bnx2x *bp = netdev_priv(dev); @@ -3665,1387 +2652,6 @@ static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance) /* end of slow path */ -/* Statistics */ - -/**************************************************************************** -* Macros -****************************************************************************/ - -/* sum[hi:lo] += add[hi:lo] */ -#define ADD_64(s_hi, a_hi, s_lo, a_lo) \ - do { \ - s_lo += a_lo; \ - s_hi += a_hi + ((s_lo < a_lo) ? 1 : 0); \ - } while (0) - -/* difference = minuend - subtrahend */ -#define DIFF_64(d_hi, m_hi, s_hi, d_lo, m_lo, s_lo) \ - do { \ - if (m_lo < s_lo) { \ - /* underflow */ \ - d_hi = m_hi - s_hi; \ - if (d_hi > 0) { \ - /* we can 'loan' 1 */ \ - d_hi--; \ - d_lo = m_lo + (UINT_MAX - s_lo) + 1; \ - } else { \ - /* m_hi <= s_hi */ \ - d_hi = 0; \ - d_lo = 0; \ - } \ - } else { \ - /* m_lo >= s_lo */ \ - if (m_hi < s_hi) { \ - d_hi = 0; \ - d_lo = 0; \ - } else { \ - /* m_hi >= s_hi */ \ - d_hi = m_hi - s_hi; \ - d_lo = m_lo - s_lo; \ - } \ - } \ - } while (0) - -#define UPDATE_STAT64(s, t) \ - do { \ - DIFF_64(diff.hi, new->s##_hi, pstats->mac_stx[0].t##_hi, \ - diff.lo, new->s##_lo, pstats->mac_stx[0].t##_lo); \ - pstats->mac_stx[0].t##_hi = new->s##_hi; \ - pstats->mac_stx[0].t##_lo = new->s##_lo; \ - ADD_64(pstats->mac_stx[1].t##_hi, diff.hi, \ - pstats->mac_stx[1].t##_lo, diff.lo); \ - } while (0) - -#define UPDATE_STAT64_NIG(s, t) \ - do { \ - DIFF_64(diff.hi, new->s##_hi, old->s##_hi, \ - diff.lo, new->s##_lo, old->s##_lo); \ - ADD_64(estats->t##_hi, diff.hi, \ - estats->t##_lo, diff.lo); \ - } while (0) - -/* sum[hi:lo] += add */ -#define ADD_EXTEND_64(s_hi, s_lo, a) \ - do { \ - s_lo += a; \ - s_hi += (s_lo < a) ? 1 : 0; \ - } while (0) - -#define UPDATE_EXTEND_STAT(s) \ - do { \ - ADD_EXTEND_64(pstats->mac_stx[1].s##_hi, \ - pstats->mac_stx[1].s##_lo, \ - new->s); \ - } while (0) - -#define UPDATE_EXTEND_TSTAT(s, t) \ - do { \ - diff = le32_to_cpu(tclient->s) - le32_to_cpu(old_tclient->s); \ - old_tclient->s = tclient->s; \ - ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \ - } while (0) - -#define UPDATE_EXTEND_USTAT(s, t) \ - do { \ - diff = le32_to_cpu(uclient->s) - le32_to_cpu(old_uclient->s); \ - old_uclient->s = uclient->s; \ - ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \ - } while (0) - -#define UPDATE_EXTEND_XSTAT(s, t) \ - do { \ - diff = le32_to_cpu(xclient->s) - le32_to_cpu(old_xclient->s); \ - old_xclient->s = xclient->s; \ - ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \ - } while (0) - -/* minuend -= subtrahend */ -#define SUB_64(m_hi, s_hi, m_lo, s_lo) \ - do { \ - DIFF_64(m_hi, m_hi, s_hi, m_lo, m_lo, s_lo); \ - } while (0) - -/* minuend[hi:lo] -= subtrahend */ -#define SUB_EXTEND_64(m_hi, m_lo, s) \ - do { \ - SUB_64(m_hi, 0, m_lo, s); \ - } while (0) - -#define SUB_EXTEND_USTAT(s, t) \ - do { \ - diff = le32_to_cpu(uclient->s) - le32_to_cpu(old_uclient->s); \ - SUB_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \ - } while (0) - -/* - * General service functions - */ - -static inline long bnx2x_hilo(u32 *hiref) -{ - u32 lo = *(hiref + 1); -#if (BITS_PER_LONG == 64) - u32 hi = *hiref; - - return HILO_U64(hi, lo); -#else - return lo; -#endif -} - -/* - * Init service functions - */ - -static void bnx2x_storm_stats_post(struct bnx2x *bp) -{ - if (!bp->stats_pending) { - struct eth_query_ramrod_data ramrod_data = {0}; - int i, rc; - - ramrod_data.drv_counter = bp->stats_counter++; - ramrod_data.collect_port = bp->port.pmf ? 1 : 0; - for_each_queue(bp, i) - ramrod_data.ctr_id_vector |= (1 << bp->fp[i].cl_id); - - rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_STAT_QUERY, 0, - ((u32 *)&ramrod_data)[1], - ((u32 *)&ramrod_data)[0], 0); - if (rc == 0) { - /* stats ramrod has it's own slot on the spq */ - bp->spq_left++; - bp->stats_pending = 1; - } - } -} - -static void bnx2x_hw_stats_post(struct bnx2x *bp) -{ - struct dmae_command *dmae = &bp->stats_dmae; - u32 *stats_comp = bnx2x_sp(bp, stats_comp); - - *stats_comp = DMAE_COMP_VAL; - if (CHIP_REV_IS_SLOW(bp)) - return; - - /* loader */ - if (bp->executer_idx) { - int loader_idx = PMF_DMAE_C(bp); - - memset(dmae, 0, sizeof(struct dmae_command)); - - dmae->opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC | - DMAE_CMD_C_DST_GRC | DMAE_CMD_C_ENABLE | - DMAE_CMD_DST_RESET | -#ifdef __BIG_ENDIAN - DMAE_CMD_ENDIANITY_B_DW_SWAP | -#else - DMAE_CMD_ENDIANITY_DW_SWAP | -#endif - (BP_PORT(bp) ? DMAE_CMD_PORT_1 : - DMAE_CMD_PORT_0) | - (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT)); - dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, dmae[0])); - dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, dmae[0])); - dmae->dst_addr_lo = (DMAE_REG_CMD_MEM + - sizeof(struct dmae_command) * - (loader_idx + 1)) >> 2; - dmae->dst_addr_hi = 0; - dmae->len = sizeof(struct dmae_command) >> 2; - if (CHIP_IS_E1(bp)) - dmae->len--; - dmae->comp_addr_lo = dmae_reg_go_c[loader_idx + 1] >> 2; - dmae->comp_addr_hi = 0; - dmae->comp_val = 1; - - *stats_comp = 0; - bnx2x_post_dmae(bp, dmae, loader_idx); - - } else if (bp->func_stx) { - *stats_comp = 0; - bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp)); - } -} - -static int bnx2x_stats_comp(struct bnx2x *bp) -{ - u32 *stats_comp = bnx2x_sp(bp, stats_comp); - int cnt = 10; - - might_sleep(); - while (*stats_comp != DMAE_COMP_VAL) { - if (!cnt) { - BNX2X_ERR("timeout waiting for stats finished\n"); - break; - } - cnt--; - msleep(1); - } - return 1; -} - -/* - * Statistics service functions - */ - -static void bnx2x_stats_pmf_update(struct bnx2x *bp) -{ - struct dmae_command *dmae; - u32 opcode; - int loader_idx = PMF_DMAE_C(bp); - u32 *stats_comp = bnx2x_sp(bp, stats_comp); - - /* sanity */ - if (!IS_E1HMF(bp) || !bp->port.pmf || !bp->port.port_stx) { - BNX2X_ERR("BUG!\n"); - return; - } - - bp->executer_idx = 0; - - opcode = (DMAE_CMD_SRC_GRC | DMAE_CMD_DST_PCI | - DMAE_CMD_C_ENABLE | - DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET | -#ifdef __BIG_ENDIAN - DMAE_CMD_ENDIANITY_B_DW_SWAP | -#else - DMAE_CMD_ENDIANITY_DW_SWAP | -#endif - (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) | - (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT)); - - dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); - dmae->opcode = (opcode | DMAE_CMD_C_DST_GRC); - dmae->src_addr_lo = bp->port.port_stx >> 2; - dmae->src_addr_hi = 0; - dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats)); - dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats)); - dmae->len = DMAE_LEN32_RD_MAX; - dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; - dmae->comp_addr_hi = 0; - dmae->comp_val = 1; - - dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); - dmae->opcode = (opcode | DMAE_CMD_C_DST_PCI); - dmae->src_addr_lo = (bp->port.port_stx >> 2) + DMAE_LEN32_RD_MAX; - dmae->src_addr_hi = 0; - dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats) + - DMAE_LEN32_RD_MAX * 4); - dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats) + - DMAE_LEN32_RD_MAX * 4); - dmae->len = (sizeof(struct host_port_stats) >> 2) - DMAE_LEN32_RD_MAX; - dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp)); - dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp)); - dmae->comp_val = DMAE_COMP_VAL; - - *stats_comp = 0; - bnx2x_hw_stats_post(bp); - bnx2x_stats_comp(bp); -} - -static void bnx2x_port_stats_init(struct bnx2x *bp) -{ - struct dmae_command *dmae; - int port = BP_PORT(bp); - int vn = BP_E1HVN(bp); - u32 opcode; - int loader_idx = PMF_DMAE_C(bp); - u32 mac_addr; - u32 *stats_comp = bnx2x_sp(bp, stats_comp); - - /* sanity */ - if (!bp->link_vars.link_up || !bp->port.pmf) { - BNX2X_ERR("BUG!\n"); - return; - } - - bp->executer_idx = 0; - - /* MCP */ - opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC | - DMAE_CMD_C_DST_GRC | DMAE_CMD_C_ENABLE | - DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET | -#ifdef __BIG_ENDIAN - DMAE_CMD_ENDIANITY_B_DW_SWAP | -#else - DMAE_CMD_ENDIANITY_DW_SWAP | -#endif - (port ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) | - (vn << DMAE_CMD_E1HVN_SHIFT)); - - if (bp->port.port_stx) { - - dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); - dmae->opcode = opcode; - dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats)); - dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats)); - dmae->dst_addr_lo = bp->port.port_stx >> 2; - dmae->dst_addr_hi = 0; - dmae->len = sizeof(struct host_port_stats) >> 2; - dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; - dmae->comp_addr_hi = 0; - dmae->comp_val = 1; - } - - if (bp->func_stx) { - - dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); - dmae->opcode = opcode; - dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, func_stats)); - dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, func_stats)); - dmae->dst_addr_lo = bp->func_stx >> 2; - dmae->dst_addr_hi = 0; - dmae->len = sizeof(struct host_func_stats) >> 2; - dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; - dmae->comp_addr_hi = 0; - dmae->comp_val = 1; - } - - /* MAC */ - opcode = (DMAE_CMD_SRC_GRC | DMAE_CMD_DST_PCI | - DMAE_CMD_C_DST_GRC | DMAE_CMD_C_ENABLE | - DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET | -#ifdef __BIG_ENDIAN - DMAE_CMD_ENDIANITY_B_DW_SWAP | -#else - DMAE_CMD_ENDIANITY_DW_SWAP | -#endif - (port ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) | - (vn << DMAE_CMD_E1HVN_SHIFT)); - - if (bp->link_vars.mac_type == MAC_TYPE_BMAC) { - - mac_addr = (port ? NIG_REG_INGRESS_BMAC1_MEM : - NIG_REG_INGRESS_BMAC0_MEM); - - /* BIGMAC_REGISTER_TX_STAT_GTPKT .. - BIGMAC_REGISTER_TX_STAT_GTBYT */ - dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); - dmae->opcode = opcode; - dmae->src_addr_lo = (mac_addr + - BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2; - dmae->src_addr_hi = 0; - dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats)); - dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats)); - dmae->len = (8 + BIGMAC_REGISTER_TX_STAT_GTBYT - - BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2; - dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; - dmae->comp_addr_hi = 0; - dmae->comp_val = 1; - - /* BIGMAC_REGISTER_RX_STAT_GR64 .. - BIGMAC_REGISTER_RX_STAT_GRIPJ */ - dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); - dmae->opcode = opcode; - dmae->src_addr_lo = (mac_addr + - BIGMAC_REGISTER_RX_STAT_GR64) >> 2; - dmae->src_addr_hi = 0; - dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats) + - offsetof(struct bmac_stats, rx_stat_gr64_lo)); - dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats) + - offsetof(struct bmac_stats, rx_stat_gr64_lo)); - dmae->len = (8 + BIGMAC_REGISTER_RX_STAT_GRIPJ - - BIGMAC_REGISTER_RX_STAT_GR64) >> 2; - dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; - dmae->comp_addr_hi = 0; - dmae->comp_val = 1; - - } else if (bp->link_vars.mac_type == MAC_TYPE_EMAC) { - - mac_addr = (port ? GRCBASE_EMAC1 : GRCBASE_EMAC0); - - /* EMAC_REG_EMAC_RX_STAT_AC (EMAC_REG_EMAC_RX_STAT_AC_COUNT)*/ - dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); - dmae->opcode = opcode; - dmae->src_addr_lo = (mac_addr + - EMAC_REG_EMAC_RX_STAT_AC) >> 2; - dmae->src_addr_hi = 0; - dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats)); - dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats)); - dmae->len = EMAC_REG_EMAC_RX_STAT_AC_COUNT; - dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; - dmae->comp_addr_hi = 0; - dmae->comp_val = 1; - - /* EMAC_REG_EMAC_RX_STAT_AC_28 */ - dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); - dmae->opcode = opcode; - dmae->src_addr_lo = (mac_addr + - EMAC_REG_EMAC_RX_STAT_AC_28) >> 2; - dmae->src_addr_hi = 0; - dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats) + - offsetof(struct emac_stats, rx_stat_falsecarriererrors)); - dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats) + - offsetof(struct emac_stats, rx_stat_falsecarriererrors)); - dmae->len = 1; - dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; - dmae->comp_addr_hi = 0; - dmae->comp_val = 1; - - /* EMAC_REG_EMAC_TX_STAT_AC (EMAC_REG_EMAC_TX_STAT_AC_COUNT)*/ - dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); - dmae->opcode = opcode; - dmae->src_addr_lo = (mac_addr + - EMAC_REG_EMAC_TX_STAT_AC) >> 2; - dmae->src_addr_hi = 0; - dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats) + - offsetof(struct emac_stats, tx_stat_ifhcoutoctets)); - dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats) + - offsetof(struct emac_stats, tx_stat_ifhcoutoctets)); - dmae->len = EMAC_REG_EMAC_TX_STAT_AC_COUNT; - dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; - dmae->comp_addr_hi = 0; - dmae->comp_val = 1; - } - - /* NIG */ - dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); - dmae->opcode = opcode; - dmae->src_addr_lo = (port ? NIG_REG_STAT1_BRB_DISCARD : - NIG_REG_STAT0_BRB_DISCARD) >> 2; - dmae->src_addr_hi = 0; - dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats)); - dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats)); - dmae->len = (sizeof(struct nig_stats) - 4*sizeof(u32)) >> 2; - dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; - dmae->comp_addr_hi = 0; - dmae->comp_val = 1; - - dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); - dmae->opcode = opcode; - dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT0 : - NIG_REG_STAT0_EGRESS_MAC_PKT0) >> 2; - dmae->src_addr_hi = 0; - dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats) + - offsetof(struct nig_stats, egress_mac_pkt0_lo)); - dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats) + - offsetof(struct nig_stats, egress_mac_pkt0_lo)); - dmae->len = (2*sizeof(u32)) >> 2; - dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; - dmae->comp_addr_hi = 0; - dmae->comp_val = 1; - - dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); - dmae->opcode = (DMAE_CMD_SRC_GRC | DMAE_CMD_DST_PCI | - DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE | - DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET | -#ifdef __BIG_ENDIAN - DMAE_CMD_ENDIANITY_B_DW_SWAP | -#else - DMAE_CMD_ENDIANITY_DW_SWAP | -#endif - (port ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) | - (vn << DMAE_CMD_E1HVN_SHIFT)); - dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT1 : - NIG_REG_STAT0_EGRESS_MAC_PKT1) >> 2; - dmae->src_addr_hi = 0; - dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats) + - offsetof(struct nig_stats, egress_mac_pkt1_lo)); - dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats) + - offsetof(struct nig_stats, egress_mac_pkt1_lo)); - dmae->len = (2*sizeof(u32)) >> 2; - dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp)); - dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp)); - dmae->comp_val = DMAE_COMP_VAL; - - *stats_comp = 0; -} - -static void bnx2x_func_stats_init(struct bnx2x *bp) -{ - struct dmae_command *dmae = &bp->stats_dmae; - u32 *stats_comp = bnx2x_sp(bp, stats_comp); - - /* sanity */ - if (!bp->func_stx) { - BNX2X_ERR("BUG!\n"); - return; - } - - bp->executer_idx = 0; - memset(dmae, 0, sizeof(struct dmae_command)); - - dmae->opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC | - DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE | - DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET | -#ifdef __BIG_ENDIAN - DMAE_CMD_ENDIANITY_B_DW_SWAP | -#else - DMAE_CMD_ENDIANITY_DW_SWAP | -#endif - (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) | - (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT)); - dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, func_stats)); - dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, func_stats)); - dmae->dst_addr_lo = bp->func_stx >> 2; - dmae->dst_addr_hi = 0; - dmae->len = sizeof(struct host_func_stats) >> 2; - dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp)); - dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp)); - dmae->comp_val = DMAE_COMP_VAL; - - *stats_comp = 0; -} - -static void bnx2x_stats_start(struct bnx2x *bp) -{ - if (bp->port.pmf) - bnx2x_port_stats_init(bp); - - else if (bp->func_stx) - bnx2x_func_stats_init(bp); - - bnx2x_hw_stats_post(bp); - bnx2x_storm_stats_post(bp); -} - -static void bnx2x_stats_pmf_start(struct bnx2x *bp) -{ - bnx2x_stats_comp(bp); - bnx2x_stats_pmf_update(bp); - bnx2x_stats_start(bp); -} - -static void bnx2x_stats_restart(struct bnx2x *bp) -{ - bnx2x_stats_comp(bp); - bnx2x_stats_start(bp); -} - -static void bnx2x_bmac_stats_update(struct bnx2x *bp) -{ - struct bmac_stats *new = bnx2x_sp(bp, mac_stats.bmac_stats); - struct host_port_stats *pstats = bnx2x_sp(bp, port_stats); - struct bnx2x_eth_stats *estats = &bp->eth_stats; - struct { - u32 lo; - u32 hi; - } diff; - - UPDATE_STAT64(rx_stat_grerb, rx_stat_ifhcinbadoctets); - UPDATE_STAT64(rx_stat_grfcs, rx_stat_dot3statsfcserrors); - UPDATE_STAT64(rx_stat_grund, rx_stat_etherstatsundersizepkts); - UPDATE_STAT64(rx_stat_grovr, rx_stat_dot3statsframestoolong); - UPDATE_STAT64(rx_stat_grfrg, rx_stat_etherstatsfragments); - UPDATE_STAT64(rx_stat_grjbr, rx_stat_etherstatsjabbers); - UPDATE_STAT64(rx_stat_grxcf, rx_stat_maccontrolframesreceived); - UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffstateentered); - UPDATE_STAT64(rx_stat_grxpf, rx_stat_bmac_xpf); - UPDATE_STAT64(tx_stat_gtxpf, tx_stat_outxoffsent); - UPDATE_STAT64(tx_stat_gtxpf, tx_stat_flowcontroldone); - UPDATE_STAT64(tx_stat_gt64, tx_stat_etherstatspkts64octets); - UPDATE_STAT64(tx_stat_gt127, - tx_stat_etherstatspkts65octetsto127octets); - UPDATE_STAT64(tx_stat_gt255, - tx_stat_etherstatspkts128octetsto255octets); - UPDATE_STAT64(tx_stat_gt511, - tx_stat_etherstatspkts256octetsto511octets); - UPDATE_STAT64(tx_stat_gt1023, - tx_stat_etherstatspkts512octetsto1023octets); - UPDATE_STAT64(tx_stat_gt1518, - tx_stat_etherstatspkts1024octetsto1522octets); - UPDATE_STAT64(tx_stat_gt2047, tx_stat_bmac_2047); - UPDATE_STAT64(tx_stat_gt4095, tx_stat_bmac_4095); - UPDATE_STAT64(tx_stat_gt9216, tx_stat_bmac_9216); - UPDATE_STAT64(tx_stat_gt16383, tx_stat_bmac_16383); - UPDATE_STAT64(tx_stat_gterr, - tx_stat_dot3statsinternalmactransmiterrors); - UPDATE_STAT64(tx_stat_gtufl, tx_stat_bmac_ufl); - - estats->pause_frames_received_hi = - pstats->mac_stx[1].rx_stat_bmac_xpf_hi; - estats->pause_frames_received_lo = - pstats->mac_stx[1].rx_stat_bmac_xpf_lo; - - estats->pause_frames_sent_hi = - pstats->mac_stx[1].tx_stat_outxoffsent_hi; - estats->pause_frames_sent_lo = - pstats->mac_stx[1].tx_stat_outxoffsent_lo; -} - -static void bnx2x_emac_stats_update(struct bnx2x *bp) -{ - struct emac_stats *new = bnx2x_sp(bp, mac_stats.emac_stats); - struct host_port_stats *pstats = bnx2x_sp(bp, port_stats); - struct bnx2x_eth_stats *estats = &bp->eth_stats; - - UPDATE_EXTEND_STAT(rx_stat_ifhcinbadoctets); - UPDATE_EXTEND_STAT(tx_stat_ifhcoutbadoctets); - UPDATE_EXTEND_STAT(rx_stat_dot3statsfcserrors); - UPDATE_EXTEND_STAT(rx_stat_dot3statsalignmenterrors); - UPDATE_EXTEND_STAT(rx_stat_dot3statscarriersenseerrors); - UPDATE_EXTEND_STAT(rx_stat_falsecarriererrors); - UPDATE_EXTEND_STAT(rx_stat_etherstatsundersizepkts); - UPDATE_EXTEND_STAT(rx_stat_dot3statsframestoolong); - UPDATE_EXTEND_STAT(rx_stat_etherstatsfragments); - UPDATE_EXTEND_STAT(rx_stat_etherstatsjabbers); - UPDATE_EXTEND_STAT(rx_stat_maccontrolframesreceived); - UPDATE_EXTEND_STAT(rx_stat_xoffstateentered); - UPDATE_EXTEND_STAT(rx_stat_xonpauseframesreceived); - UPDATE_EXTEND_STAT(rx_stat_xoffpauseframesreceived); - UPDATE_EXTEND_STAT(tx_stat_outxonsent); - UPDATE_EXTEND_STAT(tx_stat_outxoffsent); - UPDATE_EXTEND_STAT(tx_stat_flowcontroldone); - UPDATE_EXTEND_STAT(tx_stat_etherstatscollisions); - UPDATE_EXTEND_STAT(tx_stat_dot3statssinglecollisionframes); - UPDATE_EXTEND_STAT(tx_stat_dot3statsmultiplecollisionframes); - UPDATE_EXTEND_STAT(tx_stat_dot3statsdeferredtransmissions); - UPDATE_EXTEND_STAT(tx_stat_dot3statsexcessivecollisions); - UPDATE_EXTEND_STAT(tx_stat_dot3statslatecollisions); - UPDATE_EXTEND_STAT(tx_stat_etherstatspkts64octets); - UPDATE_EXTEND_STAT(tx_stat_etherstatspkts65octetsto127octets); - UPDATE_EXTEND_STAT(tx_stat_etherstatspkts128octetsto255octets); - UPDATE_EXTEND_STAT(tx_stat_etherstatspkts256octetsto511octets); - UPDATE_EXTEND_STAT(tx_stat_etherstatspkts512octetsto1023octets); - UPDATE_EXTEND_STAT(tx_stat_etherstatspkts1024octetsto1522octets); - UPDATE_EXTEND_STAT(tx_stat_etherstatspktsover1522octets); - UPDATE_EXTEND_STAT(tx_stat_dot3statsinternalmactransmiterrors); - - estats->pause_frames_received_hi = - pstats->mac_stx[1].rx_stat_xonpauseframesreceived_hi; - estats->pause_frames_received_lo = - pstats->mac_stx[1].rx_stat_xonpauseframesreceived_lo; - ADD_64(estats->pause_frames_received_hi, - pstats->mac_stx[1].rx_stat_xoffpauseframesreceived_hi, - estats->pause_frames_received_lo, - pstats->mac_stx[1].rx_stat_xoffpauseframesreceived_lo); - - estats->pause_frames_sent_hi = - pstats->mac_stx[1].tx_stat_outxonsent_hi; - estats->pause_frames_sent_lo = - pstats->mac_stx[1].tx_stat_outxonsent_lo; - ADD_64(estats->pause_frames_sent_hi, - pstats->mac_stx[1].tx_stat_outxoffsent_hi, - estats->pause_frames_sent_lo, - pstats->mac_stx[1].tx_stat_outxoffsent_lo); -} - -static int bnx2x_hw_stats_update(struct bnx2x *bp) -{ - struct nig_stats *new = bnx2x_sp(bp, nig_stats); - struct nig_stats *old = &(bp->port.old_nig_stats); - struct host_port_stats *pstats = bnx2x_sp(bp, port_stats); - struct bnx2x_eth_stats *estats = &bp->eth_stats; - struct { - u32 lo; - u32 hi; - } diff; - - if (bp->link_vars.mac_type == MAC_TYPE_BMAC) - bnx2x_bmac_stats_update(bp); - - else if (bp->link_vars.mac_type == MAC_TYPE_EMAC) - bnx2x_emac_stats_update(bp); - - else { /* unreached */ - BNX2X_ERR("stats updated by DMAE but no MAC active\n"); - return -1; - } - - ADD_EXTEND_64(pstats->brb_drop_hi, pstats->brb_drop_lo, - new->brb_discard - old->brb_discard); - ADD_EXTEND_64(estats->brb_truncate_hi, estats->brb_truncate_lo, - new->brb_truncate - old->brb_truncate); - - UPDATE_STAT64_NIG(egress_mac_pkt0, - etherstatspkts1024octetsto1522octets); - UPDATE_STAT64_NIG(egress_mac_pkt1, etherstatspktsover1522octets); - - memcpy(old, new, sizeof(struct nig_stats)); - - memcpy(&(estats->rx_stat_ifhcinbadoctets_hi), &(pstats->mac_stx[1]), - sizeof(struct mac_stx)); - estats->brb_drop_hi = pstats->brb_drop_hi; - estats->brb_drop_lo = pstats->brb_drop_lo; - - pstats->host_port_stats_start = ++pstats->host_port_stats_end; - - if (!BP_NOMCP(bp)) { - u32 nig_timer_max = - SHMEM_RD(bp, port_mb[BP_PORT(bp)].stat_nig_timer); - if (nig_timer_max != estats->nig_timer_max) { - estats->nig_timer_max = nig_timer_max; - BNX2X_ERR("NIG timer max (%u)\n", - estats->nig_timer_max); - } - } - - return 0; -} - -static int bnx2x_storm_stats_update(struct bnx2x *bp) -{ - struct eth_stats_query *stats = bnx2x_sp(bp, fw_stats); - struct tstorm_per_port_stats *tport = - &stats->tstorm_common.port_statistics; - struct host_func_stats *fstats = bnx2x_sp(bp, func_stats); - struct bnx2x_eth_stats *estats = &bp->eth_stats; - int i; - - memcpy(&(fstats->total_bytes_received_hi), - &(bnx2x_sp(bp, func_stats_base)->total_bytes_received_hi), - sizeof(struct host_func_stats) - 2*sizeof(u32)); - estats->error_bytes_received_hi = 0; - estats->error_bytes_received_lo = 0; - estats->etherstatsoverrsizepkts_hi = 0; - estats->etherstatsoverrsizepkts_lo = 0; - estats->no_buff_discard_hi = 0; - estats->no_buff_discard_lo = 0; - - for_each_queue(bp, i) { - struct bnx2x_fastpath *fp = &bp->fp[i]; - int cl_id = fp->cl_id; - struct tstorm_per_client_stats *tclient = - &stats->tstorm_common.client_statistics[cl_id]; - struct tstorm_per_client_stats *old_tclient = &fp->old_tclient; - struct ustorm_per_client_stats *uclient = - &stats->ustorm_common.client_statistics[cl_id]; - struct ustorm_per_client_stats *old_uclient = &fp->old_uclient; - struct xstorm_per_client_stats *xclient = - &stats->xstorm_common.client_statistics[cl_id]; - struct xstorm_per_client_stats *old_xclient = &fp->old_xclient; - struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats; - u32 diff; - - /* are storm stats valid? */ - if ((u16)(le16_to_cpu(xclient->stats_counter) + 1) != - bp->stats_counter) { - DP(BNX2X_MSG_STATS, "[%d] stats not updated by xstorm" - " xstorm counter (0x%x) != stats_counter (0x%x)\n", - i, xclient->stats_counter, bp->stats_counter); - return -1; - } - if ((u16)(le16_to_cpu(tclient->stats_counter) + 1) != - bp->stats_counter) { - DP(BNX2X_MSG_STATS, "[%d] stats not updated by tstorm" - " tstorm counter (0x%x) != stats_counter (0x%x)\n", - i, tclient->stats_counter, bp->stats_counter); - return -2; - } - if ((u16)(le16_to_cpu(uclient->stats_counter) + 1) != - bp->stats_counter) { - DP(BNX2X_MSG_STATS, "[%d] stats not updated by ustorm" - " ustorm counter (0x%x) != stats_counter (0x%x)\n", - i, uclient->stats_counter, bp->stats_counter); - return -4; - } - - qstats->total_bytes_received_hi = - le32_to_cpu(tclient->rcv_broadcast_bytes.hi); - qstats->total_bytes_received_lo = - le32_to_cpu(tclient->rcv_broadcast_bytes.lo); - - ADD_64(qstats->total_bytes_received_hi, - le32_to_cpu(tclient->rcv_multicast_bytes.hi), - qstats->total_bytes_received_lo, - le32_to_cpu(tclient->rcv_multicast_bytes.lo)); - - ADD_64(qstats->total_bytes_received_hi, - le32_to_cpu(tclient->rcv_unicast_bytes.hi), - qstats->total_bytes_received_lo, - le32_to_cpu(tclient->rcv_unicast_bytes.lo)); - - SUB_64(qstats->total_bytes_received_hi, - le32_to_cpu(uclient->bcast_no_buff_bytes.hi), - qstats->total_bytes_received_lo, - le32_to_cpu(uclient->bcast_no_buff_bytes.lo)); - - SUB_64(qstats->total_bytes_received_hi, - le32_to_cpu(uclient->mcast_no_buff_bytes.hi), - qstats->total_bytes_received_lo, - le32_to_cpu(uclient->mcast_no_buff_bytes.lo)); - - SUB_64(qstats->total_bytes_received_hi, - le32_to_cpu(uclient->ucast_no_buff_bytes.hi), - qstats->total_bytes_received_lo, - le32_to_cpu(uclient->ucast_no_buff_bytes.lo)); - - qstats->valid_bytes_received_hi = - qstats->total_bytes_received_hi; - qstats->valid_bytes_received_lo = - qstats->total_bytes_received_lo; - - qstats->error_bytes_received_hi = - le32_to_cpu(tclient->rcv_error_bytes.hi); - qstats->error_bytes_received_lo = - le32_to_cpu(tclient->rcv_error_bytes.lo); - - ADD_64(qstats->total_bytes_received_hi, - qstats->error_bytes_received_hi, - qstats->total_bytes_received_lo, - qstats->error_bytes_received_lo); - - UPDATE_EXTEND_TSTAT(rcv_unicast_pkts, - total_unicast_packets_received); - UPDATE_EXTEND_TSTAT(rcv_multicast_pkts, - total_multicast_packets_received); - UPDATE_EXTEND_TSTAT(rcv_broadcast_pkts, - total_broadcast_packets_received); - UPDATE_EXTEND_TSTAT(packets_too_big_discard, - etherstatsoverrsizepkts); - UPDATE_EXTEND_TSTAT(no_buff_discard, no_buff_discard); - - SUB_EXTEND_USTAT(ucast_no_buff_pkts, - total_unicast_packets_received); - SUB_EXTEND_USTAT(mcast_no_buff_pkts, - total_multicast_packets_received); - SUB_EXTEND_USTAT(bcast_no_buff_pkts, - total_broadcast_packets_received); - UPDATE_EXTEND_USTAT(ucast_no_buff_pkts, no_buff_discard); - UPDATE_EXTEND_USTAT(mcast_no_buff_pkts, no_buff_discard); - UPDATE_EXTEND_USTAT(bcast_no_buff_pkts, no_buff_discard); - - qstats->total_bytes_transmitted_hi = - le32_to_cpu(xclient->unicast_bytes_sent.hi); - qstats->total_bytes_transmitted_lo = - le32_to_cpu(xclient->unicast_bytes_sent.lo); - - ADD_64(qstats->total_bytes_transmitted_hi, - le32_to_cpu(xclient->multicast_bytes_sent.hi), - qstats->total_bytes_transmitted_lo, - le32_to_cpu(xclient->multicast_bytes_sent.lo)); - - ADD_64(qstats->total_bytes_transmitted_hi, - le32_to_cpu(xclient->broadcast_bytes_sent.hi), - qstats->total_bytes_transmitted_lo, - le32_to_cpu(xclient->broadcast_bytes_sent.lo)); - - UPDATE_EXTEND_XSTAT(unicast_pkts_sent, - total_unicast_packets_transmitted); - UPDATE_EXTEND_XSTAT(multicast_pkts_sent, - total_multicast_packets_transmitted); - UPDATE_EXTEND_XSTAT(broadcast_pkts_sent, - total_broadcast_packets_transmitted); - - old_tclient->checksum_discard = tclient->checksum_discard; - old_tclient->ttl0_discard = tclient->ttl0_discard; - - ADD_64(fstats->total_bytes_received_hi, - qstats->total_bytes_received_hi, - fstats->total_bytes_received_lo, - qstats->total_bytes_received_lo); - ADD_64(fstats->total_bytes_transmitted_hi, - qstats->total_bytes_transmitted_hi, - fstats->total_bytes_transmitted_lo, - qstats->total_bytes_transmitted_lo); - ADD_64(fstats->total_unicast_packets_received_hi, - qstats->total_unicast_packets_received_hi, - fstats->total_unicast_packets_received_lo, - qstats->total_unicast_packets_received_lo); - ADD_64(fstats->total_multicast_packets_received_hi, - qstats->total_multicast_packets_received_hi, - fstats->total_multicast_packets_received_lo, - qstats->total_multicast_packets_received_lo); - ADD_64(fstats->total_broadcast_packets_received_hi, - qstats->total_broadcast_packets_received_hi, - fstats->total_broadcast_packets_received_lo, - qstats->total_broadcast_packets_received_lo); - ADD_64(fstats->total_unicast_packets_transmitted_hi, - qstats->total_unicast_packets_transmitted_hi, - fstats->total_unicast_packets_transmitted_lo, - qstats->total_unicast_packets_transmitted_lo); - ADD_64(fstats->total_multicast_packets_transmitted_hi, - qstats->total_multicast_packets_transmitted_hi, - fstats->total_multicast_packets_transmitted_lo, - qstats->total_multicast_packets_transmitted_lo); - ADD_64(fstats->total_broadcast_packets_transmitted_hi, - qstats->total_broadcast_packets_transmitted_hi, - fstats->total_broadcast_packets_transmitted_lo, - qstats->total_broadcast_packets_transmitted_lo); - ADD_64(fstats->valid_bytes_received_hi, - qstats->valid_bytes_received_hi, - fstats->valid_bytes_received_lo, - qstats->valid_bytes_received_lo); - - ADD_64(estats->error_bytes_received_hi, - qstats->error_bytes_received_hi, - estats->error_bytes_received_lo, - qstats->error_bytes_received_lo); - ADD_64(estats->etherstatsoverrsizepkts_hi, - qstats->etherstatsoverrsizepkts_hi, - estats->etherstatsoverrsizepkts_lo, - qstats->etherstatsoverrsizepkts_lo); - ADD_64(estats->no_buff_discard_hi, qstats->no_buff_discard_hi, - estats->no_buff_discard_lo, qstats->no_buff_discard_lo); - } - - ADD_64(fstats->total_bytes_received_hi, - estats->rx_stat_ifhcinbadoctets_hi, - fstats->total_bytes_received_lo, - estats->rx_stat_ifhcinbadoctets_lo); - - memcpy(estats, &(fstats->total_bytes_received_hi), - sizeof(struct host_func_stats) - 2*sizeof(u32)); - - ADD_64(estats->etherstatsoverrsizepkts_hi, - estats->rx_stat_dot3statsframestoolong_hi, - estats->etherstatsoverrsizepkts_lo, - estats->rx_stat_dot3statsframestoolong_lo); - ADD_64(estats->error_bytes_received_hi, - estats->rx_stat_ifhcinbadoctets_hi, - estats->error_bytes_received_lo, - estats->rx_stat_ifhcinbadoctets_lo); - - if (bp->port.pmf) { - estats->mac_filter_discard = - le32_to_cpu(tport->mac_filter_discard); - estats->xxoverflow_discard = - le32_to_cpu(tport->xxoverflow_discard); - estats->brb_truncate_discard = - le32_to_cpu(tport->brb_truncate_discard); - estats->mac_discard = le32_to_cpu(tport->mac_discard); - } - - fstats->host_func_stats_start = ++fstats->host_func_stats_end; - - bp->stats_pending = 0; - - return 0; -} - -static void bnx2x_net_stats_update(struct bnx2x *bp) -{ - struct bnx2x_eth_stats *estats = &bp->eth_stats; - struct net_device_stats *nstats = &bp->dev->stats; - int i; - - nstats->rx_packets = - bnx2x_hilo(&estats->total_unicast_packets_received_hi) + - bnx2x_hilo(&estats->total_multicast_packets_received_hi) + - bnx2x_hilo(&estats->total_broadcast_packets_received_hi); - - nstats->tx_packets = - bnx2x_hilo(&estats->total_unicast_packets_transmitted_hi) + - bnx2x_hilo(&estats->total_multicast_packets_transmitted_hi) + - bnx2x_hilo(&estats->total_broadcast_packets_transmitted_hi); - - nstats->rx_bytes = bnx2x_hilo(&estats->total_bytes_received_hi); - - nstats->tx_bytes = bnx2x_hilo(&estats->total_bytes_transmitted_hi); - - nstats->rx_dropped = estats->mac_discard; - for_each_queue(bp, i) - nstats->rx_dropped += - le32_to_cpu(bp->fp[i].old_tclient.checksum_discard); - - nstats->tx_dropped = 0; - - nstats->multicast = - bnx2x_hilo(&estats->total_multicast_packets_received_hi); - - nstats->collisions = - bnx2x_hilo(&estats->tx_stat_etherstatscollisions_hi); - - nstats->rx_length_errors = - bnx2x_hilo(&estats->rx_stat_etherstatsundersizepkts_hi) + - bnx2x_hilo(&estats->etherstatsoverrsizepkts_hi); - nstats->rx_over_errors = bnx2x_hilo(&estats->brb_drop_hi) + - bnx2x_hilo(&estats->brb_truncate_hi); - nstats->rx_crc_errors = - bnx2x_hilo(&estats->rx_stat_dot3statsfcserrors_hi); - nstats->rx_frame_errors = - bnx2x_hilo(&estats->rx_stat_dot3statsalignmenterrors_hi); - nstats->rx_fifo_errors = bnx2x_hilo(&estats->no_buff_discard_hi); - nstats->rx_missed_errors = estats->xxoverflow_discard; - - nstats->rx_errors = nstats->rx_length_errors + - nstats->rx_over_errors + - nstats->rx_crc_errors + - nstats->rx_frame_errors + - nstats->rx_fifo_errors + - nstats->rx_missed_errors; - - nstats->tx_aborted_errors = - bnx2x_hilo(&estats->tx_stat_dot3statslatecollisions_hi) + - bnx2x_hilo(&estats->tx_stat_dot3statsexcessivecollisions_hi); - nstats->tx_carrier_errors = - bnx2x_hilo(&estats->rx_stat_dot3statscarriersenseerrors_hi); - nstats->tx_fifo_errors = 0; - nstats->tx_heartbeat_errors = 0; - nstats->tx_window_errors = 0; - - nstats->tx_errors = nstats->tx_aborted_errors + - nstats->tx_carrier_errors + - bnx2x_hilo(&estats->tx_stat_dot3statsinternalmactransmiterrors_hi); -} - -static void bnx2x_drv_stats_update(struct bnx2x *bp) -{ - struct bnx2x_eth_stats *estats = &bp->eth_stats; - int i; - - estats->driver_xoff = 0; - estats->rx_err_discard_pkt = 0; - estats->rx_skb_alloc_failed = 0; - estats->hw_csum_err = 0; - for_each_queue(bp, i) { - struct bnx2x_eth_q_stats *qstats = &bp->fp[i].eth_q_stats; - - estats->driver_xoff += qstats->driver_xoff; - estats->rx_err_discard_pkt += qstats->rx_err_discard_pkt; - estats->rx_skb_alloc_failed += qstats->rx_skb_alloc_failed; - estats->hw_csum_err += qstats->hw_csum_err; - } -} - -static void bnx2x_stats_update(struct bnx2x *bp) -{ - u32 *stats_comp = bnx2x_sp(bp, stats_comp); - - if (*stats_comp != DMAE_COMP_VAL) - return; - - if (bp->port.pmf) - bnx2x_hw_stats_update(bp); - - if (bnx2x_storm_stats_update(bp) && (bp->stats_pending++ == 3)) { - BNX2X_ERR("storm stats were not updated for 3 times\n"); - bnx2x_panic(); - return; - } - - bnx2x_net_stats_update(bp); - bnx2x_drv_stats_update(bp); - - if (netif_msg_timer(bp)) { - struct bnx2x_eth_stats *estats = &bp->eth_stats; - int i; - - printk(KERN_DEBUG "%s: brb drops %u brb truncate %u\n", - bp->dev->name, - estats->brb_drop_lo, estats->brb_truncate_lo); - - for_each_queue(bp, i) { - struct bnx2x_fastpath *fp = &bp->fp[i]; - struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats; - - printk(KERN_DEBUG "%s: rx usage(%4u) *rx_cons_sb(%u)" - " rx pkt(%lu) rx calls(%lu %lu)\n", - fp->name, (le16_to_cpu(*fp->rx_cons_sb) - - fp->rx_comp_cons), - le16_to_cpu(*fp->rx_cons_sb), - bnx2x_hilo(&qstats-> - total_unicast_packets_received_hi), - fp->rx_calls, fp->rx_pkt); - } - - for_each_queue(bp, i) { - struct bnx2x_fastpath *fp = &bp->fp[i]; - struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats; - struct netdev_queue *txq = - netdev_get_tx_queue(bp->dev, i); - - printk(KERN_DEBUG "%s: tx avail(%4u) *tx_cons_sb(%u)" - " tx pkt(%lu) tx calls (%lu)" - " %s (Xoff events %u)\n", - fp->name, bnx2x_tx_avail(fp), - le16_to_cpu(*fp->tx_cons_sb), - bnx2x_hilo(&qstats-> - total_unicast_packets_transmitted_hi), - fp->tx_pkt, - (netif_tx_queue_stopped(txq) ? "Xoff" : "Xon"), - qstats->driver_xoff); - } - } - - bnx2x_hw_stats_post(bp); - bnx2x_storm_stats_post(bp); -} - -static void bnx2x_port_stats_stop(struct bnx2x *bp) -{ - struct dmae_command *dmae; - u32 opcode; - int loader_idx = PMF_DMAE_C(bp); - u32 *stats_comp = bnx2x_sp(bp, stats_comp); - - bp->executer_idx = 0; - - opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC | - DMAE_CMD_C_ENABLE | - DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET | -#ifdef __BIG_ENDIAN - DMAE_CMD_ENDIANITY_B_DW_SWAP | -#else - DMAE_CMD_ENDIANITY_DW_SWAP | -#endif - (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) | - (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT)); - - if (bp->port.port_stx) { - - dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); - if (bp->func_stx) - dmae->opcode = (opcode | DMAE_CMD_C_DST_GRC); - else - dmae->opcode = (opcode | DMAE_CMD_C_DST_PCI); - dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats)); - dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats)); - dmae->dst_addr_lo = bp->port.port_stx >> 2; - dmae->dst_addr_hi = 0; - dmae->len = sizeof(struct host_port_stats) >> 2; - if (bp->func_stx) { - dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; - dmae->comp_addr_hi = 0; - dmae->comp_val = 1; - } else { - dmae->comp_addr_lo = - U64_LO(bnx2x_sp_mapping(bp, stats_comp)); - dmae->comp_addr_hi = - U64_HI(bnx2x_sp_mapping(bp, stats_comp)); - dmae->comp_val = DMAE_COMP_VAL; - - *stats_comp = 0; - } - } - - if (bp->func_stx) { - - dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); - dmae->opcode = (opcode | DMAE_CMD_C_DST_PCI); - dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, func_stats)); - dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, func_stats)); - dmae->dst_addr_lo = bp->func_stx >> 2; - dmae->dst_addr_hi = 0; - dmae->len = sizeof(struct host_func_stats) >> 2; - dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp)); - dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp)); - dmae->comp_val = DMAE_COMP_VAL; - - *stats_comp = 0; - } -} - -static void bnx2x_stats_stop(struct bnx2x *bp) -{ - int update = 0; - - bnx2x_stats_comp(bp); - - if (bp->port.pmf) - update = (bnx2x_hw_stats_update(bp) == 0); - - update |= (bnx2x_storm_stats_update(bp) == 0); - - if (update) { - bnx2x_net_stats_update(bp); - - if (bp->port.pmf) - bnx2x_port_stats_stop(bp); - - bnx2x_hw_stats_post(bp); - bnx2x_stats_comp(bp); - } -} - -static void bnx2x_stats_do_nothing(struct bnx2x *bp) -{ -} - -static const struct { - void (*action)(struct bnx2x *bp); - enum bnx2x_stats_state next_state; -} bnx2x_stats_stm[STATS_STATE_MAX][STATS_EVENT_MAX] = { -/* state event */ -{ -/* DISABLED PMF */ {bnx2x_stats_pmf_update, STATS_STATE_DISABLED}, -/* LINK_UP */ {bnx2x_stats_start, STATS_STATE_ENABLED}, -/* UPDATE */ {bnx2x_stats_do_nothing, STATS_STATE_DISABLED}, -/* STOP */ {bnx2x_stats_do_nothing, STATS_STATE_DISABLED} -}, -{ -/* ENABLED PMF */ {bnx2x_stats_pmf_start, STATS_STATE_ENABLED}, -/* LINK_UP */ {bnx2x_stats_restart, STATS_STATE_ENABLED}, -/* UPDATE */ {bnx2x_stats_update, STATS_STATE_ENABLED}, -/* STOP */ {bnx2x_stats_stop, STATS_STATE_DISABLED} -} -}; - -static void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event) -{ - enum bnx2x_stats_state state = bp->stats_state; - - if (unlikely(bp->panic)) - return; - - bnx2x_stats_stm[state][event].action(bp); - bp->stats_state = bnx2x_stats_stm[state][event].next_state; - - /* Make sure the state has been "changed" */ - smp_wmb(); - - if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp)) - DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n", - state, event, bp->stats_state); -} - -static void bnx2x_port_stats_base_init(struct bnx2x *bp) -{ - struct dmae_command *dmae; - u32 *stats_comp = bnx2x_sp(bp, stats_comp); - - /* sanity */ - if (!bp->port.pmf || !bp->port.port_stx) { - BNX2X_ERR("BUG!\n"); - return; - } - - bp->executer_idx = 0; - - dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); - dmae->opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC | - DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE | - DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET | -#ifdef __BIG_ENDIAN - DMAE_CMD_ENDIANITY_B_DW_SWAP | -#else - DMAE_CMD_ENDIANITY_DW_SWAP | -#endif - (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) | - (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT)); - dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats)); - dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats)); - dmae->dst_addr_lo = bp->port.port_stx >> 2; - dmae->dst_addr_hi = 0; - dmae->len = sizeof(struct host_port_stats) >> 2; - dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp)); - dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp)); - dmae->comp_val = DMAE_COMP_VAL; - - *stats_comp = 0; - bnx2x_hw_stats_post(bp); - bnx2x_stats_comp(bp); -} - -static void bnx2x_func_stats_base_init(struct bnx2x *bp) -{ - int vn, vn_max = IS_E1HMF(bp) ? E1HVN_MAX : E1VN_MAX; - int port = BP_PORT(bp); - int func; - u32 func_stx; - - /* sanity */ - if (!bp->port.pmf || !bp->func_stx) { - BNX2X_ERR("BUG!\n"); - return; - } - - /* save our func_stx */ - func_stx = bp->func_stx; - - for (vn = VN_0; vn < vn_max; vn++) { - func = 2*vn + port; - - bp->func_stx = SHMEM_RD(bp, func_mb[func].fw_mb_param); - bnx2x_func_stats_init(bp); - bnx2x_hw_stats_post(bp); - bnx2x_stats_comp(bp); - } - - /* restore our func_stx */ - bp->func_stx = func_stx; -} - -static void bnx2x_func_stats_base_update(struct bnx2x *bp) -{ - struct dmae_command *dmae = &bp->stats_dmae; - u32 *stats_comp = bnx2x_sp(bp, stats_comp); - - /* sanity */ - if (!bp->func_stx) { - BNX2X_ERR("BUG!\n"); - return; - } - - bp->executer_idx = 0; - memset(dmae, 0, sizeof(struct dmae_command)); - - dmae->opcode = (DMAE_CMD_SRC_GRC | DMAE_CMD_DST_PCI | - DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE | - DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET | -#ifdef __BIG_ENDIAN - DMAE_CMD_ENDIANITY_B_DW_SWAP | -#else - DMAE_CMD_ENDIANITY_DW_SWAP | -#endif - (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) | - (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT)); - dmae->src_addr_lo = bp->func_stx >> 2; - dmae->src_addr_hi = 0; - dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, func_stats_base)); - dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, func_stats_base)); - dmae->len = sizeof(struct host_func_stats) >> 2; - dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp)); - dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp)); - dmae->comp_val = DMAE_COMP_VAL; - - *stats_comp = 0; - bnx2x_hw_stats_post(bp); - bnx2x_stats_comp(bp); -} - -static void bnx2x_stats_init(struct bnx2x *bp) -{ - int port = BP_PORT(bp); - int func = BP_FUNC(bp); - int i; - - bp->stats_pending = 0; - bp->executer_idx = 0; - bp->stats_counter = 0; - - /* port and func stats for management */ - if (!BP_NOMCP(bp)) { - bp->port.port_stx = SHMEM_RD(bp, port_mb[port].port_stx); - bp->func_stx = SHMEM_RD(bp, func_mb[func].fw_mb_param); - - } else { - bp->port.port_stx = 0; - bp->func_stx = 0; - } - DP(BNX2X_MSG_STATS, "port_stx 0x%x func_stx 0x%x\n", - bp->port.port_stx, bp->func_stx); - - /* port stats */ - memset(&(bp->port.old_nig_stats), 0, sizeof(struct nig_stats)); - bp->port.old_nig_stats.brb_discard = - REG_RD(bp, NIG_REG_STAT0_BRB_DISCARD + port*0x38); - bp->port.old_nig_stats.brb_truncate = - REG_RD(bp, NIG_REG_STAT0_BRB_TRUNCATE + port*0x38); - REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT0 + port*0x50, - &(bp->port.old_nig_stats.egress_mac_pkt0_lo), 2); - REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT1 + port*0x50, - &(bp->port.old_nig_stats.egress_mac_pkt1_lo), 2); - - /* function stats */ - for_each_queue(bp, i) { - struct bnx2x_fastpath *fp = &bp->fp[i]; - - memset(&fp->old_tclient, 0, - sizeof(struct tstorm_per_client_stats)); - memset(&fp->old_uclient, 0, - sizeof(struct ustorm_per_client_stats)); - memset(&fp->old_xclient, 0, - sizeof(struct xstorm_per_client_stats)); - memset(&fp->eth_q_stats, 0, sizeof(struct bnx2x_eth_q_stats)); - } - - memset(&bp->dev->stats, 0, sizeof(struct net_device_stats)); - memset(&bp->eth_stats, 0, sizeof(struct bnx2x_eth_stats)); - - bp->stats_state = STATS_STATE_DISABLED; - - if (bp->port.pmf) { - if (bp->port.port_stx) - bnx2x_port_stats_base_init(bp); - - if (bp->func_stx) - bnx2x_func_stats_base_init(bp); - - } else if (bp->func_stx) - bnx2x_func_stats_base_update(bp); -} - static void bnx2x_timer(unsigned long data) { struct bnx2x *bp = (struct bnx2x *) data; @@ -5116,7 +2722,7 @@ static void bnx2x_zero_sb(struct bnx2x *bp, int sb_id) CSTORM_SB_STATUS_BLOCK_C_SIZE / 4); } -static void bnx2x_init_sb(struct bnx2x *bp, struct host_status_block *sb, +void bnx2x_init_sb(struct bnx2x *bp, struct host_status_block *sb, dma_addr_t mapping, int sb_id) { int port = BP_PORT(bp); @@ -5295,7 +2901,7 @@ static void bnx2x_init_def_sb(struct bnx2x *bp, bnx2x_ack_sb(bp, sb_id, CSTORM_ID, 0, IGU_INT_ENABLE, 0); } -static void bnx2x_update_coalesce(struct bnx2x *bp) +void bnx2x_update_coalesce(struct bnx2x *bp) { int port = BP_PORT(bp); int i; @@ -5325,207 +2931,6 @@ static void bnx2x_update_coalesce(struct bnx2x *bp) } } -static inline void bnx2x_free_tpa_pool(struct bnx2x *bp, - struct bnx2x_fastpath *fp, int last) -{ - int i; - - for (i = 0; i < last; i++) { - struct sw_rx_bd *rx_buf = &(fp->tpa_pool[i]); - struct sk_buff *skb = rx_buf->skb; - - if (skb == NULL) { - DP(NETIF_MSG_IFDOWN, "tpa bin %d empty on free\n", i); - continue; - } - - if (fp->tpa_state[i] == BNX2X_TPA_START) - dma_unmap_single(&bp->pdev->dev, - dma_unmap_addr(rx_buf, mapping), - bp->rx_buf_size, DMA_FROM_DEVICE); - - dev_kfree_skb(skb); - rx_buf->skb = NULL; - } -} - -static void bnx2x_init_rx_rings(struct bnx2x *bp) -{ - int func = BP_FUNC(bp); - int max_agg_queues = CHIP_IS_E1(bp) ? ETH_MAX_AGGREGATION_QUEUES_E1 : - ETH_MAX_AGGREGATION_QUEUES_E1H; - u16 ring_prod, cqe_ring_prod; - int i, j; - - bp->rx_buf_size = bp->dev->mtu + ETH_OVREHEAD + BNX2X_RX_ALIGN; - DP(NETIF_MSG_IFUP, - "mtu %d rx_buf_size %d\n", bp->dev->mtu, bp->rx_buf_size); - - if (bp->flags & TPA_ENABLE_FLAG) { - - for_each_queue(bp, j) { - struct bnx2x_fastpath *fp = &bp->fp[j]; - - for (i = 0; i < max_agg_queues; i++) { - fp->tpa_pool[i].skb = - netdev_alloc_skb(bp->dev, bp->rx_buf_size); - if (!fp->tpa_pool[i].skb) { - BNX2X_ERR("Failed to allocate TPA " - "skb pool for queue[%d] - " - "disabling TPA on this " - "queue!\n", j); - bnx2x_free_tpa_pool(bp, fp, i); - fp->disable_tpa = 1; - break; - } - dma_unmap_addr_set((struct sw_rx_bd *) - &bp->fp->tpa_pool[i], - mapping, 0); - fp->tpa_state[i] = BNX2X_TPA_STOP; - } - } - } - - for_each_queue(bp, j) { - struct bnx2x_fastpath *fp = &bp->fp[j]; - - fp->rx_bd_cons = 0; - fp->rx_cons_sb = BNX2X_RX_SB_INDEX; - fp->rx_bd_cons_sb = BNX2X_RX_SB_BD_INDEX; - - /* "next page" elements initialization */ - /* SGE ring */ - for (i = 1; i <= NUM_RX_SGE_PAGES; i++) { - struct eth_rx_sge *sge; - - sge = &fp->rx_sge_ring[RX_SGE_CNT * i - 2]; - sge->addr_hi = - cpu_to_le32(U64_HI(fp->rx_sge_mapping + - BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES))); - sge->addr_lo = - cpu_to_le32(U64_LO(fp->rx_sge_mapping + - BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES))); - } - - bnx2x_init_sge_ring_bit_mask(fp); - - /* RX BD ring */ - for (i = 1; i <= NUM_RX_RINGS; i++) { - struct eth_rx_bd *rx_bd; - - rx_bd = &fp->rx_desc_ring[RX_DESC_CNT * i - 2]; - rx_bd->addr_hi = - cpu_to_le32(U64_HI(fp->rx_desc_mapping + - BCM_PAGE_SIZE*(i % NUM_RX_RINGS))); - rx_bd->addr_lo = - cpu_to_le32(U64_LO(fp->rx_desc_mapping + - BCM_PAGE_SIZE*(i % NUM_RX_RINGS))); - } - - /* CQ ring */ - for (i = 1; i <= NUM_RCQ_RINGS; i++) { - struct eth_rx_cqe_next_page *nextpg; - - nextpg = (struct eth_rx_cqe_next_page *) - &fp->rx_comp_ring[RCQ_DESC_CNT * i - 1]; - nextpg->addr_hi = - cpu_to_le32(U64_HI(fp->rx_comp_mapping + - BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS))); - nextpg->addr_lo = - cpu_to_le32(U64_LO(fp->rx_comp_mapping + - BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS))); - } - - /* Allocate SGEs and initialize the ring elements */ - for (i = 0, ring_prod = 0; - i < MAX_RX_SGE_CNT*NUM_RX_SGE_PAGES; i++) { - - if (bnx2x_alloc_rx_sge(bp, fp, ring_prod) < 0) { - BNX2X_ERR("was only able to allocate " - "%d rx sges\n", i); - BNX2X_ERR("disabling TPA for queue[%d]\n", j); - /* Cleanup already allocated elements */ - bnx2x_free_rx_sge_range(bp, fp, ring_prod); - bnx2x_free_tpa_pool(bp, fp, max_agg_queues); - fp->disable_tpa = 1; - ring_prod = 0; - break; - } - ring_prod = NEXT_SGE_IDX(ring_prod); - } - fp->rx_sge_prod = ring_prod; - - /* Allocate BDs and initialize BD ring */ - fp->rx_comp_cons = 0; - cqe_ring_prod = ring_prod = 0; - for (i = 0; i < bp->rx_ring_size; i++) { - if (bnx2x_alloc_rx_skb(bp, fp, ring_prod) < 0) { - BNX2X_ERR("was only able to allocate " - "%d rx skbs on queue[%d]\n", i, j); - fp->eth_q_stats.rx_skb_alloc_failed++; - break; - } - ring_prod = NEXT_RX_IDX(ring_prod); - cqe_ring_prod = NEXT_RCQ_IDX(cqe_ring_prod); - WARN_ON(ring_prod <= i); - } - - fp->rx_bd_prod = ring_prod; - /* must not have more available CQEs than BDs */ - fp->rx_comp_prod = min_t(u16, NUM_RCQ_RINGS*RCQ_DESC_CNT, - cqe_ring_prod); - fp->rx_pkt = fp->rx_calls = 0; - - /* Warning! - * this will generate an interrupt (to the TSTORM) - * must only be done after chip is initialized - */ - bnx2x_update_rx_prod(bp, fp, ring_prod, fp->rx_comp_prod, - fp->rx_sge_prod); - if (j != 0) - continue; - - REG_WR(bp, BAR_USTRORM_INTMEM + - USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func), - U64_LO(fp->rx_comp_mapping)); - REG_WR(bp, BAR_USTRORM_INTMEM + - USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func) + 4, - U64_HI(fp->rx_comp_mapping)); - } -} - -static void bnx2x_init_tx_ring(struct bnx2x *bp) -{ - int i, j; - - for_each_queue(bp, j) { - struct bnx2x_fastpath *fp = &bp->fp[j]; - - for (i = 1; i <= NUM_TX_RINGS; i++) { - struct eth_tx_next_bd *tx_next_bd = - &fp->tx_desc_ring[TX_DESC_CNT * i - 1].next_bd; - - tx_next_bd->addr_hi = - cpu_to_le32(U64_HI(fp->tx_desc_mapping + - BCM_PAGE_SIZE*(i % NUM_TX_RINGS))); - tx_next_bd->addr_lo = - cpu_to_le32(U64_LO(fp->tx_desc_mapping + - BCM_PAGE_SIZE*(i % NUM_TX_RINGS))); - } - - fp->tx_db.data.header.header = DOORBELL_HDR_DB_TYPE; - fp->tx_db.data.zero_fill1 = 0; - fp->tx_db.data.prod = 0; - - fp->tx_pkt_prod = 0; - fp->tx_pkt_cons = 0; - fp->tx_bd_prod = 0; - fp->tx_bd_cons = 0; - fp->tx_cons_sb = BNX2X_TX_SB_INDEX; - fp->tx_pkt = 0; - } -} - static void bnx2x_init_sp_ring(struct bnx2x *bp) { int func = BP_FUNC(bp); @@ -5640,7 +3045,7 @@ static void bnx2x_init_ind_table(struct bnx2x *bp) bp->fp->cl_id + (i % bp->num_queues)); } -static void bnx2x_set_client_config(struct bnx2x *bp) +void bnx2x_set_client_config(struct bnx2x *bp) { struct tstorm_eth_client_config tstorm_client = {0}; int port = BP_PORT(bp); @@ -5673,7 +3078,7 @@ static void bnx2x_set_client_config(struct bnx2x *bp) ((u32 *)&tstorm_client)[0], ((u32 *)&tstorm_client)[1]); } -static void bnx2x_set_storm_rx_mode(struct bnx2x *bp) +void bnx2x_set_storm_rx_mode(struct bnx2x *bp) { struct tstorm_eth_mac_filter_config tstorm_mac_filter = {0}; int mode = bp->rx_mode; @@ -5993,7 +3398,7 @@ static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code) } } -static void bnx2x_nic_init(struct bnx2x *bp, u32 load_code) +void bnx2x_nic_init(struct bnx2x *bp, u32 load_code) { int i; @@ -7074,7 +4479,7 @@ static int bnx2x_init_func(struct bnx2x *bp) return 0; } -static int bnx2x_init_hw(struct bnx2x *bp, u32 load_code) +int bnx2x_init_hw(struct bnx2x *bp, u32 load_code) { int i, rc = 0; @@ -7136,7 +4541,7 @@ init_hw_err: return rc; } -static void bnx2x_free_mem(struct bnx2x *bp) +void bnx2x_free_mem(struct bnx2x *bp) { #define BNX2X_PCI_FREE(x, y, size) \ @@ -7218,7 +4623,7 @@ static void bnx2x_free_mem(struct bnx2x *bp) #undef BNX2X_KFREE } -static int bnx2x_alloc_mem(struct bnx2x *bp) +int bnx2x_alloc_mem(struct bnx2x *bp) { #define BNX2X_PCI_ALLOC(x, y, size) \ @@ -7324,264 +4729,6 @@ alloc_mem_err: #undef BNX2X_ALLOC } -static void bnx2x_free_tx_skbs(struct bnx2x *bp) -{ - int i; - - for_each_queue(bp, i) { - struct bnx2x_fastpath *fp = &bp->fp[i]; - - u16 bd_cons = fp->tx_bd_cons; - u16 sw_prod = fp->tx_pkt_prod; - u16 sw_cons = fp->tx_pkt_cons; - - while (sw_cons != sw_prod) { - bd_cons = bnx2x_free_tx_pkt(bp, fp, TX_BD(sw_cons)); - sw_cons++; - } - } -} - -static void bnx2x_free_rx_skbs(struct bnx2x *bp) -{ - int i, j; - - for_each_queue(bp, j) { - struct bnx2x_fastpath *fp = &bp->fp[j]; - - for (i = 0; i < NUM_RX_BD; i++) { - struct sw_rx_bd *rx_buf = &fp->rx_buf_ring[i]; - struct sk_buff *skb = rx_buf->skb; - - if (skb == NULL) - continue; - - dma_unmap_single(&bp->pdev->dev, - dma_unmap_addr(rx_buf, mapping), - bp->rx_buf_size, DMA_FROM_DEVICE); - - rx_buf->skb = NULL; - dev_kfree_skb(skb); - } - if (!fp->disable_tpa) - bnx2x_free_tpa_pool(bp, fp, CHIP_IS_E1(bp) ? - ETH_MAX_AGGREGATION_QUEUES_E1 : - ETH_MAX_AGGREGATION_QUEUES_E1H); - } -} - -static void bnx2x_free_skbs(struct bnx2x *bp) -{ - bnx2x_free_tx_skbs(bp); - bnx2x_free_rx_skbs(bp); -} - -static void bnx2x_free_msix_irqs(struct bnx2x *bp) -{ - int i, offset = 1; - - free_irq(bp->msix_table[0].vector, bp->dev); - DP(NETIF_MSG_IFDOWN, "released sp irq (%d)\n", - bp->msix_table[0].vector); - -#ifdef BCM_CNIC - offset++; -#endif - for_each_queue(bp, i) { - DP(NETIF_MSG_IFDOWN, "about to release fp #%d->%d irq " - "state %x\n", i, bp->msix_table[i + offset].vector, - bnx2x_fp(bp, i, state)); - - free_irq(bp->msix_table[i + offset].vector, &bp->fp[i]); - } -} - -static void bnx2x_free_irq(struct bnx2x *bp, bool disable_only) -{ - if (bp->flags & USING_MSIX_FLAG) { - if (!disable_only) - bnx2x_free_msix_irqs(bp); - pci_disable_msix(bp->pdev); - bp->flags &= ~USING_MSIX_FLAG; - - } else if (bp->flags & USING_MSI_FLAG) { - if (!disable_only) - free_irq(bp->pdev->irq, bp->dev); - pci_disable_msi(bp->pdev); - bp->flags &= ~USING_MSI_FLAG; - - } else if (!disable_only) - free_irq(bp->pdev->irq, bp->dev); -} - -static int bnx2x_enable_msix(struct bnx2x *bp) -{ - int i, rc, offset = 1; - int igu_vec = 0; - - bp->msix_table[0].entry = igu_vec; - DP(NETIF_MSG_IFUP, "msix_table[0].entry = %d (slowpath)\n", igu_vec); - -#ifdef BCM_CNIC - igu_vec = BP_L_ID(bp) + offset; - bp->msix_table[1].entry = igu_vec; - DP(NETIF_MSG_IFUP, "msix_table[1].entry = %d (CNIC)\n", igu_vec); - offset++; -#endif - for_each_queue(bp, i) { - igu_vec = BP_L_ID(bp) + offset + i; - bp->msix_table[i + offset].entry = igu_vec; - DP(NETIF_MSG_IFUP, "msix_table[%d].entry = %d " - "(fastpath #%u)\n", i + offset, igu_vec, i); - } - - rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], - BNX2X_NUM_QUEUES(bp) + offset); - - /* - * reconfigure number of tx/rx queues according to available - * MSI-X vectors - */ - if (rc >= BNX2X_MIN_MSIX_VEC_CNT) { - /* vectors available for FP */ - int fp_vec = rc - BNX2X_MSIX_VEC_FP_START; - - DP(NETIF_MSG_IFUP, - "Trying to use less MSI-X vectors: %d\n", rc); - - rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], rc); - - if (rc) { - DP(NETIF_MSG_IFUP, - "MSI-X is not attainable rc %d\n", rc); - return rc; - } - - bp->num_queues = min(bp->num_queues, fp_vec); - - DP(NETIF_MSG_IFUP, "New queue configuration set: %d\n", - bp->num_queues); - } else if (rc) { - DP(NETIF_MSG_IFUP, "MSI-X is not attainable rc %d\n", rc); - return rc; - } - - bp->flags |= USING_MSIX_FLAG; - - return 0; -} - -static int bnx2x_req_msix_irqs(struct bnx2x *bp) -{ - int i, rc, offset = 1; - - rc = request_irq(bp->msix_table[0].vector, bnx2x_msix_sp_int, 0, - bp->dev->name, bp->dev); - if (rc) { - BNX2X_ERR("request sp irq failed\n"); - return -EBUSY; - } - -#ifdef BCM_CNIC - offset++; -#endif - for_each_queue(bp, i) { - struct bnx2x_fastpath *fp = &bp->fp[i]; - snprintf(fp->name, sizeof(fp->name), "%s-fp-%d", - bp->dev->name, i); - - rc = request_irq(bp->msix_table[i + offset].vector, - bnx2x_msix_fp_int, 0, fp->name, fp); - if (rc) { - BNX2X_ERR("request fp #%d irq failed rc %d\n", i, rc); - bnx2x_free_msix_irqs(bp); - return -EBUSY; - } - - fp->state = BNX2X_FP_STATE_IRQ; - } - - i = BNX2X_NUM_QUEUES(bp); - netdev_info(bp->dev, "using MSI-X IRQs: sp %d fp[%d] %d" - " ... fp[%d] %d\n", - bp->msix_table[0].vector, - 0, bp->msix_table[offset].vector, - i - 1, bp->msix_table[offset + i - 1].vector); - - return 0; -} - -static int bnx2x_enable_msi(struct bnx2x *bp) -{ - int rc; - - rc = pci_enable_msi(bp->pdev); - if (rc) { - DP(NETIF_MSG_IFUP, "MSI is not attainable\n"); - return -1; - } - bp->flags |= USING_MSI_FLAG; - - return 0; -} - -static int bnx2x_req_irq(struct bnx2x *bp) -{ - unsigned long flags; - int rc; - - if (bp->flags & USING_MSI_FLAG) - flags = 0; - else - flags = IRQF_SHARED; - - rc = request_irq(bp->pdev->irq, bnx2x_interrupt, flags, - bp->dev->name, bp->dev); - if (!rc) - bnx2x_fp(bp, 0, state) = BNX2X_FP_STATE_IRQ; - - return rc; -} - -static void bnx2x_napi_enable(struct bnx2x *bp) -{ - int i; - - for_each_queue(bp, i) - napi_enable(&bnx2x_fp(bp, i, napi)); -} - -static void bnx2x_napi_disable(struct bnx2x *bp) -{ - int i; - - for_each_queue(bp, i) - napi_disable(&bnx2x_fp(bp, i, napi)); -} - -static void bnx2x_netif_start(struct bnx2x *bp) -{ - int intr_sem; - - intr_sem = atomic_dec_and_test(&bp->intr_sem); - smp_wmb(); /* Ensure that bp->intr_sem update is SMP-safe */ - - if (intr_sem) { - if (netif_running(bp->dev)) { - bnx2x_napi_enable(bp); - bnx2x_int_enable(bp); - if (bp->state == BNX2X_STATE_OPEN) - netif_tx_wake_all_queues(bp->dev); - } - } -} - -static void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw) -{ - bnx2x_int_disable_sync(bp, disable_hw); - bnx2x_napi_disable(bp); - netif_tx_disable(bp->dev); -} /* * Init service functions @@ -7752,7 +4899,7 @@ static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx, return -EBUSY; } -static void bnx2x_set_eth_mac_addr_e1h(struct bnx2x *bp, int set) +void bnx2x_set_eth_mac_addr_e1h(struct bnx2x *bp, int set) { bp->set_mac_pending++; smp_wmb(); @@ -7764,7 +4911,7 @@ static void bnx2x_set_eth_mac_addr_e1h(struct bnx2x *bp, int set) bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending, set ? 0 : 1); } -static void bnx2x_set_eth_mac_addr_e1(struct bnx2x *bp, int set) +void bnx2x_set_eth_mac_addr_e1(struct bnx2x *bp, int set) { bp->set_mac_pending++; smp_wmb(); @@ -7788,7 +4935,7 @@ static void bnx2x_set_eth_mac_addr_e1(struct bnx2x *bp, int set) * * @return 0 if cussess, -ENODEV if ramrod doesn't return. */ -static int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set) +int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set) { u32 cl_bit_vec = (1 << BCM_ISCSI_ETH_CL_ID); @@ -7815,7 +4962,7 @@ static int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set) } #endif -static int bnx2x_setup_leading(struct bnx2x *bp) +int bnx2x_setup_leading(struct bnx2x *bp) { int rc; @@ -7831,7 +4978,7 @@ static int bnx2x_setup_leading(struct bnx2x *bp) return rc; } -static int bnx2x_setup_multi(struct bnx2x *bp, int index) +int bnx2x_setup_multi(struct bnx2x *bp, int index) { struct bnx2x_fastpath *fp = &bp->fp[index]; @@ -7848,9 +4995,8 @@ static int bnx2x_setup_multi(struct bnx2x *bp, int index) &(fp->state), 0); } -static int bnx2x_poll(struct napi_struct *napi, int budget); -static void bnx2x_set_num_queues_msix(struct bnx2x *bp) +void bnx2x_set_num_queues_msix(struct bnx2x *bp) { switch (bp->multi_mode) { @@ -7874,292 +5020,7 @@ static void bnx2x_set_num_queues_msix(struct bnx2x *bp) } } -static int bnx2x_set_num_queues(struct bnx2x *bp) -{ - int rc = 0; - - switch (int_mode) { - case INT_MODE_INTx: - case INT_MODE_MSI: - bp->num_queues = 1; - DP(NETIF_MSG_IFUP, "set number of queues to 1\n"); - break; - default: - /* Set number of queues according to bp->multi_mode value */ - bnx2x_set_num_queues_msix(bp); - - DP(NETIF_MSG_IFUP, "set number of queues to %d\n", - bp->num_queues); - - /* if we can't use MSI-X we only need one fp, - * so try to enable MSI-X with the requested number of fp's - * and fallback to MSI or legacy INTx with one fp - */ - rc = bnx2x_enable_msix(bp); - if (rc) - /* failed to enable MSI-X */ - bp->num_queues = 1; - break; - } - bp->dev->real_num_tx_queues = bp->num_queues; - return rc; -} - -#ifdef BCM_CNIC -static int bnx2x_cnic_notify(struct bnx2x *bp, int cmd); -static void bnx2x_setup_cnic_irq_info(struct bnx2x *bp); -#endif - -/* must be called with rtnl_lock */ -static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) -{ - u32 load_code; - int i, rc; - -#ifdef BNX2X_STOP_ON_ERROR - if (unlikely(bp->panic)) - return -EPERM; -#endif - - bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD; - - rc = bnx2x_set_num_queues(bp); - - if (bnx2x_alloc_mem(bp)) { - bnx2x_free_irq(bp, true); - return -ENOMEM; - } - - for_each_queue(bp, i) - bnx2x_fp(bp, i, disable_tpa) = - ((bp->flags & TPA_ENABLE_FLAG) == 0); - - for_each_queue(bp, i) - netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi), - bnx2x_poll, 128); - bnx2x_napi_enable(bp); - - if (bp->flags & USING_MSIX_FLAG) { - rc = bnx2x_req_msix_irqs(bp); - if (rc) { - bnx2x_free_irq(bp, true); - goto load_error1; - } - } else { - /* Fall to INTx if failed to enable MSI-X due to lack of - memory (in bnx2x_set_num_queues()) */ - if ((rc != -ENOMEM) && (int_mode != INT_MODE_INTx)) - bnx2x_enable_msi(bp); - bnx2x_ack_int(bp); - rc = bnx2x_req_irq(bp); - if (rc) { - BNX2X_ERR("IRQ request failed rc %d, aborting\n", rc); - bnx2x_free_irq(bp, true); - goto load_error1; - } - if (bp->flags & USING_MSI_FLAG) { - bp->dev->irq = bp->pdev->irq; - netdev_info(bp->dev, "using MSI IRQ %d\n", - bp->pdev->irq); - } - } - - /* Send LOAD_REQUEST command to MCP - Returns the type of LOAD command: - if it is the first port to be initialized - common blocks should be initialized, otherwise - not - */ - if (!BP_NOMCP(bp)) { - load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ); - if (!load_code) { - BNX2X_ERR("MCP response failure, aborting\n"); - rc = -EBUSY; - goto load_error2; - } - if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED) { - rc = -EBUSY; /* other port in diagnostic mode */ - goto load_error2; - } - - } else { - int port = BP_PORT(bp); - - DP(NETIF_MSG_IFUP, "NO MCP - load counts %d, %d, %d\n", - load_count[0], load_count[1], load_count[2]); - load_count[0]++; - load_count[1 + port]++; - DP(NETIF_MSG_IFUP, "NO MCP - new load counts %d, %d, %d\n", - load_count[0], load_count[1], load_count[2]); - if (load_count[0] == 1) - load_code = FW_MSG_CODE_DRV_LOAD_COMMON; - else if (load_count[1 + port] == 1) - load_code = FW_MSG_CODE_DRV_LOAD_PORT; - else - load_code = FW_MSG_CODE_DRV_LOAD_FUNCTION; - } - - if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) || - (load_code == FW_MSG_CODE_DRV_LOAD_PORT)) - bp->port.pmf = 1; - else - bp->port.pmf = 0; - DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf); - - /* Initialize HW */ - rc = bnx2x_init_hw(bp, load_code); - if (rc) { - BNX2X_ERR("HW init failed, aborting\n"); - bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE); - bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP); - bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE); - goto load_error2; - } - - /* Setup NIC internals and enable interrupts */ - bnx2x_nic_init(bp, load_code); - - if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) && - (bp->common.shmem2_base)) - SHMEM2_WR(bp, dcc_support, - (SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV | - SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV)); - - /* Send LOAD_DONE command to MCP */ - if (!BP_NOMCP(bp)) { - load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE); - if (!load_code) { - BNX2X_ERR("MCP response failure, aborting\n"); - rc = -EBUSY; - goto load_error3; - } - } - - bp->state = BNX2X_STATE_OPENING_WAIT4_PORT; - - rc = bnx2x_setup_leading(bp); - if (rc) { - BNX2X_ERR("Setup leading failed!\n"); -#ifndef BNX2X_STOP_ON_ERROR - goto load_error3; -#else - bp->panic = 1; - return -EBUSY; -#endif - } - - if (CHIP_IS_E1H(bp)) - if (bp->mf_config & FUNC_MF_CFG_FUNC_DISABLED) { - DP(NETIF_MSG_IFUP, "mf_cfg function disabled\n"); - bp->flags |= MF_FUNC_DIS; - } - - if (bp->state == BNX2X_STATE_OPEN) { -#ifdef BCM_CNIC - /* Enable Timer scan */ - REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + BP_PORT(bp)*4, 1); -#endif - for_each_nondefault_queue(bp, i) { - rc = bnx2x_setup_multi(bp, i); - if (rc) -#ifdef BCM_CNIC - goto load_error4; -#else - goto load_error3; -#endif - } - - if (CHIP_IS_E1(bp)) - bnx2x_set_eth_mac_addr_e1(bp, 1); - else - bnx2x_set_eth_mac_addr_e1h(bp, 1); -#ifdef BCM_CNIC - /* Set iSCSI L2 MAC */ - mutex_lock(&bp->cnic_mutex); - if (bp->cnic_eth_dev.drv_state & CNIC_DRV_STATE_REGD) { - bnx2x_set_iscsi_eth_mac_addr(bp, 1); - bp->cnic_flags |= BNX2X_CNIC_FLAG_MAC_SET; - bnx2x_init_sb(bp, bp->cnic_sb, bp->cnic_sb_mapping, - CNIC_SB_ID(bp)); - } - mutex_unlock(&bp->cnic_mutex); -#endif - } - - if (bp->port.pmf) - bnx2x_initial_phy_init(bp, load_mode); - - /* Start fast path */ - switch (load_mode) { - case LOAD_NORMAL: - if (bp->state == BNX2X_STATE_OPEN) { - /* Tx queue should be only reenabled */ - netif_tx_wake_all_queues(bp->dev); - } - /* Initialize the receive filter. */ - bnx2x_set_rx_mode(bp->dev); - break; - - case LOAD_OPEN: - netif_tx_start_all_queues(bp->dev); - if (bp->state != BNX2X_STATE_OPEN) - netif_tx_disable(bp->dev); - /* Initialize the receive filter. */ - bnx2x_set_rx_mode(bp->dev); - break; - - case LOAD_DIAG: - /* Initialize the receive filter. */ - bnx2x_set_rx_mode(bp->dev); - bp->state = BNX2X_STATE_DIAG; - break; - - default: - break; - } - - if (!bp->port.pmf) - bnx2x__link_status_update(bp); - - /* start the timer */ - mod_timer(&bp->timer, jiffies + bp->current_interval); - -#ifdef BCM_CNIC - bnx2x_setup_cnic_irq_info(bp); - if (bp->state == BNX2X_STATE_OPEN) - bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD); -#endif - bnx2x_inc_load_cnt(bp); - - return 0; - -#ifdef BCM_CNIC -load_error4: - /* Disable Timer scan */ - REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + BP_PORT(bp)*4, 0); -#endif -load_error3: - bnx2x_int_disable_sync(bp, 1); - if (!BP_NOMCP(bp)) { - bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP); - bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE); - } - bp->port.pmf = 0; - /* Free SKBs, SGEs, TPA pool and driver internals */ - bnx2x_free_skbs(bp); - for_each_queue(bp, i) - bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); -load_error2: - /* Release IRQs */ - bnx2x_free_irq(bp, false); -load_error1: - bnx2x_napi_disable(bp); - for_each_queue(bp, i) - netif_napi_del(&bnx2x_fp(bp, i, napi)); - bnx2x_free_mem(bp); - - return rc; -} static int bnx2x_stop_multi(struct bnx2x *bp, int index) { @@ -8317,7 +5178,7 @@ static void bnx2x_reset_chip(struct bnx2x *bp, u32 reset_code) } } -static void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode) +void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode) { int port = BP_PORT(bp); u32 reset_code = 0; @@ -8465,7 +5326,7 @@ unload_error: } -static inline void bnx2x_disable_close_the_gate(struct bnx2x *bp) +void bnx2x_disable_close_the_gate(struct bnx2x *bp) { u32 val; @@ -8487,71 +5348,6 @@ static inline void bnx2x_disable_close_the_gate(struct bnx2x *bp) } } -/* must be called with rtnl_lock */ -static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) -{ - int i; - - if (bp->state == BNX2X_STATE_CLOSED) { - /* Interface has been removed - nothing to recover */ - bp->recovery_state = BNX2X_RECOVERY_DONE; - bp->is_leader = 0; - bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESERVED_08); - smp_wmb(); - - return -EINVAL; - } - -#ifdef BCM_CNIC - bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD); -#endif - bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT; - - /* Set "drop all" */ - bp->rx_mode = BNX2X_RX_MODE_NONE; - bnx2x_set_storm_rx_mode(bp); - - /* Disable HW interrupts, NAPI and Tx */ - bnx2x_netif_stop(bp, 1); - netif_carrier_off(bp->dev); - - del_timer_sync(&bp->timer); - SHMEM_WR(bp, func_mb[BP_FUNC(bp)].drv_pulse_mb, - (DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq)); - bnx2x_stats_handle(bp, STATS_EVENT_STOP); - - /* Release IRQs */ - bnx2x_free_irq(bp, false); - - /* Cleanup the chip if needed */ - if (unload_mode != UNLOAD_RECOVERY) - bnx2x_chip_cleanup(bp, unload_mode); - - bp->port.pmf = 0; - - /* Free SKBs, SGEs, TPA pool and driver internals */ - bnx2x_free_skbs(bp); - for_each_queue(bp, i) - bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); - for_each_queue(bp, i) - netif_napi_del(&bnx2x_fp(bp, i, napi)); - bnx2x_free_mem(bp); - - bp->state = BNX2X_STATE_CLOSED; - - /* The last driver must disable a "close the gate" if there is no - * parity attention or "process kill" pending. - */ - if ((!bnx2x_dec_load_cnt(bp)) && (!bnx2x_chk_parity_attn(bp)) && - bnx2x_reset_is_done(bp)) - bnx2x_disable_close_the_gate(bp); - - /* Reset MCP mail box sequence if there is on going recovery */ - if (unload_mode == UNLOAD_RECOVERY) - bp->fw_seq = 0; - - return 0; -} /* Close gates #2, #3 and #4: */ static void bnx2x_set_234_gates(struct bnx2x *bp, bool close) @@ -8864,8 +5660,6 @@ exit_leader_reset: return rc; } -static int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state); - /* Assumption: runs under rtnl lock. This together with the fact * that it's called only from bnx2x_reset_task() ensure that it * will never be called when netif_running(bp->dev) is false. @@ -9002,8 +5796,6 @@ reset_task_exit: /* end of nic load/unload */ -/* ethtool_ops */ - /* * Init service functions */ @@ -9922,6 +6714,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) mutex_init(&bp->port.phy_mutex); mutex_init(&bp->fw_mb_mutex); + spin_lock_init(&bp->stats_lock); #ifdef BCM_CNIC mutex_init(&bp->cnic_mutex); #endif @@ -9951,7 +6744,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) multi_mode = ETH_RSS_MODE_DISABLED; } bp->multi_mode = multi_mode; - + bp->int_mode = int_mode; bp->dev->features |= NETIF_F_GRO; @@ -9963,6 +6756,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) bp->flags |= TPA_ENABLE_FLAG; bp->dev->features |= NETIF_F_LRO; } + bp->disable_tpa = disable_tpa; if (CHIP_IS_E1(bp)) bp->dropless_fc = 0; @@ -9991,2547 +6785,11 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) return rc; } -/* - * ethtool service functions - */ - -/* All ethtool functions called with rtnl_lock */ - -static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct bnx2x *bp = netdev_priv(dev); - - cmd->supported = bp->port.supported; - cmd->advertising = bp->port.advertising; - - if ((bp->state == BNX2X_STATE_OPEN) && - !(bp->flags & MF_FUNC_DIS) && - (bp->link_vars.link_up)) { - cmd->speed = bp->link_vars.line_speed; - cmd->duplex = bp->link_vars.duplex; - if (IS_E1HMF(bp)) { - u16 vn_max_rate; - - vn_max_rate = - ((bp->mf_config & FUNC_MF_CFG_MAX_BW_MASK) >> - FUNC_MF_CFG_MAX_BW_SHIFT) * 100; - if (vn_max_rate < cmd->speed) - cmd->speed = vn_max_rate; - } - } else { - cmd->speed = -1; - cmd->duplex = -1; - } - - if (bp->link_params.switch_cfg == SWITCH_CFG_10G) { - u32 ext_phy_type = - XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config); - - switch (ext_phy_type) { - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727: - cmd->port = PORT_FIBRE; - break; - - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481: - cmd->port = PORT_TP; - break; - - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE: - BNX2X_ERR("XGXS PHY Failure detected 0x%x\n", - bp->link_params.ext_phy_config); - break; - - default: - DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n", - bp->link_params.ext_phy_config); - break; - } - } else - cmd->port = PORT_TP; - - cmd->phy_address = bp->mdio.prtad; - cmd->transceiver = XCVR_INTERNAL; - - if (bp->link_params.req_line_speed == SPEED_AUTO_NEG) - cmd->autoneg = AUTONEG_ENABLE; - else - cmd->autoneg = AUTONEG_DISABLE; - - cmd->maxtxpkt = 0; - cmd->maxrxpkt = 0; - - DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n" - DP_LEVEL " supported 0x%x advertising 0x%x speed %d\n" - DP_LEVEL " duplex %d port %d phy_address %d transceiver %d\n" - DP_LEVEL " autoneg %d maxtxpkt %d maxrxpkt %d\n", - cmd->cmd, cmd->supported, cmd->advertising, cmd->speed, - cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver, - cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt); - - return 0; -} - -static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct bnx2x *bp = netdev_priv(dev); - u32 advertising; - - if (IS_E1HMF(bp)) - return 0; - - DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n" - DP_LEVEL " supported 0x%x advertising 0x%x speed %d\n" - DP_LEVEL " duplex %d port %d phy_address %d transceiver %d\n" - DP_LEVEL " autoneg %d maxtxpkt %d maxrxpkt %d\n", - cmd->cmd, cmd->supported, cmd->advertising, cmd->speed, - cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver, - cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt); - - if (cmd->autoneg == AUTONEG_ENABLE) { - if (!(bp->port.supported & SUPPORTED_Autoneg)) { - DP(NETIF_MSG_LINK, "Autoneg not supported\n"); - return -EINVAL; - } - - /* advertise the requested speed and duplex if supported */ - cmd->advertising &= bp->port.supported; - - bp->link_params.req_line_speed = SPEED_AUTO_NEG; - bp->link_params.req_duplex = DUPLEX_FULL; - bp->port.advertising |= (ADVERTISED_Autoneg | - cmd->advertising); - - } else { /* forced speed */ - /* advertise the requested speed and duplex if supported */ - switch (cmd->speed) { - case SPEED_10: - if (cmd->duplex == DUPLEX_FULL) { - if (!(bp->port.supported & - SUPPORTED_10baseT_Full)) { - DP(NETIF_MSG_LINK, - "10M full not supported\n"); - return -EINVAL; - } - - advertising = (ADVERTISED_10baseT_Full | - ADVERTISED_TP); - } else { - if (!(bp->port.supported & - SUPPORTED_10baseT_Half)) { - DP(NETIF_MSG_LINK, - "10M half not supported\n"); - return -EINVAL; - } - - advertising = (ADVERTISED_10baseT_Half | - ADVERTISED_TP); - } - break; - - case SPEED_100: - if (cmd->duplex == DUPLEX_FULL) { - if (!(bp->port.supported & - SUPPORTED_100baseT_Full)) { - DP(NETIF_MSG_LINK, - "100M full not supported\n"); - return -EINVAL; - } - - advertising = (ADVERTISED_100baseT_Full | - ADVERTISED_TP); - } else { - if (!(bp->port.supported & - SUPPORTED_100baseT_Half)) { - DP(NETIF_MSG_LINK, - "100M half not supported\n"); - return -EINVAL; - } - - advertising = (ADVERTISED_100baseT_Half | - ADVERTISED_TP); - } - break; - - case SPEED_1000: - if (cmd->duplex != DUPLEX_FULL) { - DP(NETIF_MSG_LINK, "1G half not supported\n"); - return -EINVAL; - } - - if (!(bp->port.supported & SUPPORTED_1000baseT_Full)) { - DP(NETIF_MSG_LINK, "1G full not supported\n"); - return -EINVAL; - } - - advertising = (ADVERTISED_1000baseT_Full | - ADVERTISED_TP); - break; - - case SPEED_2500: - if (cmd->duplex != DUPLEX_FULL) { - DP(NETIF_MSG_LINK, - "2.5G half not supported\n"); - return -EINVAL; - } - - if (!(bp->port.supported & SUPPORTED_2500baseX_Full)) { - DP(NETIF_MSG_LINK, - "2.5G full not supported\n"); - return -EINVAL; - } - - advertising = (ADVERTISED_2500baseX_Full | - ADVERTISED_TP); - break; - - case SPEED_10000: - if (cmd->duplex != DUPLEX_FULL) { - DP(NETIF_MSG_LINK, "10G half not supported\n"); - return -EINVAL; - } - - if (!(bp->port.supported & SUPPORTED_10000baseT_Full)) { - DP(NETIF_MSG_LINK, "10G full not supported\n"); - return -EINVAL; - } - - advertising = (ADVERTISED_10000baseT_Full | - ADVERTISED_FIBRE); - break; - - default: - DP(NETIF_MSG_LINK, "Unsupported speed\n"); - return -EINVAL; - } - - bp->link_params.req_line_speed = cmd->speed; - bp->link_params.req_duplex = cmd->duplex; - bp->port.advertising = advertising; - } - - DP(NETIF_MSG_LINK, "req_line_speed %d\n" - DP_LEVEL " req_duplex %d advertising 0x%x\n", - bp->link_params.req_line_speed, bp->link_params.req_duplex, - bp->port.advertising); - - if (netif_running(dev)) { - bnx2x_stats_handle(bp, STATS_EVENT_STOP); - bnx2x_link_set(bp); - } - - return 0; -} - -#define IS_E1_ONLINE(info) (((info) & RI_E1_ONLINE) == RI_E1_ONLINE) -#define IS_E1H_ONLINE(info) (((info) & RI_E1H_ONLINE) == RI_E1H_ONLINE) - -static int bnx2x_get_regs_len(struct net_device *dev) -{ - struct bnx2x *bp = netdev_priv(dev); - int regdump_len = 0; - int i; - - if (CHIP_IS_E1(bp)) { - for (i = 0; i < REGS_COUNT; i++) - if (IS_E1_ONLINE(reg_addrs[i].info)) - regdump_len += reg_addrs[i].size; - - for (i = 0; i < WREGS_COUNT_E1; i++) - if (IS_E1_ONLINE(wreg_addrs_e1[i].info)) - regdump_len += wreg_addrs_e1[i].size * - (1 + wreg_addrs_e1[i].read_regs_count); - - } else { /* E1H */ - for (i = 0; i < REGS_COUNT; i++) - if (IS_E1H_ONLINE(reg_addrs[i].info)) - regdump_len += reg_addrs[i].size; - - for (i = 0; i < WREGS_COUNT_E1H; i++) - if (IS_E1H_ONLINE(wreg_addrs_e1h[i].info)) - regdump_len += wreg_addrs_e1h[i].size * - (1 + wreg_addrs_e1h[i].read_regs_count); - } - regdump_len *= 4; - regdump_len += sizeof(struct dump_hdr); - - return regdump_len; -} - -static void bnx2x_get_regs(struct net_device *dev, - struct ethtool_regs *regs, void *_p) -{ - u32 *p = _p, i, j; - struct bnx2x *bp = netdev_priv(dev); - struct dump_hdr dump_hdr = {0}; - - regs->version = 0; - memset(p, 0, regs->len); - - if (!netif_running(bp->dev)) - return; - - dump_hdr.hdr_size = (sizeof(struct dump_hdr) / 4) - 1; - dump_hdr.dump_sign = dump_sign_all; - dump_hdr.xstorm_waitp = REG_RD(bp, XSTORM_WAITP_ADDR); - dump_hdr.tstorm_waitp = REG_RD(bp, TSTORM_WAITP_ADDR); - dump_hdr.ustorm_waitp = REG_RD(bp, USTORM_WAITP_ADDR); - dump_hdr.cstorm_waitp = REG_RD(bp, CSTORM_WAITP_ADDR); - dump_hdr.info = CHIP_IS_E1(bp) ? RI_E1_ONLINE : RI_E1H_ONLINE; - - memcpy(p, &dump_hdr, sizeof(struct dump_hdr)); - p += dump_hdr.hdr_size + 1; - - if (CHIP_IS_E1(bp)) { - for (i = 0; i < REGS_COUNT; i++) - if (IS_E1_ONLINE(reg_addrs[i].info)) - for (j = 0; j < reg_addrs[i].size; j++) - *p++ = REG_RD(bp, - reg_addrs[i].addr + j*4); - - } else { /* E1H */ - for (i = 0; i < REGS_COUNT; i++) - if (IS_E1H_ONLINE(reg_addrs[i].info)) - for (j = 0; j < reg_addrs[i].size; j++) - *p++ = REG_RD(bp, - reg_addrs[i].addr + j*4); - } -} - -#define PHY_FW_VER_LEN 10 - -static void bnx2x_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct bnx2x *bp = netdev_priv(dev); - u8 phy_fw_ver[PHY_FW_VER_LEN]; - - strcpy(info->driver, DRV_MODULE_NAME); - strcpy(info->version, DRV_MODULE_VERSION); - - phy_fw_ver[0] = '\0'; - if (bp->port.pmf) { - bnx2x_acquire_phy_lock(bp); - bnx2x_get_ext_phy_fw_version(&bp->link_params, - (bp->state != BNX2X_STATE_CLOSED), - phy_fw_ver, PHY_FW_VER_LEN); - bnx2x_release_phy_lock(bp); - } - - strncpy(info->fw_version, bp->fw_ver, 32); - snprintf(info->fw_version + strlen(bp->fw_ver), 32 - strlen(bp->fw_ver), - "bc %d.%d.%d%s%s", - (bp->common.bc_ver & 0xff0000) >> 16, - (bp->common.bc_ver & 0xff00) >> 8, - (bp->common.bc_ver & 0xff), - ((phy_fw_ver[0] != '\0') ? " phy " : ""), phy_fw_ver); - strcpy(info->bus_info, pci_name(bp->pdev)); - info->n_stats = BNX2X_NUM_STATS; - info->testinfo_len = BNX2X_NUM_TESTS; - info->eedump_len = bp->common.flash_size; - info->regdump_len = bnx2x_get_regs_len(dev); -} - -static void bnx2x_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct bnx2x *bp = netdev_priv(dev); - - if (bp->flags & NO_WOL_FLAG) { - wol->supported = 0; - wol->wolopts = 0; - } else { - wol->supported = WAKE_MAGIC; - if (bp->wol) - wol->wolopts = WAKE_MAGIC; - else - wol->wolopts = 0; - } - memset(&wol->sopass, 0, sizeof(wol->sopass)); -} - -static int bnx2x_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct bnx2x *bp = netdev_priv(dev); - - if (wol->wolopts & ~WAKE_MAGIC) - return -EINVAL; - - if (wol->wolopts & WAKE_MAGIC) { - if (bp->flags & NO_WOL_FLAG) - return -EINVAL; - - bp->wol = 1; - } else - bp->wol = 0; - - return 0; -} - -static u32 bnx2x_get_msglevel(struct net_device *dev) -{ - struct bnx2x *bp = netdev_priv(dev); - - return bp->msg_enable; -} - -static void bnx2x_set_msglevel(struct net_device *dev, u32 level) -{ - struct bnx2x *bp = netdev_priv(dev); - - if (capable(CAP_NET_ADMIN)) - bp->msg_enable = level; -} - -static int bnx2x_nway_reset(struct net_device *dev) -{ - struct bnx2x *bp = netdev_priv(dev); - - if (!bp->port.pmf) - return 0; - - if (netif_running(dev)) { - bnx2x_stats_handle(bp, STATS_EVENT_STOP); - bnx2x_link_set(bp); - } - - return 0; -} - -static u32 bnx2x_get_link(struct net_device *dev) -{ - struct bnx2x *bp = netdev_priv(dev); - - if (bp->flags & MF_FUNC_DIS) - return 0; - - return bp->link_vars.link_up; -} - -static int bnx2x_get_eeprom_len(struct net_device *dev) -{ - struct bnx2x *bp = netdev_priv(dev); - - return bp->common.flash_size; -} - -static int bnx2x_acquire_nvram_lock(struct bnx2x *bp) -{ - int port = BP_PORT(bp); - int count, i; - u32 val = 0; - - /* adjust timeout for emulation/FPGA */ - count = NVRAM_TIMEOUT_COUNT; - if (CHIP_REV_IS_SLOW(bp)) - count *= 100; - - /* request access to nvram interface */ - REG_WR(bp, MCP_REG_MCPR_NVM_SW_ARB, - (MCPR_NVM_SW_ARB_ARB_REQ_SET1 << port)); - - for (i = 0; i < count*10; i++) { - val = REG_RD(bp, MCP_REG_MCPR_NVM_SW_ARB); - if (val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port)) - break; - - udelay(5); - } - - if (!(val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port))) { - DP(BNX2X_MSG_NVM, "cannot get access to nvram interface\n"); - return -EBUSY; - } - - return 0; -} - -static int bnx2x_release_nvram_lock(struct bnx2x *bp) -{ - int port = BP_PORT(bp); - int count, i; - u32 val = 0; - - /* adjust timeout for emulation/FPGA */ - count = NVRAM_TIMEOUT_COUNT; - if (CHIP_REV_IS_SLOW(bp)) - count *= 100; - - /* relinquish nvram interface */ - REG_WR(bp, MCP_REG_MCPR_NVM_SW_ARB, - (MCPR_NVM_SW_ARB_ARB_REQ_CLR1 << port)); - - for (i = 0; i < count*10; i++) { - val = REG_RD(bp, MCP_REG_MCPR_NVM_SW_ARB); - if (!(val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port))) - break; - - udelay(5); - } - - if (val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port)) { - DP(BNX2X_MSG_NVM, "cannot free access to nvram interface\n"); - return -EBUSY; - } - - return 0; -} - -static void bnx2x_enable_nvram_access(struct bnx2x *bp) -{ - u32 val; - - val = REG_RD(bp, MCP_REG_MCPR_NVM_ACCESS_ENABLE); - - /* enable both bits, even on read */ - REG_WR(bp, MCP_REG_MCPR_NVM_ACCESS_ENABLE, - (val | MCPR_NVM_ACCESS_ENABLE_EN | - MCPR_NVM_ACCESS_ENABLE_WR_EN)); -} - -static void bnx2x_disable_nvram_access(struct bnx2x *bp) -{ - u32 val; - - val = REG_RD(bp, MCP_REG_MCPR_NVM_ACCESS_ENABLE); - - /* disable both bits, even after read */ - REG_WR(bp, MCP_REG_MCPR_NVM_ACCESS_ENABLE, - (val & ~(MCPR_NVM_ACCESS_ENABLE_EN | - MCPR_NVM_ACCESS_ENABLE_WR_EN))); -} - -static int bnx2x_nvram_read_dword(struct bnx2x *bp, u32 offset, __be32 *ret_val, - u32 cmd_flags) -{ - int count, i, rc; - u32 val; - - /* build the command word */ - cmd_flags |= MCPR_NVM_COMMAND_DOIT; - - /* need to clear DONE bit separately */ - REG_WR(bp, MCP_REG_MCPR_NVM_COMMAND, MCPR_NVM_COMMAND_DONE); - - /* address of the NVRAM to read from */ - REG_WR(bp, MCP_REG_MCPR_NVM_ADDR, - (offset & MCPR_NVM_ADDR_NVM_ADDR_VALUE)); - - /* issue a read command */ - REG_WR(bp, MCP_REG_MCPR_NVM_COMMAND, cmd_flags); - - /* adjust timeout for emulation/FPGA */ - count = NVRAM_TIMEOUT_COUNT; - if (CHIP_REV_IS_SLOW(bp)) - count *= 100; - - /* wait for completion */ - *ret_val = 0; - rc = -EBUSY; - for (i = 0; i < count; i++) { - udelay(5); - val = REG_RD(bp, MCP_REG_MCPR_NVM_COMMAND); - - if (val & MCPR_NVM_COMMAND_DONE) { - val = REG_RD(bp, MCP_REG_MCPR_NVM_READ); - /* we read nvram data in cpu order - * but ethtool sees it as an array of bytes - * converting to big-endian will do the work */ - *ret_val = cpu_to_be32(val); - rc = 0; - break; - } - } - - return rc; -} - -static int bnx2x_nvram_read(struct bnx2x *bp, u32 offset, u8 *ret_buf, - int buf_size) -{ - int rc; - u32 cmd_flags; - __be32 val; - - if ((offset & 0x03) || (buf_size & 0x03) || (buf_size == 0)) { - DP(BNX2X_MSG_NVM, - "Invalid parameter: offset 0x%x buf_size 0x%x\n", - offset, buf_size); - return -EINVAL; - } - - if (offset + buf_size > bp->common.flash_size) { - DP(BNX2X_MSG_NVM, "Invalid parameter: offset (0x%x) +" - " buf_size (0x%x) > flash_size (0x%x)\n", - offset, buf_size, bp->common.flash_size); - return -EINVAL; - } - - /* request access to nvram interface */ - rc = bnx2x_acquire_nvram_lock(bp); - if (rc) - return rc; - - /* enable access to nvram interface */ - bnx2x_enable_nvram_access(bp); - - /* read the first word(s) */ - cmd_flags = MCPR_NVM_COMMAND_FIRST; - while ((buf_size > sizeof(u32)) && (rc == 0)) { - rc = bnx2x_nvram_read_dword(bp, offset, &val, cmd_flags); - memcpy(ret_buf, &val, 4); - - /* advance to the next dword */ - offset += sizeof(u32); - ret_buf += sizeof(u32); - buf_size -= sizeof(u32); - cmd_flags = 0; - } - - if (rc == 0) { - cmd_flags |= MCPR_NVM_COMMAND_LAST; - rc = bnx2x_nvram_read_dword(bp, offset, &val, cmd_flags); - memcpy(ret_buf, &val, 4); - } - - /* disable access to nvram interface */ - bnx2x_disable_nvram_access(bp); - bnx2x_release_nvram_lock(bp); - - return rc; -} - -static int bnx2x_get_eeprom(struct net_device *dev, - struct ethtool_eeprom *eeprom, u8 *eebuf) -{ - struct bnx2x *bp = netdev_priv(dev); - int rc; - - if (!netif_running(dev)) - return -EAGAIN; - - DP(BNX2X_MSG_NVM, "ethtool_eeprom: cmd %d\n" - DP_LEVEL " magic 0x%x offset 0x%x (%d) len 0x%x (%d)\n", - eeprom->cmd, eeprom->magic, eeprom->offset, eeprom->offset, - eeprom->len, eeprom->len); - - /* parameters already validated in ethtool_get_eeprom */ - - rc = bnx2x_nvram_read(bp, eeprom->offset, eebuf, eeprom->len); - - return rc; -} - -static int bnx2x_nvram_write_dword(struct bnx2x *bp, u32 offset, u32 val, - u32 cmd_flags) -{ - int count, i, rc; - - /* build the command word */ - cmd_flags |= MCPR_NVM_COMMAND_DOIT | MCPR_NVM_COMMAND_WR; - - /* need to clear DONE bit separately */ - REG_WR(bp, MCP_REG_MCPR_NVM_COMMAND, MCPR_NVM_COMMAND_DONE); - - /* write the data */ - REG_WR(bp, MCP_REG_MCPR_NVM_WRITE, val); - - /* address of the NVRAM to write to */ - REG_WR(bp, MCP_REG_MCPR_NVM_ADDR, - (offset & MCPR_NVM_ADDR_NVM_ADDR_VALUE)); - - /* issue the write command */ - REG_WR(bp, MCP_REG_MCPR_NVM_COMMAND, cmd_flags); - - /* adjust timeout for emulation/FPGA */ - count = NVRAM_TIMEOUT_COUNT; - if (CHIP_REV_IS_SLOW(bp)) - count *= 100; - - /* wait for completion */ - rc = -EBUSY; - for (i = 0; i < count; i++) { - udelay(5); - val = REG_RD(bp, MCP_REG_MCPR_NVM_COMMAND); - if (val & MCPR_NVM_COMMAND_DONE) { - rc = 0; - break; - } - } - - return rc; -} - -#define BYTE_OFFSET(offset) (8 * (offset & 0x03)) - -static int bnx2x_nvram_write1(struct bnx2x *bp, u32 offset, u8 *data_buf, - int buf_size) -{ - int rc; - u32 cmd_flags; - u32 align_offset; - __be32 val; - - if (offset + buf_size > bp->common.flash_size) { - DP(BNX2X_MSG_NVM, "Invalid parameter: offset (0x%x) +" - " buf_size (0x%x) > flash_size (0x%x)\n", - offset, buf_size, bp->common.flash_size); - return -EINVAL; - } - - /* request access to nvram interface */ - rc = bnx2x_acquire_nvram_lock(bp); - if (rc) - return rc; - - /* enable access to nvram interface */ - bnx2x_enable_nvram_access(bp); - - cmd_flags = (MCPR_NVM_COMMAND_FIRST | MCPR_NVM_COMMAND_LAST); - align_offset = (offset & ~0x03); - rc = bnx2x_nvram_read_dword(bp, align_offset, &val, cmd_flags); - - if (rc == 0) { - val &= ~(0xff << BYTE_OFFSET(offset)); - val |= (*data_buf << BYTE_OFFSET(offset)); - - /* nvram data is returned as an array of bytes - * convert it back to cpu order */ - val = be32_to_cpu(val); - - rc = bnx2x_nvram_write_dword(bp, align_offset, val, - cmd_flags); - } - - /* disable access to nvram interface */ - bnx2x_disable_nvram_access(bp); - bnx2x_release_nvram_lock(bp); - - return rc; -} - -static int bnx2x_nvram_write(struct bnx2x *bp, u32 offset, u8 *data_buf, - int buf_size) -{ - int rc; - u32 cmd_flags; - u32 val; - u32 written_so_far; - - if (buf_size == 1) /* ethtool */ - return bnx2x_nvram_write1(bp, offset, data_buf, buf_size); - - if ((offset & 0x03) || (buf_size & 0x03) || (buf_size == 0)) { - DP(BNX2X_MSG_NVM, - "Invalid parameter: offset 0x%x buf_size 0x%x\n", - offset, buf_size); - return -EINVAL; - } - - if (offset + buf_size > bp->common.flash_size) { - DP(BNX2X_MSG_NVM, "Invalid parameter: offset (0x%x) +" - " buf_size (0x%x) > flash_size (0x%x)\n", - offset, buf_size, bp->common.flash_size); - return -EINVAL; - } - - /* request access to nvram interface */ - rc = bnx2x_acquire_nvram_lock(bp); - if (rc) - return rc; - - /* enable access to nvram interface */ - bnx2x_enable_nvram_access(bp); - - written_so_far = 0; - cmd_flags = MCPR_NVM_COMMAND_FIRST; - while ((written_so_far < buf_size) && (rc == 0)) { - if (written_so_far == (buf_size - sizeof(u32))) - cmd_flags |= MCPR_NVM_COMMAND_LAST; - else if (((offset + 4) % NVRAM_PAGE_SIZE) == 0) - cmd_flags |= MCPR_NVM_COMMAND_LAST; - else if ((offset % NVRAM_PAGE_SIZE) == 0) - cmd_flags |= MCPR_NVM_COMMAND_FIRST; - - memcpy(&val, data_buf, 4); - - rc = bnx2x_nvram_write_dword(bp, offset, val, cmd_flags); - - /* advance to the next dword */ - offset += sizeof(u32); - data_buf += sizeof(u32); - written_so_far += sizeof(u32); - cmd_flags = 0; - } - - /* disable access to nvram interface */ - bnx2x_disable_nvram_access(bp); - bnx2x_release_nvram_lock(bp); - - return rc; -} - -static int bnx2x_set_eeprom(struct net_device *dev, - struct ethtool_eeprom *eeprom, u8 *eebuf) -{ - struct bnx2x *bp = netdev_priv(dev); - int port = BP_PORT(bp); - int rc = 0; - - if (!netif_running(dev)) - return -EAGAIN; - - DP(BNX2X_MSG_NVM, "ethtool_eeprom: cmd %d\n" - DP_LEVEL " magic 0x%x offset 0x%x (%d) len 0x%x (%d)\n", - eeprom->cmd, eeprom->magic, eeprom->offset, eeprom->offset, - eeprom->len, eeprom->len); - - /* parameters already validated in ethtool_set_eeprom */ - - /* PHY eeprom can be accessed only by the PMF */ - if ((eeprom->magic >= 0x50485900) && (eeprom->magic <= 0x504859FF) && - !bp->port.pmf) - return -EINVAL; - - if (eeprom->magic == 0x50485950) { - /* 'PHYP' (0x50485950): prepare phy for FW upgrade */ - bnx2x_stats_handle(bp, STATS_EVENT_STOP); - - bnx2x_acquire_phy_lock(bp); - rc |= bnx2x_link_reset(&bp->link_params, - &bp->link_vars, 0); - if (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config) == - PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101) - bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, - MISC_REGISTERS_GPIO_HIGH, port); - bnx2x_release_phy_lock(bp); - bnx2x_link_report(bp); - - } else if (eeprom->magic == 0x50485952) { - /* 'PHYR' (0x50485952): re-init link after FW upgrade */ - if (bp->state == BNX2X_STATE_OPEN) { - bnx2x_acquire_phy_lock(bp); - rc |= bnx2x_link_reset(&bp->link_params, - &bp->link_vars, 1); - - rc |= bnx2x_phy_init(&bp->link_params, - &bp->link_vars); - bnx2x_release_phy_lock(bp); - bnx2x_calc_fc_adv(bp); - } - } else if (eeprom->magic == 0x53985943) { - /* 'PHYC' (0x53985943): PHY FW upgrade completed */ - if (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config) == - PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101) { - u8 ext_phy_addr = - XGXS_EXT_PHY_ADDR(bp->link_params.ext_phy_config); - - /* DSP Remove Download Mode */ - bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, - MISC_REGISTERS_GPIO_LOW, port); - - bnx2x_acquire_phy_lock(bp); - - bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr); - - /* wait 0.5 sec to allow it to run */ - msleep(500); - bnx2x_ext_phy_hw_reset(bp, port); - msleep(500); - bnx2x_release_phy_lock(bp); - } - } else - rc = bnx2x_nvram_write(bp, eeprom->offset, eebuf, eeprom->len); - - return rc; -} - -static int bnx2x_get_coalesce(struct net_device *dev, - struct ethtool_coalesce *coal) -{ - struct bnx2x *bp = netdev_priv(dev); - - memset(coal, 0, sizeof(struct ethtool_coalesce)); - - coal->rx_coalesce_usecs = bp->rx_ticks; - coal->tx_coalesce_usecs = bp->tx_ticks; - - return 0; -} - -static int bnx2x_set_coalesce(struct net_device *dev, - struct ethtool_coalesce *coal) -{ - struct bnx2x *bp = netdev_priv(dev); - - bp->rx_ticks = (u16)coal->rx_coalesce_usecs; - if (bp->rx_ticks > BNX2X_MAX_COALESCE_TOUT) - bp->rx_ticks = BNX2X_MAX_COALESCE_TOUT; - - bp->tx_ticks = (u16)coal->tx_coalesce_usecs; - if (bp->tx_ticks > BNX2X_MAX_COALESCE_TOUT) - bp->tx_ticks = BNX2X_MAX_COALESCE_TOUT; - - if (netif_running(dev)) - bnx2x_update_coalesce(bp); - - return 0; -} - -static void bnx2x_get_ringparam(struct net_device *dev, - struct ethtool_ringparam *ering) -{ - struct bnx2x *bp = netdev_priv(dev); - - ering->rx_max_pending = MAX_RX_AVAIL; - ering->rx_mini_max_pending = 0; - ering->rx_jumbo_max_pending = 0; - - ering->rx_pending = bp->rx_ring_size; - ering->rx_mini_pending = 0; - ering->rx_jumbo_pending = 0; - - ering->tx_max_pending = MAX_TX_AVAIL; - ering->tx_pending = bp->tx_ring_size; -} - -static int bnx2x_set_ringparam(struct net_device *dev, - struct ethtool_ringparam *ering) -{ - struct bnx2x *bp = netdev_priv(dev); - int rc = 0; - - if (bp->recovery_state != BNX2X_RECOVERY_DONE) { - printk(KERN_ERR "Handling parity error recovery. Try again later\n"); - return -EAGAIN; - } - - if ((ering->rx_pending > MAX_RX_AVAIL) || - (ering->tx_pending > MAX_TX_AVAIL) || - (ering->tx_pending <= MAX_SKB_FRAGS + 4)) - return -EINVAL; - - bp->rx_ring_size = ering->rx_pending; - bp->tx_ring_size = ering->tx_pending; - - if (netif_running(dev)) { - bnx2x_nic_unload(bp, UNLOAD_NORMAL); - rc = bnx2x_nic_load(bp, LOAD_NORMAL); - } - - return rc; -} - -static void bnx2x_get_pauseparam(struct net_device *dev, - struct ethtool_pauseparam *epause) -{ - struct bnx2x *bp = netdev_priv(dev); - - epause->autoneg = (bp->link_params.req_flow_ctrl == - BNX2X_FLOW_CTRL_AUTO) && - (bp->link_params.req_line_speed == SPEED_AUTO_NEG); - - epause->rx_pause = ((bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) == - BNX2X_FLOW_CTRL_RX); - epause->tx_pause = ((bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX) == - BNX2X_FLOW_CTRL_TX); - - DP(NETIF_MSG_LINK, "ethtool_pauseparam: cmd %d\n" - DP_LEVEL " autoneg %d rx_pause %d tx_pause %d\n", - epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause); -} - -static int bnx2x_set_pauseparam(struct net_device *dev, - struct ethtool_pauseparam *epause) -{ - struct bnx2x *bp = netdev_priv(dev); - - if (IS_E1HMF(bp)) - return 0; - - DP(NETIF_MSG_LINK, "ethtool_pauseparam: cmd %d\n" - DP_LEVEL " autoneg %d rx_pause %d tx_pause %d\n", - epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause); - - bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO; - - if (epause->rx_pause) - bp->link_params.req_flow_ctrl |= BNX2X_FLOW_CTRL_RX; - - if (epause->tx_pause) - bp->link_params.req_flow_ctrl |= BNX2X_FLOW_CTRL_TX; - - if (bp->link_params.req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) - bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_NONE; - - if (epause->autoneg) { - if (!(bp->port.supported & SUPPORTED_Autoneg)) { - DP(NETIF_MSG_LINK, "autoneg not supported\n"); - return -EINVAL; - } - - if (bp->link_params.req_line_speed == SPEED_AUTO_NEG) - bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO; - } - - DP(NETIF_MSG_LINK, - "req_flow_ctrl 0x%x\n", bp->link_params.req_flow_ctrl); - - if (netif_running(dev)) { - bnx2x_stats_handle(bp, STATS_EVENT_STOP); - bnx2x_link_set(bp); - } - - return 0; -} - -static int bnx2x_set_flags(struct net_device *dev, u32 data) -{ - struct bnx2x *bp = netdev_priv(dev); - int changed = 0; - int rc = 0; - - if (data & ~(ETH_FLAG_LRO | ETH_FLAG_RXHASH)) - return -EINVAL; - - if (bp->recovery_state != BNX2X_RECOVERY_DONE) { - printk(KERN_ERR "Handling parity error recovery. Try again later\n"); - return -EAGAIN; - } - - /* TPA requires Rx CSUM offloading */ - if ((data & ETH_FLAG_LRO) && bp->rx_csum) { - if (!disable_tpa) { - if (!(dev->features & NETIF_F_LRO)) { - dev->features |= NETIF_F_LRO; - bp->flags |= TPA_ENABLE_FLAG; - changed = 1; - } - } else - rc = -EINVAL; - } else if (dev->features & NETIF_F_LRO) { - dev->features &= ~NETIF_F_LRO; - bp->flags &= ~TPA_ENABLE_FLAG; - changed = 1; - } - - if (data & ETH_FLAG_RXHASH) - dev->features |= NETIF_F_RXHASH; - else - dev->features &= ~NETIF_F_RXHASH; - - if (changed && netif_running(dev)) { - bnx2x_nic_unload(bp, UNLOAD_NORMAL); - rc = bnx2x_nic_load(bp, LOAD_NORMAL); - } - - return rc; -} - -static u32 bnx2x_get_rx_csum(struct net_device *dev) -{ - struct bnx2x *bp = netdev_priv(dev); - - return bp->rx_csum; -} - -static int bnx2x_set_rx_csum(struct net_device *dev, u32 data) -{ - struct bnx2x *bp = netdev_priv(dev); - int rc = 0; - - if (bp->recovery_state != BNX2X_RECOVERY_DONE) { - printk(KERN_ERR "Handling parity error recovery. Try again later\n"); - return -EAGAIN; - } - - bp->rx_csum = data; - - /* Disable TPA, when Rx CSUM is disabled. Otherwise all - TPA'ed packets will be discarded due to wrong TCP CSUM */ - if (!data) { - u32 flags = ethtool_op_get_flags(dev); - - rc = bnx2x_set_flags(dev, (flags & ~ETH_FLAG_LRO)); - } - - return rc; -} - -static int bnx2x_set_tso(struct net_device *dev, u32 data) -{ - if (data) { - dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN); - dev->features |= NETIF_F_TSO6; - } else { - dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO_ECN); - dev->features &= ~NETIF_F_TSO6; - } - - return 0; -} - -static const struct { - char string[ETH_GSTRING_LEN]; -} bnx2x_tests_str_arr[BNX2X_NUM_TESTS] = { - { "register_test (offline)" }, - { "memory_test (offline)" }, - { "loopback_test (offline)" }, - { "nvram_test (online)" }, - { "interrupt_test (online)" }, - { "link_test (online)" }, - { "idle check (online)" } -}; - -static int bnx2x_test_registers(struct bnx2x *bp) -{ - int idx, i, rc = -ENODEV; - u32 wr_val = 0; - int port = BP_PORT(bp); - static const struct { - u32 offset0; - u32 offset1; - u32 mask; - } reg_tbl[] = { -/* 0 */ { BRB1_REG_PAUSE_LOW_THRESHOLD_0, 4, 0x000003ff }, - { DORQ_REG_DB_ADDR0, 4, 0xffffffff }, - { HC_REG_AGG_INT_0, 4, 0x000003ff }, - { PBF_REG_MAC_IF0_ENABLE, 4, 0x00000001 }, - { PBF_REG_P0_INIT_CRD, 4, 0x000007ff }, - { PRS_REG_CID_PORT_0, 4, 0x00ffffff }, - { PXP2_REG_PSWRQ_CDU0_L2P, 4, 0x000fffff }, - { PXP2_REG_RQ_CDU0_EFIRST_MEM_ADDR, 8, 0x0003ffff }, - { PXP2_REG_PSWRQ_TM0_L2P, 4, 0x000fffff }, - { PXP2_REG_RQ_USDM0_EFIRST_MEM_ADDR, 8, 0x0003ffff }, -/* 10 */ { PXP2_REG_PSWRQ_TSDM0_L2P, 4, 0x000fffff }, - { QM_REG_CONNNUM_0, 4, 0x000fffff }, - { TM_REG_LIN0_MAX_ACTIVE_CID, 4, 0x0003ffff }, - { SRC_REG_KEYRSS0_0, 40, 0xffffffff }, - { SRC_REG_KEYRSS0_7, 40, 0xffffffff }, - { XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 4, 0x00000001 }, - { XCM_REG_WU_DA_CNT_CMD00, 4, 0x00000003 }, - { XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 4, 0x000000ff }, - { NIG_REG_LLH0_T_BIT, 4, 0x00000001 }, - { NIG_REG_EMAC0_IN_EN, 4, 0x00000001 }, -/* 20 */ { NIG_REG_BMAC0_IN_EN, 4, 0x00000001 }, - { NIG_REG_XCM0_OUT_EN, 4, 0x00000001 }, - { NIG_REG_BRB0_OUT_EN, 4, 0x00000001 }, - { NIG_REG_LLH0_XCM_MASK, 4, 0x00000007 }, - { NIG_REG_LLH0_ACPI_PAT_6_LEN, 68, 0x000000ff }, - { NIG_REG_LLH0_ACPI_PAT_0_CRC, 68, 0xffffffff }, - { NIG_REG_LLH0_DEST_MAC_0_0, 160, 0xffffffff }, - { NIG_REG_LLH0_DEST_IP_0_1, 160, 0xffffffff }, - { NIG_REG_LLH0_IPV4_IPV6_0, 160, 0x00000001 }, - { NIG_REG_LLH0_DEST_UDP_0, 160, 0x0000ffff }, -/* 30 */ { NIG_REG_LLH0_DEST_TCP_0, 160, 0x0000ffff }, - { NIG_REG_LLH0_VLAN_ID_0, 160, 0x00000fff }, - { NIG_REG_XGXS_SERDES0_MODE_SEL, 4, 0x00000001 }, - { NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0, 4, 0x00000001 }, - { NIG_REG_STATUS_INTERRUPT_PORT0, 4, 0x07ffffff }, - { NIG_REG_XGXS0_CTRL_EXTREMOTEMDIOST, 24, 0x00000001 }, - { NIG_REG_SERDES0_CTRL_PHY_ADDR, 16, 0x0000001f }, - - { 0xffffffff, 0, 0x00000000 } - }; - - if (!netif_running(bp->dev)) - return rc; - - /* Repeat the test twice: - First by writing 0x00000000, second by writing 0xffffffff */ - for (idx = 0; idx < 2; idx++) { - - switch (idx) { - case 0: - wr_val = 0; - break; - case 1: - wr_val = 0xffffffff; - break; - } - - for (i = 0; reg_tbl[i].offset0 != 0xffffffff; i++) { - u32 offset, mask, save_val, val; - - offset = reg_tbl[i].offset0 + port*reg_tbl[i].offset1; - mask = reg_tbl[i].mask; - - save_val = REG_RD(bp, offset); - - REG_WR(bp, offset, (wr_val & mask)); - val = REG_RD(bp, offset); - - /* Restore the original register's value */ - REG_WR(bp, offset, save_val); - - /* verify value is as expected */ - if ((val & mask) != (wr_val & mask)) { - DP(NETIF_MSG_PROBE, - "offset 0x%x: val 0x%x != 0x%x mask 0x%x\n", - offset, val, wr_val, mask); - goto test_reg_exit; - } - } - } - - rc = 0; - -test_reg_exit: - return rc; -} - -static int bnx2x_test_memory(struct bnx2x *bp) -{ - int i, j, rc = -ENODEV; - u32 val; - static const struct { - u32 offset; - int size; - } mem_tbl[] = { - { CCM_REG_XX_DESCR_TABLE, CCM_REG_XX_DESCR_TABLE_SIZE }, - { CFC_REG_ACTIVITY_COUNTER, CFC_REG_ACTIVITY_COUNTER_SIZE }, - { CFC_REG_LINK_LIST, CFC_REG_LINK_LIST_SIZE }, - { DMAE_REG_CMD_MEM, DMAE_REG_CMD_MEM_SIZE }, - { TCM_REG_XX_DESCR_TABLE, TCM_REG_XX_DESCR_TABLE_SIZE }, - { UCM_REG_XX_DESCR_TABLE, UCM_REG_XX_DESCR_TABLE_SIZE }, - { XCM_REG_XX_DESCR_TABLE, XCM_REG_XX_DESCR_TABLE_SIZE }, - - { 0xffffffff, 0 } - }; - static const struct { - char *name; - u32 offset; - u32 e1_mask; - u32 e1h_mask; - } prty_tbl[] = { - { "CCM_PRTY_STS", CCM_REG_CCM_PRTY_STS, 0x3ffc0, 0 }, - { "CFC_PRTY_STS", CFC_REG_CFC_PRTY_STS, 0x2, 0x2 }, - { "DMAE_PRTY_STS", DMAE_REG_DMAE_PRTY_STS, 0, 0 }, - { "TCM_PRTY_STS", TCM_REG_TCM_PRTY_STS, 0x3ffc0, 0 }, - { "UCM_PRTY_STS", UCM_REG_UCM_PRTY_STS, 0x3ffc0, 0 }, - { "XCM_PRTY_STS", XCM_REG_XCM_PRTY_STS, 0x3ffc1, 0 }, - - { NULL, 0xffffffff, 0, 0 } - }; - - if (!netif_running(bp->dev)) - return rc; - - /* Go through all the memories */ - for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) - for (j = 0; j < mem_tbl[i].size; j++) - REG_RD(bp, mem_tbl[i].offset + j*4); - - /* Check the parity status */ - for (i = 0; prty_tbl[i].offset != 0xffffffff; i++) { - val = REG_RD(bp, prty_tbl[i].offset); - if ((CHIP_IS_E1(bp) && (val & ~(prty_tbl[i].e1_mask))) || - (CHIP_IS_E1H(bp) && (val & ~(prty_tbl[i].e1h_mask)))) { - DP(NETIF_MSG_HW, - "%s is 0x%x\n", prty_tbl[i].name, val); - goto test_mem_exit; - } - } - - rc = 0; - -test_mem_exit: - return rc; -} - -static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up) -{ - int cnt = 1000; - - if (link_up) - while (bnx2x_link_test(bp) && cnt--) - msleep(10); -} - -static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up) -{ - unsigned int pkt_size, num_pkts, i; - struct sk_buff *skb; - unsigned char *packet; - struct bnx2x_fastpath *fp_rx = &bp->fp[0]; - struct bnx2x_fastpath *fp_tx = &bp->fp[0]; - u16 tx_start_idx, tx_idx; - u16 rx_start_idx, rx_idx; - u16 pkt_prod, bd_prod; - struct sw_tx_bd *tx_buf; - struct eth_tx_start_bd *tx_start_bd; - struct eth_tx_parse_bd *pbd = NULL; - dma_addr_t mapping; - union eth_rx_cqe *cqe; - u8 cqe_fp_flags; - struct sw_rx_bd *rx_buf; - u16 len; - int rc = -ENODEV; - - /* check the loopback mode */ - switch (loopback_mode) { - case BNX2X_PHY_LOOPBACK: - if (bp->link_params.loopback_mode != LOOPBACK_XGXS_10) - return -EINVAL; - break; - case BNX2X_MAC_LOOPBACK: - bp->link_params.loopback_mode = LOOPBACK_BMAC; - bnx2x_phy_init(&bp->link_params, &bp->link_vars); - break; - default: - return -EINVAL; - } - - /* prepare the loopback packet */ - pkt_size = (((bp->dev->mtu < ETH_MAX_PACKET_SIZE) ? - bp->dev->mtu : ETH_MAX_PACKET_SIZE) + ETH_HLEN); - skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size); - if (!skb) { - rc = -ENOMEM; - goto test_loopback_exit; - } - packet = skb_put(skb, pkt_size); - memcpy(packet, bp->dev->dev_addr, ETH_ALEN); - memset(packet + ETH_ALEN, 0, ETH_ALEN); - memset(packet + 2*ETH_ALEN, 0x77, (ETH_HLEN - 2*ETH_ALEN)); - for (i = ETH_HLEN; i < pkt_size; i++) - packet[i] = (unsigned char) (i & 0xff); - - /* send the loopback packet */ - num_pkts = 0; - tx_start_idx = le16_to_cpu(*fp_tx->tx_cons_sb); - rx_start_idx = le16_to_cpu(*fp_rx->rx_cons_sb); - - pkt_prod = fp_tx->tx_pkt_prod++; - tx_buf = &fp_tx->tx_buf_ring[TX_BD(pkt_prod)]; - tx_buf->first_bd = fp_tx->tx_bd_prod; - tx_buf->skb = skb; - tx_buf->flags = 0; - - bd_prod = TX_BD(fp_tx->tx_bd_prod); - tx_start_bd = &fp_tx->tx_desc_ring[bd_prod].start_bd; - mapping = dma_map_single(&bp->pdev->dev, skb->data, - skb_headlen(skb), DMA_TO_DEVICE); - tx_start_bd->addr_hi = cpu_to_le32(U64_HI(mapping)); - tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping)); - tx_start_bd->nbd = cpu_to_le16(2); /* start + pbd */ - tx_start_bd->nbytes = cpu_to_le16(skb_headlen(skb)); - tx_start_bd->vlan = cpu_to_le16(pkt_prod); - tx_start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD; - tx_start_bd->general_data = ((UNICAST_ADDRESS << - ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT) | 1); - - /* turn on parsing and get a BD */ - bd_prod = TX_BD(NEXT_TX_IDX(bd_prod)); - pbd = &fp_tx->tx_desc_ring[bd_prod].parse_bd; - - memset(pbd, 0, sizeof(struct eth_tx_parse_bd)); - - wmb(); - - fp_tx->tx_db.data.prod += 2; - barrier(); - DOORBELL(bp, fp_tx->index, fp_tx->tx_db.raw); - - mmiowb(); - - num_pkts++; - fp_tx->tx_bd_prod += 2; /* start + pbd */ - - udelay(100); - - tx_idx = le16_to_cpu(*fp_tx->tx_cons_sb); - if (tx_idx != tx_start_idx + num_pkts) - goto test_loopback_exit; - - rx_idx = le16_to_cpu(*fp_rx->rx_cons_sb); - if (rx_idx != rx_start_idx + num_pkts) - goto test_loopback_exit; - - cqe = &fp_rx->rx_comp_ring[RCQ_BD(fp_rx->rx_comp_cons)]; - cqe_fp_flags = cqe->fast_path_cqe.type_error_flags; - if (CQE_TYPE(cqe_fp_flags) || (cqe_fp_flags & ETH_RX_ERROR_FALGS)) - goto test_loopback_rx_exit; - - len = le16_to_cpu(cqe->fast_path_cqe.pkt_len); - if (len != pkt_size) - goto test_loopback_rx_exit; - - rx_buf = &fp_rx->rx_buf_ring[RX_BD(fp_rx->rx_bd_cons)]; - skb = rx_buf->skb; - skb_reserve(skb, cqe->fast_path_cqe.placement_offset); - for (i = ETH_HLEN; i < pkt_size; i++) - if (*(skb->data + i) != (unsigned char) (i & 0xff)) - goto test_loopback_rx_exit; - - rc = 0; - -test_loopback_rx_exit: - - fp_rx->rx_bd_cons = NEXT_RX_IDX(fp_rx->rx_bd_cons); - fp_rx->rx_bd_prod = NEXT_RX_IDX(fp_rx->rx_bd_prod); - fp_rx->rx_comp_cons = NEXT_RCQ_IDX(fp_rx->rx_comp_cons); - fp_rx->rx_comp_prod = NEXT_RCQ_IDX(fp_rx->rx_comp_prod); - - /* Update producers */ - bnx2x_update_rx_prod(bp, fp_rx, fp_rx->rx_bd_prod, fp_rx->rx_comp_prod, - fp_rx->rx_sge_prod); - -test_loopback_exit: - bp->link_params.loopback_mode = LOOPBACK_NONE; - - return rc; -} - -static int bnx2x_test_loopback(struct bnx2x *bp, u8 link_up) -{ - int rc = 0, res; - - if (BP_NOMCP(bp)) - return rc; - - if (!netif_running(bp->dev)) - return BNX2X_LOOPBACK_FAILED; - - bnx2x_netif_stop(bp, 1); - bnx2x_acquire_phy_lock(bp); - - res = bnx2x_run_loopback(bp, BNX2X_PHY_LOOPBACK, link_up); - if (res) { - DP(NETIF_MSG_PROBE, " PHY loopback failed (res %d)\n", res); - rc |= BNX2X_PHY_LOOPBACK_FAILED; - } - - res = bnx2x_run_loopback(bp, BNX2X_MAC_LOOPBACK, link_up); - if (res) { - DP(NETIF_MSG_PROBE, " MAC loopback failed (res %d)\n", res); - rc |= BNX2X_MAC_LOOPBACK_FAILED; - } - - bnx2x_release_phy_lock(bp); - bnx2x_netif_start(bp); - - return rc; -} - -#define CRC32_RESIDUAL 0xdebb20e3 - -static int bnx2x_test_nvram(struct bnx2x *bp) -{ - static const struct { - int offset; - int size; - } nvram_tbl[] = { - { 0, 0x14 }, /* bootstrap */ - { 0x14, 0xec }, /* dir */ - { 0x100, 0x350 }, /* manuf_info */ - { 0x450, 0xf0 }, /* feature_info */ - { 0x640, 0x64 }, /* upgrade_key_info */ - { 0x6a4, 0x64 }, - { 0x708, 0x70 }, /* manuf_key_info */ - { 0x778, 0x70 }, - { 0, 0 } - }; - __be32 buf[0x350 / 4]; - u8 *data = (u8 *)buf; - int i, rc; - u32 magic, crc; - - if (BP_NOMCP(bp)) - return 0; - - rc = bnx2x_nvram_read(bp, 0, data, 4); - if (rc) { - DP(NETIF_MSG_PROBE, "magic value read (rc %d)\n", rc); - goto test_nvram_exit; - } - - magic = be32_to_cpu(buf[0]); - if (magic != 0x669955aa) { - DP(NETIF_MSG_PROBE, "magic value (0x%08x)\n", magic); - rc = -ENODEV; - goto test_nvram_exit; - } - - for (i = 0; nvram_tbl[i].size; i++) { - - rc = bnx2x_nvram_read(bp, nvram_tbl[i].offset, data, - nvram_tbl[i].size); - if (rc) { - DP(NETIF_MSG_PROBE, - "nvram_tbl[%d] read data (rc %d)\n", i, rc); - goto test_nvram_exit; - } - - crc = ether_crc_le(nvram_tbl[i].size, data); - if (crc != CRC32_RESIDUAL) { - DP(NETIF_MSG_PROBE, - "nvram_tbl[%d] crc value (0x%08x)\n", i, crc); - rc = -ENODEV; - goto test_nvram_exit; - } - } - -test_nvram_exit: - return rc; -} - -static int bnx2x_test_intr(struct bnx2x *bp) -{ - struct mac_configuration_cmd *config = bnx2x_sp(bp, mac_config); - int i, rc; - - if (!netif_running(bp->dev)) - return -ENODEV; - - config->hdr.length = 0; - if (CHIP_IS_E1(bp)) - /* use last unicast entries */ - config->hdr.offset = (BP_PORT(bp) ? 63 : 31); - else - config->hdr.offset = BP_FUNC(bp); - config->hdr.client_id = bp->fp->cl_id; - config->hdr.reserved1 = 0; - - bp->set_mac_pending++; - smp_wmb(); - rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0, - U64_HI(bnx2x_sp_mapping(bp, mac_config)), - U64_LO(bnx2x_sp_mapping(bp, mac_config)), 0); - if (rc == 0) { - for (i = 0; i < 10; i++) { - if (!bp->set_mac_pending) - break; - smp_rmb(); - msleep_interruptible(10); - } - if (i == 10) - rc = -ENODEV; - } - - return rc; -} - -static void bnx2x_self_test(struct net_device *dev, - struct ethtool_test *etest, u64 *buf) -{ - struct bnx2x *bp = netdev_priv(dev); - - if (bp->recovery_state != BNX2X_RECOVERY_DONE) { - printk(KERN_ERR "Handling parity error recovery. Try again later\n"); - etest->flags |= ETH_TEST_FL_FAILED; - return; - } - - memset(buf, 0, sizeof(u64) * BNX2X_NUM_TESTS); - - if (!netif_running(dev)) - return; - - /* offline tests are not supported in MF mode */ - if (IS_E1HMF(bp)) - etest->flags &= ~ETH_TEST_FL_OFFLINE; - - if (etest->flags & ETH_TEST_FL_OFFLINE) { - int port = BP_PORT(bp); - u32 val; - u8 link_up; - - /* save current value of input enable for TX port IF */ - val = REG_RD(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4); - /* disable input for TX port IF */ - REG_WR(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4, 0); - - link_up = (bnx2x_link_test(bp) == 0); - bnx2x_nic_unload(bp, UNLOAD_NORMAL); - bnx2x_nic_load(bp, LOAD_DIAG); - /* wait until link state is restored */ - bnx2x_wait_for_link(bp, link_up); - - if (bnx2x_test_registers(bp) != 0) { - buf[0] = 1; - etest->flags |= ETH_TEST_FL_FAILED; - } - if (bnx2x_test_memory(bp) != 0) { - buf[1] = 1; - etest->flags |= ETH_TEST_FL_FAILED; - } - buf[2] = bnx2x_test_loopback(bp, link_up); - if (buf[2] != 0) - etest->flags |= ETH_TEST_FL_FAILED; - - bnx2x_nic_unload(bp, UNLOAD_NORMAL); - - /* restore input for TX port IF */ - REG_WR(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4, val); - - bnx2x_nic_load(bp, LOAD_NORMAL); - /* wait until link state is restored */ - bnx2x_wait_for_link(bp, link_up); - } - if (bnx2x_test_nvram(bp) != 0) { - buf[3] = 1; - etest->flags |= ETH_TEST_FL_FAILED; - } - if (bnx2x_test_intr(bp) != 0) { - buf[4] = 1; - etest->flags |= ETH_TEST_FL_FAILED; - } - if (bp->port.pmf) - if (bnx2x_link_test(bp) != 0) { - buf[5] = 1; - etest->flags |= ETH_TEST_FL_FAILED; - } - -#ifdef BNX2X_EXTRA_DEBUG - bnx2x_panic_dump(bp); -#endif -} - -static const struct { - long offset; - int size; - u8 string[ETH_GSTRING_LEN]; -} bnx2x_q_stats_arr[BNX2X_NUM_Q_STATS] = { -/* 1 */ { Q_STATS_OFFSET32(total_bytes_received_hi), 8, "[%d]: rx_bytes" }, - { Q_STATS_OFFSET32(error_bytes_received_hi), - 8, "[%d]: rx_error_bytes" }, - { Q_STATS_OFFSET32(total_unicast_packets_received_hi), - 8, "[%d]: rx_ucast_packets" }, - { Q_STATS_OFFSET32(total_multicast_packets_received_hi), - 8, "[%d]: rx_mcast_packets" }, - { Q_STATS_OFFSET32(total_broadcast_packets_received_hi), - 8, "[%d]: rx_bcast_packets" }, - { Q_STATS_OFFSET32(no_buff_discard_hi), 8, "[%d]: rx_discards" }, - { Q_STATS_OFFSET32(rx_err_discard_pkt), - 4, "[%d]: rx_phy_ip_err_discards"}, - { Q_STATS_OFFSET32(rx_skb_alloc_failed), - 4, "[%d]: rx_skb_alloc_discard" }, - { Q_STATS_OFFSET32(hw_csum_err), 4, "[%d]: rx_csum_offload_errors" }, - -/* 10 */{ Q_STATS_OFFSET32(total_bytes_transmitted_hi), 8, "[%d]: tx_bytes" }, - { Q_STATS_OFFSET32(total_unicast_packets_transmitted_hi), - 8, "[%d]: tx_ucast_packets" }, - { Q_STATS_OFFSET32(total_multicast_packets_transmitted_hi), - 8, "[%d]: tx_mcast_packets" }, - { Q_STATS_OFFSET32(total_broadcast_packets_transmitted_hi), - 8, "[%d]: tx_bcast_packets" } -}; - -static const struct { - long offset; - int size; - u32 flags; -#define STATS_FLAGS_PORT 1 -#define STATS_FLAGS_FUNC 2 -#define STATS_FLAGS_BOTH (STATS_FLAGS_FUNC | STATS_FLAGS_PORT) - u8 string[ETH_GSTRING_LEN]; -} bnx2x_stats_arr[BNX2X_NUM_STATS] = { -/* 1 */ { STATS_OFFSET32(total_bytes_received_hi), - 8, STATS_FLAGS_BOTH, "rx_bytes" }, - { STATS_OFFSET32(error_bytes_received_hi), - 8, STATS_FLAGS_BOTH, "rx_error_bytes" }, - { STATS_OFFSET32(total_unicast_packets_received_hi), - 8, STATS_FLAGS_BOTH, "rx_ucast_packets" }, - { STATS_OFFSET32(total_multicast_packets_received_hi), - 8, STATS_FLAGS_BOTH, "rx_mcast_packets" }, - { STATS_OFFSET32(total_broadcast_packets_received_hi), - 8, STATS_FLAGS_BOTH, "rx_bcast_packets" }, - { STATS_OFFSET32(rx_stat_dot3statsfcserrors_hi), - 8, STATS_FLAGS_PORT, "rx_crc_errors" }, - { STATS_OFFSET32(rx_stat_dot3statsalignmenterrors_hi), - 8, STATS_FLAGS_PORT, "rx_align_errors" }, - { STATS_OFFSET32(rx_stat_etherstatsundersizepkts_hi), - 8, STATS_FLAGS_PORT, "rx_undersize_packets" }, - { STATS_OFFSET32(etherstatsoverrsizepkts_hi), - 8, STATS_FLAGS_PORT, "rx_oversize_packets" }, -/* 10 */{ STATS_OFFSET32(rx_stat_etherstatsfragments_hi), - 8, STATS_FLAGS_PORT, "rx_fragments" }, - { STATS_OFFSET32(rx_stat_etherstatsjabbers_hi), - 8, STATS_FLAGS_PORT, "rx_jabbers" }, - { STATS_OFFSET32(no_buff_discard_hi), - 8, STATS_FLAGS_BOTH, "rx_discards" }, - { STATS_OFFSET32(mac_filter_discard), - 4, STATS_FLAGS_PORT, "rx_filtered_packets" }, - { STATS_OFFSET32(xxoverflow_discard), - 4, STATS_FLAGS_PORT, "rx_fw_discards" }, - { STATS_OFFSET32(brb_drop_hi), - 8, STATS_FLAGS_PORT, "rx_brb_discard" }, - { STATS_OFFSET32(brb_truncate_hi), - 8, STATS_FLAGS_PORT, "rx_brb_truncate" }, - { STATS_OFFSET32(pause_frames_received_hi), - 8, STATS_FLAGS_PORT, "rx_pause_frames" }, - { STATS_OFFSET32(rx_stat_maccontrolframesreceived_hi), - 8, STATS_FLAGS_PORT, "rx_mac_ctrl_frames" }, - { STATS_OFFSET32(nig_timer_max), - 4, STATS_FLAGS_PORT, "rx_constant_pause_events" }, -/* 20 */{ STATS_OFFSET32(rx_err_discard_pkt), - 4, STATS_FLAGS_BOTH, "rx_phy_ip_err_discards"}, - { STATS_OFFSET32(rx_skb_alloc_failed), - 4, STATS_FLAGS_BOTH, "rx_skb_alloc_discard" }, - { STATS_OFFSET32(hw_csum_err), - 4, STATS_FLAGS_BOTH, "rx_csum_offload_errors" }, - - { STATS_OFFSET32(total_bytes_transmitted_hi), - 8, STATS_FLAGS_BOTH, "tx_bytes" }, - { STATS_OFFSET32(tx_stat_ifhcoutbadoctets_hi), - 8, STATS_FLAGS_PORT, "tx_error_bytes" }, - { STATS_OFFSET32(total_unicast_packets_transmitted_hi), - 8, STATS_FLAGS_BOTH, "tx_ucast_packets" }, - { STATS_OFFSET32(total_multicast_packets_transmitted_hi), - 8, STATS_FLAGS_BOTH, "tx_mcast_packets" }, - { STATS_OFFSET32(total_broadcast_packets_transmitted_hi), - 8, STATS_FLAGS_BOTH, "tx_bcast_packets" }, - { STATS_OFFSET32(tx_stat_dot3statsinternalmactransmiterrors_hi), - 8, STATS_FLAGS_PORT, "tx_mac_errors" }, - { STATS_OFFSET32(rx_stat_dot3statscarriersenseerrors_hi), - 8, STATS_FLAGS_PORT, "tx_carrier_errors" }, -/* 30 */{ STATS_OFFSET32(tx_stat_dot3statssinglecollisionframes_hi), - 8, STATS_FLAGS_PORT, "tx_single_collisions" }, - { STATS_OFFSET32(tx_stat_dot3statsmultiplecollisionframes_hi), - 8, STATS_FLAGS_PORT, "tx_multi_collisions" }, - { STATS_OFFSET32(tx_stat_dot3statsdeferredtransmissions_hi), - 8, STATS_FLAGS_PORT, "tx_deferred" }, - { STATS_OFFSET32(tx_stat_dot3statsexcessivecollisions_hi), - 8, STATS_FLAGS_PORT, "tx_excess_collisions" }, - { STATS_OFFSET32(tx_stat_dot3statslatecollisions_hi), - 8, STATS_FLAGS_PORT, "tx_late_collisions" }, - { STATS_OFFSET32(tx_stat_etherstatscollisions_hi), - 8, STATS_FLAGS_PORT, "tx_total_collisions" }, - { STATS_OFFSET32(tx_stat_etherstatspkts64octets_hi), - 8, STATS_FLAGS_PORT, "tx_64_byte_packets" }, - { STATS_OFFSET32(tx_stat_etherstatspkts65octetsto127octets_hi), - 8, STATS_FLAGS_PORT, "tx_65_to_127_byte_packets" }, - { STATS_OFFSET32(tx_stat_etherstatspkts128octetsto255octets_hi), - 8, STATS_FLAGS_PORT, "tx_128_to_255_byte_packets" }, - { STATS_OFFSET32(tx_stat_etherstatspkts256octetsto511octets_hi), - 8, STATS_FLAGS_PORT, "tx_256_to_511_byte_packets" }, -/* 40 */{ STATS_OFFSET32(tx_stat_etherstatspkts512octetsto1023octets_hi), - 8, STATS_FLAGS_PORT, "tx_512_to_1023_byte_packets" }, - { STATS_OFFSET32(etherstatspkts1024octetsto1522octets_hi), - 8, STATS_FLAGS_PORT, "tx_1024_to_1522_byte_packets" }, - { STATS_OFFSET32(etherstatspktsover1522octets_hi), - 8, STATS_FLAGS_PORT, "tx_1523_to_9022_byte_packets" }, - { STATS_OFFSET32(pause_frames_sent_hi), - 8, STATS_FLAGS_PORT, "tx_pause_frames" } -}; - -#define IS_PORT_STAT(i) \ - ((bnx2x_stats_arr[i].flags & STATS_FLAGS_BOTH) == STATS_FLAGS_PORT) -#define IS_FUNC_STAT(i) (bnx2x_stats_arr[i].flags & STATS_FLAGS_FUNC) -#define IS_E1HMF_MODE_STAT(bp) \ - (IS_E1HMF(bp) && !(bp->msg_enable & BNX2X_MSG_STATS)) - -static int bnx2x_get_sset_count(struct net_device *dev, int stringset) -{ - struct bnx2x *bp = netdev_priv(dev); - int i, num_stats; - - switch (stringset) { - case ETH_SS_STATS: - if (is_multi(bp)) { - num_stats = BNX2X_NUM_Q_STATS * bp->num_queues; - if (!IS_E1HMF_MODE_STAT(bp)) - num_stats += BNX2X_NUM_STATS; - } else { - if (IS_E1HMF_MODE_STAT(bp)) { - num_stats = 0; - for (i = 0; i < BNX2X_NUM_STATS; i++) - if (IS_FUNC_STAT(i)) - num_stats++; - } else - num_stats = BNX2X_NUM_STATS; - } - return num_stats; - - case ETH_SS_TEST: - return BNX2X_NUM_TESTS; - - default: - return -EINVAL; - } -} - -static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf) -{ - struct bnx2x *bp = netdev_priv(dev); - int i, j, k; - - switch (stringset) { - case ETH_SS_STATS: - if (is_multi(bp)) { - k = 0; - for_each_queue(bp, i) { - for (j = 0; j < BNX2X_NUM_Q_STATS; j++) - sprintf(buf + (k + j)*ETH_GSTRING_LEN, - bnx2x_q_stats_arr[j].string, i); - k += BNX2X_NUM_Q_STATS; - } - if (IS_E1HMF_MODE_STAT(bp)) - break; - for (j = 0; j < BNX2X_NUM_STATS; j++) - strcpy(buf + (k + j)*ETH_GSTRING_LEN, - bnx2x_stats_arr[j].string); - } else { - for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) { - if (IS_E1HMF_MODE_STAT(bp) && IS_PORT_STAT(i)) - continue; - strcpy(buf + j*ETH_GSTRING_LEN, - bnx2x_stats_arr[i].string); - j++; - } - } - break; - - case ETH_SS_TEST: - memcpy(buf, bnx2x_tests_str_arr, sizeof(bnx2x_tests_str_arr)); - break; - } -} - -static void bnx2x_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *buf) -{ - struct bnx2x *bp = netdev_priv(dev); - u32 *hw_stats, *offset; - int i, j, k; - - if (is_multi(bp)) { - k = 0; - for_each_queue(bp, i) { - hw_stats = (u32 *)&bp->fp[i].eth_q_stats; - for (j = 0; j < BNX2X_NUM_Q_STATS; j++) { - if (bnx2x_q_stats_arr[j].size == 0) { - /* skip this counter */ - buf[k + j] = 0; - continue; - } - offset = (hw_stats + - bnx2x_q_stats_arr[j].offset); - if (bnx2x_q_stats_arr[j].size == 4) { - /* 4-byte counter */ - buf[k + j] = (u64) *offset; - continue; - } - /* 8-byte counter */ - buf[k + j] = HILO_U64(*offset, *(offset + 1)); - } - k += BNX2X_NUM_Q_STATS; - } - if (IS_E1HMF_MODE_STAT(bp)) - return; - hw_stats = (u32 *)&bp->eth_stats; - for (j = 0; j < BNX2X_NUM_STATS; j++) { - if (bnx2x_stats_arr[j].size == 0) { - /* skip this counter */ - buf[k + j] = 0; - continue; - } - offset = (hw_stats + bnx2x_stats_arr[j].offset); - if (bnx2x_stats_arr[j].size == 4) { - /* 4-byte counter */ - buf[k + j] = (u64) *offset; - continue; - } - /* 8-byte counter */ - buf[k + j] = HILO_U64(*offset, *(offset + 1)); - } - } else { - hw_stats = (u32 *)&bp->eth_stats; - for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) { - if (IS_E1HMF_MODE_STAT(bp) && IS_PORT_STAT(i)) - continue; - if (bnx2x_stats_arr[i].size == 0) { - /* skip this counter */ - buf[j] = 0; - j++; - continue; - } - offset = (hw_stats + bnx2x_stats_arr[i].offset); - if (bnx2x_stats_arr[i].size == 4) { - /* 4-byte counter */ - buf[j] = (u64) *offset; - j++; - continue; - } - /* 8-byte counter */ - buf[j] = HILO_U64(*offset, *(offset + 1)); - j++; - } - } -} - -static int bnx2x_phys_id(struct net_device *dev, u32 data) -{ - struct bnx2x *bp = netdev_priv(dev); - int i; - - if (!netif_running(dev)) - return 0; - - if (!bp->port.pmf) - return 0; - - if (data == 0) - data = 2; - - for (i = 0; i < (data * 2); i++) { - if ((i % 2) == 0) - bnx2x_set_led(&bp->link_params, LED_MODE_OPER, - SPEED_1000); - else - bnx2x_set_led(&bp->link_params, LED_MODE_OFF, 0); - - msleep_interruptible(500); - if (signal_pending(current)) - break; - } - - if (bp->link_vars.link_up) - bnx2x_set_led(&bp->link_params, LED_MODE_OPER, - bp->link_vars.line_speed); - - return 0; -} - -static const struct ethtool_ops bnx2x_ethtool_ops = { - .get_settings = bnx2x_get_settings, - .set_settings = bnx2x_set_settings, - .get_drvinfo = bnx2x_get_drvinfo, - .get_regs_len = bnx2x_get_regs_len, - .get_regs = bnx2x_get_regs, - .get_wol = bnx2x_get_wol, - .set_wol = bnx2x_set_wol, - .get_msglevel = bnx2x_get_msglevel, - .set_msglevel = bnx2x_set_msglevel, - .nway_reset = bnx2x_nway_reset, - .get_link = bnx2x_get_link, - .get_eeprom_len = bnx2x_get_eeprom_len, - .get_eeprom = bnx2x_get_eeprom, - .set_eeprom = bnx2x_set_eeprom, - .get_coalesce = bnx2x_get_coalesce, - .set_coalesce = bnx2x_set_coalesce, - .get_ringparam = bnx2x_get_ringparam, - .set_ringparam = bnx2x_set_ringparam, - .get_pauseparam = bnx2x_get_pauseparam, - .set_pauseparam = bnx2x_set_pauseparam, - .get_rx_csum = bnx2x_get_rx_csum, - .set_rx_csum = bnx2x_set_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_hw_csum, - .set_flags = bnx2x_set_flags, - .get_flags = ethtool_op_get_flags, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, - .get_tso = ethtool_op_get_tso, - .set_tso = bnx2x_set_tso, - .self_test = bnx2x_self_test, - .get_sset_count = bnx2x_get_sset_count, - .get_strings = bnx2x_get_strings, - .phys_id = bnx2x_phys_id, - .get_ethtool_stats = bnx2x_get_ethtool_stats, -}; - -/* end of ethtool_ops */ /**************************************************************************** * General service functions ****************************************************************************/ -static int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state) -{ - u16 pmcsr; - - pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr); - - switch (state) { - case PCI_D0: - pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, - ((pmcsr & ~PCI_PM_CTRL_STATE_MASK) | - PCI_PM_CTRL_PME_STATUS)); - - if (pmcsr & PCI_PM_CTRL_STATE_MASK) - /* delay required during transition out of D3hot */ - msleep(20); - break; - - case PCI_D3hot: - /* If there are other clients above don't - shut down the power */ - if (atomic_read(&bp->pdev->enable_cnt) != 1) - return 0; - /* Don't shut down the power for emulation and FPGA */ - if (CHIP_REV_IS_SLOW(bp)) - return 0; - - pmcsr &= ~PCI_PM_CTRL_STATE_MASK; - pmcsr |= 3; - - if (bp->wol) - pmcsr |= PCI_PM_CTRL_PME_ENABLE; - - pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, - pmcsr); - - /* No more memory access after this point until - * device is brought back to D0. - */ - break; - - default: - return -EINVAL; - } - return 0; -} - -static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp) -{ - u16 rx_cons_sb; - - /* Tell compiler that status block fields can change */ - barrier(); - rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb); - if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT) - rx_cons_sb++; - return (fp->rx_comp_cons != rx_cons_sb); -} - -/* - * net_device service functions - */ - -static int bnx2x_poll(struct napi_struct *napi, int budget) -{ - int work_done = 0; - struct bnx2x_fastpath *fp = container_of(napi, struct bnx2x_fastpath, - napi); - struct bnx2x *bp = fp->bp; - - while (1) { -#ifdef BNX2X_STOP_ON_ERROR - if (unlikely(bp->panic)) { - napi_complete(napi); - return 0; - } -#endif - - if (bnx2x_has_tx_work(fp)) - bnx2x_tx_int(fp); - - if (bnx2x_has_rx_work(fp)) { - work_done += bnx2x_rx_int(fp, budget - work_done); - - /* must not complete if we consumed full budget */ - if (work_done >= budget) - break; - } - - /* Fall out from the NAPI loop if needed */ - if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) { - bnx2x_update_fpsb_idx(fp); - /* bnx2x_has_rx_work() reads the status block, thus we need - * to ensure that status block indices have been actually read - * (bnx2x_update_fpsb_idx) prior to this check - * (bnx2x_has_rx_work) so that we won't write the "newer" - * value of the status block to IGU (if there was a DMA right - * after bnx2x_has_rx_work and if there is no rmb, the memory - * reading (bnx2x_update_fpsb_idx) may be postponed to right - * before bnx2x_ack_sb). In this case there will never be - * another interrupt until there is another update of the - * status block, while there is still unhandled work. - */ - rmb(); - - if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) { - napi_complete(napi); - /* Re-enable interrupts */ - bnx2x_ack_sb(bp, fp->sb_id, CSTORM_ID, - le16_to_cpu(fp->fp_c_idx), - IGU_INT_NOP, 1); - bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID, - le16_to_cpu(fp->fp_u_idx), - IGU_INT_ENABLE, 1); - break; - } - } - } - - return work_done; -} - - -/* we split the first BD into headers and data BDs - * to ease the pain of our fellow microcode engineers - * we use one mapping for both BDs - * So far this has only been observed to happen - * in Other Operating Systems(TM) - */ -static noinline u16 bnx2x_tx_split(struct bnx2x *bp, - struct bnx2x_fastpath *fp, - struct sw_tx_bd *tx_buf, - struct eth_tx_start_bd **tx_bd, u16 hlen, - u16 bd_prod, int nbd) -{ - struct eth_tx_start_bd *h_tx_bd = *tx_bd; - struct eth_tx_bd *d_tx_bd; - dma_addr_t mapping; - int old_len = le16_to_cpu(h_tx_bd->nbytes); - - /* first fix first BD */ - h_tx_bd->nbd = cpu_to_le16(nbd); - h_tx_bd->nbytes = cpu_to_le16(hlen); - - DP(NETIF_MSG_TX_QUEUED, "TSO split header size is %d " - "(%x:%x) nbd %d\n", h_tx_bd->nbytes, h_tx_bd->addr_hi, - h_tx_bd->addr_lo, h_tx_bd->nbd); - - /* now get a new data BD - * (after the pbd) and fill it */ - bd_prod = TX_BD(NEXT_TX_IDX(bd_prod)); - d_tx_bd = &fp->tx_desc_ring[bd_prod].reg_bd; - - mapping = HILO_U64(le32_to_cpu(h_tx_bd->addr_hi), - le32_to_cpu(h_tx_bd->addr_lo)) + hlen; - - d_tx_bd->addr_hi = cpu_to_le32(U64_HI(mapping)); - d_tx_bd->addr_lo = cpu_to_le32(U64_LO(mapping)); - d_tx_bd->nbytes = cpu_to_le16(old_len - hlen); - - /* this marks the BD as one that has no individual mapping */ - tx_buf->flags |= BNX2X_TSO_SPLIT_BD; - - DP(NETIF_MSG_TX_QUEUED, - "TSO split data size is %d (%x:%x)\n", - d_tx_bd->nbytes, d_tx_bd->addr_hi, d_tx_bd->addr_lo); - - /* update tx_bd */ - *tx_bd = (struct eth_tx_start_bd *)d_tx_bd; - - return bd_prod; -} - -static inline u16 bnx2x_csum_fix(unsigned char *t_header, u16 csum, s8 fix) -{ - if (fix > 0) - csum = (u16) ~csum_fold(csum_sub(csum, - csum_partial(t_header - fix, fix, 0))); - - else if (fix < 0) - csum = (u16) ~csum_fold(csum_add(csum, - csum_partial(t_header, -fix, 0))); - - return swab16(csum); -} - -static inline u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb) -{ - u32 rc; - - if (skb->ip_summed != CHECKSUM_PARTIAL) - rc = XMIT_PLAIN; - - else { - if (skb->protocol == htons(ETH_P_IPV6)) { - rc = XMIT_CSUM_V6; - if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) - rc |= XMIT_CSUM_TCP; - - } else { - rc = XMIT_CSUM_V4; - if (ip_hdr(skb)->protocol == IPPROTO_TCP) - rc |= XMIT_CSUM_TCP; - } - } - - if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) - rc |= (XMIT_GSO_V4 | XMIT_CSUM_V4 | XMIT_CSUM_TCP); - - else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) - rc |= (XMIT_GSO_V6 | XMIT_CSUM_TCP | XMIT_CSUM_V6); - - return rc; -} - -#if (MAX_SKB_FRAGS >= MAX_FETCH_BD - 3) -/* check if packet requires linearization (packet is too fragmented) - no need to check fragmentation if page size > 8K (there will be no - violation to FW restrictions) */ -static int bnx2x_pkt_req_lin(struct bnx2x *bp, struct sk_buff *skb, - u32 xmit_type) -{ - int to_copy = 0; - int hlen = 0; - int first_bd_sz = 0; - - /* 3 = 1 (for linear data BD) + 2 (for PBD and last BD) */ - if (skb_shinfo(skb)->nr_frags >= (MAX_FETCH_BD - 3)) { - - if (xmit_type & XMIT_GSO) { - unsigned short lso_mss = skb_shinfo(skb)->gso_size; - /* Check if LSO packet needs to be copied: - 3 = 1 (for headers BD) + 2 (for PBD and last BD) */ - int wnd_size = MAX_FETCH_BD - 3; - /* Number of windows to check */ - int num_wnds = skb_shinfo(skb)->nr_frags - wnd_size; - int wnd_idx = 0; - int frag_idx = 0; - u32 wnd_sum = 0; - - /* Headers length */ - hlen = (int)(skb_transport_header(skb) - skb->data) + - tcp_hdrlen(skb); - - /* Amount of data (w/o headers) on linear part of SKB*/ - first_bd_sz = skb_headlen(skb) - hlen; - - wnd_sum = first_bd_sz; - - /* Calculate the first sum - it's special */ - for (frag_idx = 0; frag_idx < wnd_size - 1; frag_idx++) - wnd_sum += - skb_shinfo(skb)->frags[frag_idx].size; - - /* If there was data on linear skb data - check it */ - if (first_bd_sz > 0) { - if (unlikely(wnd_sum < lso_mss)) { - to_copy = 1; - goto exit_lbl; - } - - wnd_sum -= first_bd_sz; - } - - /* Others are easier: run through the frag list and - check all windows */ - for (wnd_idx = 0; wnd_idx <= num_wnds; wnd_idx++) { - wnd_sum += - skb_shinfo(skb)->frags[wnd_idx + wnd_size - 1].size; - - if (unlikely(wnd_sum < lso_mss)) { - to_copy = 1; - break; - } - wnd_sum -= - skb_shinfo(skb)->frags[wnd_idx].size; - } - } else { - /* in non-LSO too fragmented packet should always - be linearized */ - to_copy = 1; - } - } - -exit_lbl: - if (unlikely(to_copy)) - DP(NETIF_MSG_TX_QUEUED, - "Linearization IS REQUIRED for %s packet. " - "num_frags %d hlen %d first_bd_sz %d\n", - (xmit_type & XMIT_GSO) ? "LSO" : "non-LSO", - skb_shinfo(skb)->nr_frags, hlen, first_bd_sz); - - return to_copy; -} -#endif - -/* called with netif_tx_lock - * bnx2x_tx_int() runs without netif_tx_lock unless it needs to call - * netif_wake_queue() - */ -static netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct bnx2x *bp = netdev_priv(dev); - struct bnx2x_fastpath *fp; - struct netdev_queue *txq; - struct sw_tx_bd *tx_buf; - struct eth_tx_start_bd *tx_start_bd; - struct eth_tx_bd *tx_data_bd, *total_pkt_bd = NULL; - struct eth_tx_parse_bd *pbd = NULL; - u16 pkt_prod, bd_prod; - int nbd, fp_index; - dma_addr_t mapping; - u32 xmit_type = bnx2x_xmit_type(bp, skb); - int i; - u8 hlen = 0; - __le16 pkt_size = 0; - struct ethhdr *eth; - u8 mac_type = UNICAST_ADDRESS; - -#ifdef BNX2X_STOP_ON_ERROR - if (unlikely(bp->panic)) - return NETDEV_TX_BUSY; -#endif - - fp_index = skb_get_queue_mapping(skb); - txq = netdev_get_tx_queue(dev, fp_index); - - fp = &bp->fp[fp_index]; - - if (unlikely(bnx2x_tx_avail(fp) < (skb_shinfo(skb)->nr_frags + 3))) { - fp->eth_q_stats.driver_xoff++; - netif_tx_stop_queue(txq); - BNX2X_ERR("BUG! Tx ring full when queue awake!\n"); - return NETDEV_TX_BUSY; - } - - DP(NETIF_MSG_TX_QUEUED, "SKB: summed %x protocol %x protocol(%x,%x)" - " gso type %x xmit_type %x\n", - skb->ip_summed, skb->protocol, ipv6_hdr(skb)->nexthdr, - ip_hdr(skb)->protocol, skb_shinfo(skb)->gso_type, xmit_type); - - eth = (struct ethhdr *)skb->data; - - /* set flag according to packet type (UNICAST_ADDRESS is default)*/ - if (unlikely(is_multicast_ether_addr(eth->h_dest))) { - if (is_broadcast_ether_addr(eth->h_dest)) - mac_type = BROADCAST_ADDRESS; - else - mac_type = MULTICAST_ADDRESS; - } - -#if (MAX_SKB_FRAGS >= MAX_FETCH_BD - 3) - /* First, check if we need to linearize the skb (due to FW - restrictions). No need to check fragmentation if page size > 8K - (there will be no violation to FW restrictions) */ - if (bnx2x_pkt_req_lin(bp, skb, xmit_type)) { - /* Statistics of linearization */ - bp->lin_cnt++; - if (skb_linearize(skb) != 0) { - DP(NETIF_MSG_TX_QUEUED, "SKB linearization failed - " - "silently dropping this SKB\n"); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - } -#endif - - /* - Please read carefully. First we use one BD which we mark as start, - then we have a parsing info BD (used for TSO or xsum), - and only then we have the rest of the TSO BDs. - (don't forget to mark the last one as last, - and to unmap only AFTER you write to the BD ...) - And above all, all pdb sizes are in words - NOT DWORDS! - */ - - pkt_prod = fp->tx_pkt_prod++; - bd_prod = TX_BD(fp->tx_bd_prod); - - /* get a tx_buf and first BD */ - tx_buf = &fp->tx_buf_ring[TX_BD(pkt_prod)]; - tx_start_bd = &fp->tx_desc_ring[bd_prod].start_bd; - - tx_start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD; - tx_start_bd->general_data = (mac_type << - ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT); - /* header nbd */ - tx_start_bd->general_data |= (1 << ETH_TX_START_BD_HDR_NBDS_SHIFT); - - /* remember the first BD of the packet */ - tx_buf->first_bd = fp->tx_bd_prod; - tx_buf->skb = skb; - tx_buf->flags = 0; - - DP(NETIF_MSG_TX_QUEUED, - "sending pkt %u @%p next_idx %u bd %u @%p\n", - pkt_prod, tx_buf, fp->tx_pkt_prod, bd_prod, tx_start_bd); - -#ifdef BCM_VLAN - if ((bp->vlgrp != NULL) && vlan_tx_tag_present(skb) && - (bp->flags & HW_VLAN_TX_FLAG)) { - tx_start_bd->vlan = cpu_to_le16(vlan_tx_tag_get(skb)); - tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_VLAN_TAG; - } else -#endif - tx_start_bd->vlan = cpu_to_le16(pkt_prod); - - /* turn on parsing and get a BD */ - bd_prod = TX_BD(NEXT_TX_IDX(bd_prod)); - pbd = &fp->tx_desc_ring[bd_prod].parse_bd; - - memset(pbd, 0, sizeof(struct eth_tx_parse_bd)); - - if (xmit_type & XMIT_CSUM) { - hlen = (skb_network_header(skb) - skb->data) / 2; - - /* for now NS flag is not used in Linux */ - pbd->global_data = - (hlen | ((skb->protocol == cpu_to_be16(ETH_P_8021Q)) << - ETH_TX_PARSE_BD_LLC_SNAP_EN_SHIFT)); - - pbd->ip_hlen = (skb_transport_header(skb) - - skb_network_header(skb)) / 2; - - hlen += pbd->ip_hlen + tcp_hdrlen(skb) / 2; - - pbd->total_hlen = cpu_to_le16(hlen); - hlen = hlen*2; - - tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_L4_CSUM; - - if (xmit_type & XMIT_CSUM_V4) - tx_start_bd->bd_flags.as_bitfield |= - ETH_TX_BD_FLAGS_IP_CSUM; - else - tx_start_bd->bd_flags.as_bitfield |= - ETH_TX_BD_FLAGS_IPV6; - - if (xmit_type & XMIT_CSUM_TCP) { - pbd->tcp_pseudo_csum = swab16(tcp_hdr(skb)->check); - - } else { - s8 fix = SKB_CS_OFF(skb); /* signed! */ - - pbd->global_data |= ETH_TX_PARSE_BD_UDP_CS_FLG; - - DP(NETIF_MSG_TX_QUEUED, - "hlen %d fix %d csum before fix %x\n", - le16_to_cpu(pbd->total_hlen), fix, SKB_CS(skb)); - - /* HW bug: fixup the CSUM */ - pbd->tcp_pseudo_csum = - bnx2x_csum_fix(skb_transport_header(skb), - SKB_CS(skb), fix); - - DP(NETIF_MSG_TX_QUEUED, "csum after fix %x\n", - pbd->tcp_pseudo_csum); - } - } - - mapping = dma_map_single(&bp->pdev->dev, skb->data, - skb_headlen(skb), DMA_TO_DEVICE); - - tx_start_bd->addr_hi = cpu_to_le32(U64_HI(mapping)); - tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping)); - nbd = skb_shinfo(skb)->nr_frags + 2; /* start_bd + pbd + frags */ - tx_start_bd->nbd = cpu_to_le16(nbd); - tx_start_bd->nbytes = cpu_to_le16(skb_headlen(skb)); - pkt_size = tx_start_bd->nbytes; - - DP(NETIF_MSG_TX_QUEUED, "first bd @%p addr (%x:%x) nbd %d" - " nbytes %d flags %x vlan %x\n", - tx_start_bd, tx_start_bd->addr_hi, tx_start_bd->addr_lo, - le16_to_cpu(tx_start_bd->nbd), le16_to_cpu(tx_start_bd->nbytes), - tx_start_bd->bd_flags.as_bitfield, le16_to_cpu(tx_start_bd->vlan)); - - if (xmit_type & XMIT_GSO) { - - DP(NETIF_MSG_TX_QUEUED, - "TSO packet len %d hlen %d total len %d tso size %d\n", - skb->len, hlen, skb_headlen(skb), - skb_shinfo(skb)->gso_size); - - tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_SW_LSO; - - if (unlikely(skb_headlen(skb) > hlen)) - bd_prod = bnx2x_tx_split(bp, fp, tx_buf, &tx_start_bd, - hlen, bd_prod, ++nbd); - - pbd->lso_mss = cpu_to_le16(skb_shinfo(skb)->gso_size); - pbd->tcp_send_seq = swab32(tcp_hdr(skb)->seq); - pbd->tcp_flags = pbd_tcp_flags(skb); - - if (xmit_type & XMIT_GSO_V4) { - pbd->ip_id = swab16(ip_hdr(skb)->id); - pbd->tcp_pseudo_csum = - swab16(~csum_tcpudp_magic(ip_hdr(skb)->saddr, - ip_hdr(skb)->daddr, - 0, IPPROTO_TCP, 0)); - - } else - pbd->tcp_pseudo_csum = - swab16(~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, - &ipv6_hdr(skb)->daddr, - 0, IPPROTO_TCP, 0)); - - pbd->global_data |= ETH_TX_PARSE_BD_PSEUDO_CS_WITHOUT_LEN; - } - tx_data_bd = (struct eth_tx_bd *)tx_start_bd; - - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - - bd_prod = TX_BD(NEXT_TX_IDX(bd_prod)); - tx_data_bd = &fp->tx_desc_ring[bd_prod].reg_bd; - if (total_pkt_bd == NULL) - total_pkt_bd = &fp->tx_desc_ring[bd_prod].reg_bd; - - mapping = dma_map_page(&bp->pdev->dev, frag->page, - frag->page_offset, - frag->size, DMA_TO_DEVICE); - - tx_data_bd->addr_hi = cpu_to_le32(U64_HI(mapping)); - tx_data_bd->addr_lo = cpu_to_le32(U64_LO(mapping)); - tx_data_bd->nbytes = cpu_to_le16(frag->size); - le16_add_cpu(&pkt_size, frag->size); - - DP(NETIF_MSG_TX_QUEUED, - "frag %d bd @%p addr (%x:%x) nbytes %d\n", - i, tx_data_bd, tx_data_bd->addr_hi, tx_data_bd->addr_lo, - le16_to_cpu(tx_data_bd->nbytes)); - } - - DP(NETIF_MSG_TX_QUEUED, "last bd @%p\n", tx_data_bd); - - bd_prod = TX_BD(NEXT_TX_IDX(bd_prod)); - - /* now send a tx doorbell, counting the next BD - * if the packet contains or ends with it - */ - if (TX_BD_POFF(bd_prod) < nbd) - nbd++; - - if (total_pkt_bd != NULL) - total_pkt_bd->total_pkt_bytes = pkt_size; - - if (pbd) - DP(NETIF_MSG_TX_QUEUED, - "PBD @%p ip_data %x ip_hlen %u ip_id %u lso_mss %u" - " tcp_flags %x xsum %x seq %u hlen %u\n", - pbd, pbd->global_data, pbd->ip_hlen, pbd->ip_id, - pbd->lso_mss, pbd->tcp_flags, pbd->tcp_pseudo_csum, - pbd->tcp_send_seq, le16_to_cpu(pbd->total_hlen)); - - DP(NETIF_MSG_TX_QUEUED, "doorbell: nbd %d bd %u\n", nbd, bd_prod); - - /* - * Make sure that the BD data is updated before updating the producer - * since FW might read the BD right after the producer is updated. - * This is only applicable for weak-ordered memory model archs such - * as IA-64. The following barrier is also mandatory since FW will - * assumes packets must have BDs. - */ - wmb(); - - fp->tx_db.data.prod += nbd; - barrier(); - DOORBELL(bp, fp->index, fp->tx_db.raw); - - mmiowb(); - - fp->tx_bd_prod += nbd; - - if (unlikely(bnx2x_tx_avail(fp) < MAX_SKB_FRAGS + 3)) { - netif_tx_stop_queue(txq); - - /* paired memory barrier is in bnx2x_tx_int(), we have to keep - * ordering of set_bit() in netif_tx_stop_queue() and read of - * fp->bd_tx_cons */ - smp_mb(); - - fp->eth_q_stats.driver_xoff++; - if (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3) - netif_tx_wake_queue(txq); - } - fp->tx_pkt++; - - return NETDEV_TX_OK; -} - /* called with rtnl_lock */ static int bnx2x_open(struct net_device *dev) { @@ -12591,7 +6849,7 @@ static int bnx2x_close(struct net_device *dev) } /* called with netif_tx_lock from dev_mcast.c */ -static void bnx2x_set_rx_mode(struct net_device *dev) +void bnx2x_set_rx_mode(struct net_device *dev) { struct bnx2x *bp = netdev_priv(dev); u32 rx_mode = BNX2X_RX_MODE_NORMAL; @@ -12711,25 +6969,6 @@ static void bnx2x_set_rx_mode(struct net_device *dev) bnx2x_set_storm_rx_mode(bp); } -/* called with rtnl_lock */ -static int bnx2x_change_mac_addr(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - struct bnx2x *bp = netdev_priv(dev); - - if (!is_valid_ether_addr((u8 *)(addr->sa_data))) - return -EINVAL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - if (netif_running(dev)) { - if (CHIP_IS_E1(bp)) - bnx2x_set_eth_mac_addr_e1(bp, 1); - else - bnx2x_set_eth_mac_addr_e1h(bp, 1); - } - - return 0; -} /* called with rtnl_lock */ static int bnx2x_mdio_read(struct net_device *netdev, int prtad, @@ -12805,71 +7044,6 @@ static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return mdio_mii_ioctl(&bp->mdio, mdio, cmd); } -/* called with rtnl_lock */ -static int bnx2x_change_mtu(struct net_device *dev, int new_mtu) -{ - struct bnx2x *bp = netdev_priv(dev); - int rc = 0; - - if (bp->recovery_state != BNX2X_RECOVERY_DONE) { - printk(KERN_ERR "Handling parity error recovery. Try again later\n"); - return -EAGAIN; - } - - if ((new_mtu > ETH_MAX_JUMBO_PACKET_SIZE) || - ((new_mtu + ETH_HLEN) < ETH_MIN_PACKET_SIZE)) - return -EINVAL; - - /* This does not race with packet allocation - * because the actual alloc size is - * only updated as part of load - */ - dev->mtu = new_mtu; - - if (netif_running(dev)) { - bnx2x_nic_unload(bp, UNLOAD_NORMAL); - rc = bnx2x_nic_load(bp, LOAD_NORMAL); - } - - return rc; -} - -static void bnx2x_tx_timeout(struct net_device *dev) -{ - struct bnx2x *bp = netdev_priv(dev); - -#ifdef BNX2X_STOP_ON_ERROR - if (!bp->panic) - bnx2x_panic(); -#endif - /* This allows the netif to be shutdown gracefully before resetting */ - schedule_delayed_work(&bp->reset_task, 0); -} - -#ifdef BCM_VLAN -/* called with rtnl_lock */ -static void bnx2x_vlan_rx_register(struct net_device *dev, - struct vlan_group *vlgrp) -{ - struct bnx2x *bp = netdev_priv(dev); - - bp->vlgrp = vlgrp; - - /* Set flags according to the required capabilities */ - bp->flags &= ~(HW_VLAN_RX_FLAG | HW_VLAN_TX_FLAG); - - if (dev->features & NETIF_F_HW_VLAN_TX) - bp->flags |= HW_VLAN_TX_FLAG; - - if (dev->features & NETIF_F_HW_VLAN_RX) - bp->flags |= HW_VLAN_RX_FLAG; - - if (netif_running(dev)) - bnx2x_set_client_config(bp); -} - -#endif - #ifdef CONFIG_NET_POLL_CONTROLLER static void poll_bnx2x(struct net_device *dev) { @@ -13018,7 +7192,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, dev->watchdog_timeo = TX_TIMEOUT; dev->netdev_ops = &bnx2x_netdev_ops; - dev->ethtool_ops = &bnx2x_ethtool_ops; + bnx2x_set_ethtool_ops(dev); dev->features |= NETIF_F_SG; dev->features |= NETIF_F_HW_CSUM; if (bp->flags & USING_DAC_FLAG) @@ -13371,73 +7545,6 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); } -static int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct bnx2x *bp; - - if (!dev) { - dev_err(&pdev->dev, "BAD net device from bnx2x_init_one\n"); - return -ENODEV; - } - bp = netdev_priv(dev); - - rtnl_lock(); - - pci_save_state(pdev); - - if (!netif_running(dev)) { - rtnl_unlock(); - return 0; - } - - netif_device_detach(dev); - - bnx2x_nic_unload(bp, UNLOAD_CLOSE); - - bnx2x_set_power_state(bp, pci_choose_state(pdev, state)); - - rtnl_unlock(); - - return 0; -} - -static int bnx2x_resume(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct bnx2x *bp; - int rc; - - if (!dev) { - dev_err(&pdev->dev, "BAD net device from bnx2x_init_one\n"); - return -ENODEV; - } - bp = netdev_priv(dev); - - if (bp->recovery_state != BNX2X_RECOVERY_DONE) { - printk(KERN_ERR "Handling parity error recovery. Try again later\n"); - return -EAGAIN; - } - - rtnl_lock(); - - pci_restore_state(pdev); - - if (!netif_running(dev)) { - rtnl_unlock(); - return 0; - } - - bnx2x_set_power_state(bp, PCI_D0); - netif_device_attach(dev); - - rc = bnx2x_nic_load(bp, LOAD_OPEN); - - rtnl_unlock(); - - return rc; -} - static int bnx2x_eeh_nic_unload(struct bnx2x *bp) { int i; @@ -13759,7 +7866,7 @@ static int bnx2x_cnic_ctl_send_bh(struct bnx2x *bp, struct cnic_ctl_info *ctl) /* * for commands that have no data */ -static int bnx2x_cnic_notify(struct bnx2x *bp, int cmd) +int bnx2x_cnic_notify(struct bnx2x *bp, int cmd) { struct cnic_ctl_info ctl = {0}; @@ -13827,7 +7934,7 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl) return rc; } -static void bnx2x_setup_cnic_irq_info(struct bnx2x *bp) +void bnx2x_setup_cnic_irq_info(struct bnx2x *bp) { struct cnic_eth_dev *cp = &bp->cnic_eth_dev; diff --git a/drivers/net/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h index a1f3bf0cd63..a1f3bf0cd63 100644 --- a/drivers/net/bnx2x_reg.h +++ b/drivers/net/bnx2x/bnx2x_reg.h diff --git a/drivers/net/bnx2x/bnx2x_stats.c b/drivers/net/bnx2x/bnx2x_stats.c new file mode 100644 index 00000000000..c7472446102 --- /dev/null +++ b/drivers/net/bnx2x/bnx2x_stats.c @@ -0,0 +1,1411 @@ +/* bnx2x_stats.c: Broadcom Everest network driver. + * + * Copyright (c) 2007-2010 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * Maintained by: Eilon Greenstein <eilong@broadcom.com> + * Written by: Eliezer Tamir + * Based on code from Michael Chan's bnx2 driver + * UDP CSUM errata workaround by Arik Gendelman + * Slowpath and fastpath rework by Vladislav Zolotarov + * Statistics and Link management by Yitchak Gertner + * + */ + #include "bnx2x_cmn.h" + #include "bnx2x_stats.h" + +/* Statistics */ + +/**************************************************************************** +* Macros +****************************************************************************/ + +/* sum[hi:lo] += add[hi:lo] */ +#define ADD_64(s_hi, a_hi, s_lo, a_lo) \ + do { \ + s_lo += a_lo; \ + s_hi += a_hi + ((s_lo < a_lo) ? 1 : 0); \ + } while (0) + +/* difference = minuend - subtrahend */ +#define DIFF_64(d_hi, m_hi, s_hi, d_lo, m_lo, s_lo) \ + do { \ + if (m_lo < s_lo) { \ + /* underflow */ \ + d_hi = m_hi - s_hi; \ + if (d_hi > 0) { \ + /* we can 'loan' 1 */ \ + d_hi--; \ + d_lo = m_lo + (UINT_MAX - s_lo) + 1; \ + } else { \ + /* m_hi <= s_hi */ \ + d_hi = 0; \ + d_lo = 0; \ + } \ + } else { \ + /* m_lo >= s_lo */ \ + if (m_hi < s_hi) { \ + d_hi = 0; \ + d_lo = 0; \ + } else { \ + /* m_hi >= s_hi */ \ + d_hi = m_hi - s_hi; \ + d_lo = m_lo - s_lo; \ + } \ + } \ + } while (0) + +#define UPDATE_STAT64(s, t) \ + do { \ + DIFF_64(diff.hi, new->s##_hi, pstats->mac_stx[0].t##_hi, \ + diff.lo, new->s##_lo, pstats->mac_stx[0].t##_lo); \ + pstats->mac_stx[0].t##_hi = new->s##_hi; \ + pstats->mac_stx[0].t##_lo = new->s##_lo; \ + ADD_64(pstats->mac_stx[1].t##_hi, diff.hi, \ + pstats->mac_stx[1].t##_lo, diff.lo); \ + } while (0) + +#define UPDATE_STAT64_NIG(s, t) \ + do { \ + DIFF_64(diff.hi, new->s##_hi, old->s##_hi, \ + diff.lo, new->s##_lo, old->s##_lo); \ + ADD_64(estats->t##_hi, diff.hi, \ + estats->t##_lo, diff.lo); \ + } while (0) + +/* sum[hi:lo] += add */ +#define ADD_EXTEND_64(s_hi, s_lo, a) \ + do { \ + s_lo += a; \ + s_hi += (s_lo < a) ? 1 : 0; \ + } while (0) + +#define UPDATE_EXTEND_STAT(s) \ + do { \ + ADD_EXTEND_64(pstats->mac_stx[1].s##_hi, \ + pstats->mac_stx[1].s##_lo, \ + new->s); \ + } while (0) + +#define UPDATE_EXTEND_TSTAT(s, t) \ + do { \ + diff = le32_to_cpu(tclient->s) - le32_to_cpu(old_tclient->s); \ + old_tclient->s = tclient->s; \ + ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \ + } while (0) + +#define UPDATE_EXTEND_USTAT(s, t) \ + do { \ + diff = le32_to_cpu(uclient->s) - le32_to_cpu(old_uclient->s); \ + old_uclient->s = uclient->s; \ + ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \ + } while (0) + +#define UPDATE_EXTEND_XSTAT(s, t) \ + do { \ + diff = le32_to_cpu(xclient->s) - le32_to_cpu(old_xclient->s); \ + old_xclient->s = xclient->s; \ + ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \ + } while (0) + +/* minuend -= subtrahend */ +#define SUB_64(m_hi, s_hi, m_lo, s_lo) \ + do { \ + DIFF_64(m_hi, m_hi, s_hi, m_lo, m_lo, s_lo); \ + } while (0) + +/* minuend[hi:lo] -= subtrahend */ +#define SUB_EXTEND_64(m_hi, m_lo, s) \ + do { \ + SUB_64(m_hi, 0, m_lo, s); \ + } while (0) + +#define SUB_EXTEND_USTAT(s, t) \ + do { \ + diff = le32_to_cpu(uclient->s) - le32_to_cpu(old_uclient->s); \ + SUB_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \ + } while (0) + +/* + * General service functions + */ + +static inline long bnx2x_hilo(u32 *hiref) +{ + u32 lo = *(hiref + 1); +#if (BITS_PER_LONG == 64) + u32 hi = *hiref; + + return HILO_U64(hi, lo); +#else + return lo; +#endif +} + +/* + * Init service functions + */ + + +static void bnx2x_storm_stats_post(struct bnx2x *bp) +{ + if (!bp->stats_pending) { + struct eth_query_ramrod_data ramrod_data = {0}; + int i, rc; + + spin_lock_bh(&bp->stats_lock); + + ramrod_data.drv_counter = bp->stats_counter++; + ramrod_data.collect_port = bp->port.pmf ? 1 : 0; + for_each_queue(bp, i) + ramrod_data.ctr_id_vector |= (1 << bp->fp[i].cl_id); + + rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_STAT_QUERY, 0, + ((u32 *)&ramrod_data)[1], + ((u32 *)&ramrod_data)[0], 0); + if (rc == 0) { + /* stats ramrod has it's own slot on the spq */ + bp->spq_left++; + bp->stats_pending = 1; + } + + spin_unlock_bh(&bp->stats_lock); + } +} + +static void bnx2x_hw_stats_post(struct bnx2x *bp) +{ + struct dmae_command *dmae = &bp->stats_dmae; + u32 *stats_comp = bnx2x_sp(bp, stats_comp); + + *stats_comp = DMAE_COMP_VAL; + if (CHIP_REV_IS_SLOW(bp)) + return; + + /* loader */ + if (bp->executer_idx) { + int loader_idx = PMF_DMAE_C(bp); + + memset(dmae, 0, sizeof(struct dmae_command)); + + dmae->opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC | + DMAE_CMD_C_DST_GRC | DMAE_CMD_C_ENABLE | + DMAE_CMD_DST_RESET | +#ifdef __BIG_ENDIAN + DMAE_CMD_ENDIANITY_B_DW_SWAP | +#else + DMAE_CMD_ENDIANITY_DW_SWAP | +#endif + (BP_PORT(bp) ? DMAE_CMD_PORT_1 : + DMAE_CMD_PORT_0) | + (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT)); + dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, dmae[0])); + dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, dmae[0])); + dmae->dst_addr_lo = (DMAE_REG_CMD_MEM + + sizeof(struct dmae_command) * + (loader_idx + 1)) >> 2; + dmae->dst_addr_hi = 0; + dmae->len = sizeof(struct dmae_command) >> 2; + if (CHIP_IS_E1(bp)) + dmae->len--; + dmae->comp_addr_lo = dmae_reg_go_c[loader_idx + 1] >> 2; + dmae->comp_addr_hi = 0; + dmae->comp_val = 1; + + *stats_comp = 0; + bnx2x_post_dmae(bp, dmae, loader_idx); + + } else if (bp->func_stx) { + *stats_comp = 0; + bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp)); + } +} + +static int bnx2x_stats_comp(struct bnx2x *bp) +{ + u32 *stats_comp = bnx2x_sp(bp, stats_comp); + int cnt = 10; + + might_sleep(); + while (*stats_comp != DMAE_COMP_VAL) { + if (!cnt) { + BNX2X_ERR("timeout waiting for stats finished\n"); + break; + } + cnt--; + msleep(1); + } + return 1; +} + +/* + * Statistics service functions + */ + +static void bnx2x_stats_pmf_update(struct bnx2x *bp) +{ + struct dmae_command *dmae; + u32 opcode; + int loader_idx = PMF_DMAE_C(bp); + u32 *stats_comp = bnx2x_sp(bp, stats_comp); + + /* sanity */ + if (!IS_E1HMF(bp) || !bp->port.pmf || !bp->port.port_stx) { + BNX2X_ERR("BUG!\n"); + return; + } + + bp->executer_idx = 0; + + opcode = (DMAE_CMD_SRC_GRC | DMAE_CMD_DST_PCI | + DMAE_CMD_C_ENABLE | + DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET | +#ifdef __BIG_ENDIAN + DMAE_CMD_ENDIANITY_B_DW_SWAP | +#else + DMAE_CMD_ENDIANITY_DW_SWAP | +#endif + (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) | + (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT)); + + dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); + dmae->opcode = (opcode | DMAE_CMD_C_DST_GRC); + dmae->src_addr_lo = bp->port.port_stx >> 2; + dmae->src_addr_hi = 0; + dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats)); + dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats)); + dmae->len = DMAE_LEN32_RD_MAX; + dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; + dmae->comp_addr_hi = 0; + dmae->comp_val = 1; + + dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); + dmae->opcode = (opcode | DMAE_CMD_C_DST_PCI); + dmae->src_addr_lo = (bp->port.port_stx >> 2) + DMAE_LEN32_RD_MAX; + dmae->src_addr_hi = 0; + dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats) + + DMAE_LEN32_RD_MAX * 4); + dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats) + + DMAE_LEN32_RD_MAX * 4); + dmae->len = (sizeof(struct host_port_stats) >> 2) - DMAE_LEN32_RD_MAX; + dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp)); + dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp)); + dmae->comp_val = DMAE_COMP_VAL; + + *stats_comp = 0; + bnx2x_hw_stats_post(bp); + bnx2x_stats_comp(bp); +} + +static void bnx2x_port_stats_init(struct bnx2x *bp) +{ + struct dmae_command *dmae; + int port = BP_PORT(bp); + int vn = BP_E1HVN(bp); + u32 opcode; + int loader_idx = PMF_DMAE_C(bp); + u32 mac_addr; + u32 *stats_comp = bnx2x_sp(bp, stats_comp); + + /* sanity */ + if (!bp->link_vars.link_up || !bp->port.pmf) { + BNX2X_ERR("BUG!\n"); + return; + } + + bp->executer_idx = 0; + + /* MCP */ + opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC | + DMAE_CMD_C_DST_GRC | DMAE_CMD_C_ENABLE | + DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET | +#ifdef __BIG_ENDIAN + DMAE_CMD_ENDIANITY_B_DW_SWAP | +#else + DMAE_CMD_ENDIANITY_DW_SWAP | +#endif + (port ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) | + (vn << DMAE_CMD_E1HVN_SHIFT)); + + if (bp->port.port_stx) { + + dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); + dmae->opcode = opcode; + dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats)); + dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats)); + dmae->dst_addr_lo = bp->port.port_stx >> 2; + dmae->dst_addr_hi = 0; + dmae->len = sizeof(struct host_port_stats) >> 2; + dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; + dmae->comp_addr_hi = 0; + dmae->comp_val = 1; + } + + if (bp->func_stx) { + + dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); + dmae->opcode = opcode; + dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, func_stats)); + dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, func_stats)); + dmae->dst_addr_lo = bp->func_stx >> 2; + dmae->dst_addr_hi = 0; + dmae->len = sizeof(struct host_func_stats) >> 2; + dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; + dmae->comp_addr_hi = 0; + dmae->comp_val = 1; + } + + /* MAC */ + opcode = (DMAE_CMD_SRC_GRC | DMAE_CMD_DST_PCI | + DMAE_CMD_C_DST_GRC | DMAE_CMD_C_ENABLE | + DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET | +#ifdef __BIG_ENDIAN + DMAE_CMD_ENDIANITY_B_DW_SWAP | +#else + DMAE_CMD_ENDIANITY_DW_SWAP | +#endif + (port ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) | + (vn << DMAE_CMD_E1HVN_SHIFT)); + + if (bp->link_vars.mac_type == MAC_TYPE_BMAC) { + + mac_addr = (port ? NIG_REG_INGRESS_BMAC1_MEM : + NIG_REG_INGRESS_BMAC0_MEM); + + /* BIGMAC_REGISTER_TX_STAT_GTPKT .. + BIGMAC_REGISTER_TX_STAT_GTBYT */ + dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); + dmae->opcode = opcode; + dmae->src_addr_lo = (mac_addr + + BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2; + dmae->src_addr_hi = 0; + dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats)); + dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats)); + dmae->len = (8 + BIGMAC_REGISTER_TX_STAT_GTBYT - + BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2; + dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; + dmae->comp_addr_hi = 0; + dmae->comp_val = 1; + + /* BIGMAC_REGISTER_RX_STAT_GR64 .. + BIGMAC_REGISTER_RX_STAT_GRIPJ */ + dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); + dmae->opcode = opcode; + dmae->src_addr_lo = (mac_addr + + BIGMAC_REGISTER_RX_STAT_GR64) >> 2; + dmae->src_addr_hi = 0; + dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats) + + offsetof(struct bmac_stats, rx_stat_gr64_lo)); + dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats) + + offsetof(struct bmac_stats, rx_stat_gr64_lo)); + dmae->len = (8 + BIGMAC_REGISTER_RX_STAT_GRIPJ - + BIGMAC_REGISTER_RX_STAT_GR64) >> 2; + dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; + dmae->comp_addr_hi = 0; + dmae->comp_val = 1; + + } else if (bp->link_vars.mac_type == MAC_TYPE_EMAC) { + + mac_addr = (port ? GRCBASE_EMAC1 : GRCBASE_EMAC0); + + /* EMAC_REG_EMAC_RX_STAT_AC (EMAC_REG_EMAC_RX_STAT_AC_COUNT)*/ + dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); + dmae->opcode = opcode; + dmae->src_addr_lo = (mac_addr + + EMAC_REG_EMAC_RX_STAT_AC) >> 2; + dmae->src_addr_hi = 0; + dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats)); + dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats)); + dmae->len = EMAC_REG_EMAC_RX_STAT_AC_COUNT; + dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; + dmae->comp_addr_hi = 0; + dmae->comp_val = 1; + + /* EMAC_REG_EMAC_RX_STAT_AC_28 */ + dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); + dmae->opcode = opcode; + dmae->src_addr_lo = (mac_addr + + EMAC_REG_EMAC_RX_STAT_AC_28) >> 2; + dmae->src_addr_hi = 0; + dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats) + + offsetof(struct emac_stats, rx_stat_falsecarriererrors)); + dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats) + + offsetof(struct emac_stats, rx_stat_falsecarriererrors)); + dmae->len = 1; + dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; + dmae->comp_addr_hi = 0; + dmae->comp_val = 1; + + /* EMAC_REG_EMAC_TX_STAT_AC (EMAC_REG_EMAC_TX_STAT_AC_COUNT)*/ + dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); + dmae->opcode = opcode; + dmae->src_addr_lo = (mac_addr + + EMAC_REG_EMAC_TX_STAT_AC) >> 2; + dmae->src_addr_hi = 0; + dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats) + + offsetof(struct emac_stats, tx_stat_ifhcoutoctets)); + dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats) + + offsetof(struct emac_stats, tx_stat_ifhcoutoctets)); + dmae->len = EMAC_REG_EMAC_TX_STAT_AC_COUNT; + dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; + dmae->comp_addr_hi = 0; + dmae->comp_val = 1; + } + + /* NIG */ + dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); + dmae->opcode = opcode; + dmae->src_addr_lo = (port ? NIG_REG_STAT1_BRB_DISCARD : + NIG_REG_STAT0_BRB_DISCARD) >> 2; + dmae->src_addr_hi = 0; + dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats)); + dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats)); + dmae->len = (sizeof(struct nig_stats) - 4*sizeof(u32)) >> 2; + dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; + dmae->comp_addr_hi = 0; + dmae->comp_val = 1; + + dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); + dmae->opcode = opcode; + dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT0 : + NIG_REG_STAT0_EGRESS_MAC_PKT0) >> 2; + dmae->src_addr_hi = 0; + dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats) + + offsetof(struct nig_stats, egress_mac_pkt0_lo)); + dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats) + + offsetof(struct nig_stats, egress_mac_pkt0_lo)); + dmae->len = (2*sizeof(u32)) >> 2; + dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; + dmae->comp_addr_hi = 0; + dmae->comp_val = 1; + + dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); + dmae->opcode = (DMAE_CMD_SRC_GRC | DMAE_CMD_DST_PCI | + DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE | + DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET | +#ifdef __BIG_ENDIAN + DMAE_CMD_ENDIANITY_B_DW_SWAP | +#else + DMAE_CMD_ENDIANITY_DW_SWAP | +#endif + (port ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) | + (vn << DMAE_CMD_E1HVN_SHIFT)); + dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT1 : + NIG_REG_STAT0_EGRESS_MAC_PKT1) >> 2; + dmae->src_addr_hi = 0; + dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats) + + offsetof(struct nig_stats, egress_mac_pkt1_lo)); + dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats) + + offsetof(struct nig_stats, egress_mac_pkt1_lo)); + dmae->len = (2*sizeof(u32)) >> 2; + dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp)); + dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp)); + dmae->comp_val = DMAE_COMP_VAL; + + *stats_comp = 0; +} + +static void bnx2x_func_stats_init(struct bnx2x *bp) +{ + struct dmae_command *dmae = &bp->stats_dmae; + u32 *stats_comp = bnx2x_sp(bp, stats_comp); + + /* sanity */ + if (!bp->func_stx) { + BNX2X_ERR("BUG!\n"); + return; + } + + bp->executer_idx = 0; + memset(dmae, 0, sizeof(struct dmae_command)); + + dmae->opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC | + DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE | + DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET | +#ifdef __BIG_ENDIAN + DMAE_CMD_ENDIANITY_B_DW_SWAP | +#else + DMAE_CMD_ENDIANITY_DW_SWAP | +#endif + (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) | + (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT)); + dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, func_stats)); + dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, func_stats)); + dmae->dst_addr_lo = bp->func_stx >> 2; + dmae->dst_addr_hi = 0; + dmae->len = sizeof(struct host_func_stats) >> 2; + dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp)); + dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp)); + dmae->comp_val = DMAE_COMP_VAL; + + *stats_comp = 0; +} + +static void bnx2x_stats_start(struct bnx2x *bp) +{ + if (bp->port.pmf) + bnx2x_port_stats_init(bp); + + else if (bp->func_stx) + bnx2x_func_stats_init(bp); + + bnx2x_hw_stats_post(bp); + bnx2x_storm_stats_post(bp); +} + +static void bnx2x_stats_pmf_start(struct bnx2x *bp) +{ + bnx2x_stats_comp(bp); + bnx2x_stats_pmf_update(bp); + bnx2x_stats_start(bp); +} + +static void bnx2x_stats_restart(struct bnx2x *bp) +{ + bnx2x_stats_comp(bp); + bnx2x_stats_start(bp); +} + +static void bnx2x_bmac_stats_update(struct bnx2x *bp) +{ + struct bmac_stats *new = bnx2x_sp(bp, mac_stats.bmac_stats); + struct host_port_stats *pstats = bnx2x_sp(bp, port_stats); + struct bnx2x_eth_stats *estats = &bp->eth_stats; + struct { + u32 lo; + u32 hi; + } diff; + + UPDATE_STAT64(rx_stat_grerb, rx_stat_ifhcinbadoctets); + UPDATE_STAT64(rx_stat_grfcs, rx_stat_dot3statsfcserrors); + UPDATE_STAT64(rx_stat_grund, rx_stat_etherstatsundersizepkts); + UPDATE_STAT64(rx_stat_grovr, rx_stat_dot3statsframestoolong); + UPDATE_STAT64(rx_stat_grfrg, rx_stat_etherstatsfragments); + UPDATE_STAT64(rx_stat_grjbr, rx_stat_etherstatsjabbers); + UPDATE_STAT64(rx_stat_grxcf, rx_stat_maccontrolframesreceived); + UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffstateentered); + UPDATE_STAT64(rx_stat_grxpf, rx_stat_bmac_xpf); + UPDATE_STAT64(tx_stat_gtxpf, tx_stat_outxoffsent); + UPDATE_STAT64(tx_stat_gtxpf, tx_stat_flowcontroldone); + UPDATE_STAT64(tx_stat_gt64, tx_stat_etherstatspkts64octets); + UPDATE_STAT64(tx_stat_gt127, + tx_stat_etherstatspkts65octetsto127octets); + UPDATE_STAT64(tx_stat_gt255, + tx_stat_etherstatspkts128octetsto255octets); + UPDATE_STAT64(tx_stat_gt511, + tx_stat_etherstatspkts256octetsto511octets); + UPDATE_STAT64(tx_stat_gt1023, + tx_stat_etherstatspkts512octetsto1023octets); + UPDATE_STAT64(tx_stat_gt1518, + tx_stat_etherstatspkts1024octetsto1522octets); + UPDATE_STAT64(tx_stat_gt2047, tx_stat_bmac_2047); + UPDATE_STAT64(tx_stat_gt4095, tx_stat_bmac_4095); + UPDATE_STAT64(tx_stat_gt9216, tx_stat_bmac_9216); + UPDATE_STAT64(tx_stat_gt16383, tx_stat_bmac_16383); + UPDATE_STAT64(tx_stat_gterr, + tx_stat_dot3statsinternalmactransmiterrors); + UPDATE_STAT64(tx_stat_gtufl, tx_stat_bmac_ufl); + + estats->pause_frames_received_hi = + pstats->mac_stx[1].rx_stat_bmac_xpf_hi; + estats->pause_frames_received_lo = + pstats->mac_stx[1].rx_stat_bmac_xpf_lo; + + estats->pause_frames_sent_hi = + pstats->mac_stx[1].tx_stat_outxoffsent_hi; + estats->pause_frames_sent_lo = + pstats->mac_stx[1].tx_stat_outxoffsent_lo; +} + +static void bnx2x_emac_stats_update(struct bnx2x *bp) +{ + struct emac_stats *new = bnx2x_sp(bp, mac_stats.emac_stats); + struct host_port_stats *pstats = bnx2x_sp(bp, port_stats); + struct bnx2x_eth_stats *estats = &bp->eth_stats; + + UPDATE_EXTEND_STAT(rx_stat_ifhcinbadoctets); + UPDATE_EXTEND_STAT(tx_stat_ifhcoutbadoctets); + UPDATE_EXTEND_STAT(rx_stat_dot3statsfcserrors); + UPDATE_EXTEND_STAT(rx_stat_dot3statsalignmenterrors); + UPDATE_EXTEND_STAT(rx_stat_dot3statscarriersenseerrors); + UPDATE_EXTEND_STAT(rx_stat_falsecarriererrors); + UPDATE_EXTEND_STAT(rx_stat_etherstatsundersizepkts); + UPDATE_EXTEND_STAT(rx_stat_dot3statsframestoolong); + UPDATE_EXTEND_STAT(rx_stat_etherstatsfragments); + UPDATE_EXTEND_STAT(rx_stat_etherstatsjabbers); + UPDATE_EXTEND_STAT(rx_stat_maccontrolframesreceived); + UPDATE_EXTEND_STAT(rx_stat_xoffstateentered); + UPDATE_EXTEND_STAT(rx_stat_xonpauseframesreceived); + UPDATE_EXTEND_STAT(rx_stat_xoffpauseframesreceived); + UPDATE_EXTEND_STAT(tx_stat_outxonsent); + UPDATE_EXTEND_STAT(tx_stat_outxoffsent); + UPDATE_EXTEND_STAT(tx_stat_flowcontroldone); + UPDATE_EXTEND_STAT(tx_stat_etherstatscollisions); + UPDATE_EXTEND_STAT(tx_stat_dot3statssinglecollisionframes); + UPDATE_EXTEND_STAT(tx_stat_dot3statsmultiplecollisionframes); + UPDATE_EXTEND_STAT(tx_stat_dot3statsdeferredtransmissions); + UPDATE_EXTEND_STAT(tx_stat_dot3statsexcessivecollisions); + UPDATE_EXTEND_STAT(tx_stat_dot3statslatecollisions); + UPDATE_EXTEND_STAT(tx_stat_etherstatspkts64octets); + UPDATE_EXTEND_STAT(tx_stat_etherstatspkts65octetsto127octets); + UPDATE_EXTEND_STAT(tx_stat_etherstatspkts128octetsto255octets); + UPDATE_EXTEND_STAT(tx_stat_etherstatspkts256octetsto511octets); + UPDATE_EXTEND_STAT(tx_stat_etherstatspkts512octetsto1023octets); + UPDATE_EXTEND_STAT(tx_stat_etherstatspkts1024octetsto1522octets); + UPDATE_EXTEND_STAT(tx_stat_etherstatspktsover1522octets); + UPDATE_EXTEND_STAT(tx_stat_dot3statsinternalmactransmiterrors); + + estats->pause_frames_received_hi = + pstats->mac_stx[1].rx_stat_xonpauseframesreceived_hi; + estats->pause_frames_received_lo = + pstats->mac_stx[1].rx_stat_xonpauseframesreceived_lo; + ADD_64(estats->pause_frames_received_hi, + pstats->mac_stx[1].rx_stat_xoffpauseframesreceived_hi, + estats->pause_frames_received_lo, + pstats->mac_stx[1].rx_stat_xoffpauseframesreceived_lo); + + estats->pause_frames_sent_hi = + pstats->mac_stx[1].tx_stat_outxonsent_hi; + estats->pause_frames_sent_lo = + pstats->mac_stx[1].tx_stat_outxonsent_lo; + ADD_64(estats->pause_frames_sent_hi, + pstats->mac_stx[1].tx_stat_outxoffsent_hi, + estats->pause_frames_sent_lo, + pstats->mac_stx[1].tx_stat_outxoffsent_lo); +} + +static int bnx2x_hw_stats_update(struct bnx2x *bp) +{ + struct nig_stats *new = bnx2x_sp(bp, nig_stats); + struct nig_stats *old = &(bp->port.old_nig_stats); + struct host_port_stats *pstats = bnx2x_sp(bp, port_stats); + struct bnx2x_eth_stats *estats = &bp->eth_stats; + struct { + u32 lo; + u32 hi; + } diff; + + if (bp->link_vars.mac_type == MAC_TYPE_BMAC) + bnx2x_bmac_stats_update(bp); + + else if (bp->link_vars.mac_type == MAC_TYPE_EMAC) + bnx2x_emac_stats_update(bp); + + else { /* unreached */ + BNX2X_ERR("stats updated by DMAE but no MAC active\n"); + return -1; + } + + ADD_EXTEND_64(pstats->brb_drop_hi, pstats->brb_drop_lo, + new->brb_discard - old->brb_discard); + ADD_EXTEND_64(estats->brb_truncate_hi, estats->brb_truncate_lo, + new->brb_truncate - old->brb_truncate); + + UPDATE_STAT64_NIG(egress_mac_pkt0, + etherstatspkts1024octetsto1522octets); + UPDATE_STAT64_NIG(egress_mac_pkt1, etherstatspktsover1522octets); + + memcpy(old, new, sizeof(struct nig_stats)); + + memcpy(&(estats->rx_stat_ifhcinbadoctets_hi), &(pstats->mac_stx[1]), + sizeof(struct mac_stx)); + estats->brb_drop_hi = pstats->brb_drop_hi; + estats->brb_drop_lo = pstats->brb_drop_lo; + + pstats->host_port_stats_start = ++pstats->host_port_stats_end; + + if (!BP_NOMCP(bp)) { + u32 nig_timer_max = + SHMEM_RD(bp, port_mb[BP_PORT(bp)].stat_nig_timer); + if (nig_timer_max != estats->nig_timer_max) { + estats->nig_timer_max = nig_timer_max; + BNX2X_ERR("NIG timer max (%u)\n", + estats->nig_timer_max); + } + } + + return 0; +} + +static int bnx2x_storm_stats_update(struct bnx2x *bp) +{ + struct eth_stats_query *stats = bnx2x_sp(bp, fw_stats); + struct tstorm_per_port_stats *tport = + &stats->tstorm_common.port_statistics; + struct host_func_stats *fstats = bnx2x_sp(bp, func_stats); + struct bnx2x_eth_stats *estats = &bp->eth_stats; + int i; + u16 cur_stats_counter; + + /* Make sure we use the value of the counter + * used for sending the last stats ramrod. + */ + spin_lock_bh(&bp->stats_lock); + cur_stats_counter = bp->stats_counter - 1; + spin_unlock_bh(&bp->stats_lock); + + memcpy(&(fstats->total_bytes_received_hi), + &(bnx2x_sp(bp, func_stats_base)->total_bytes_received_hi), + sizeof(struct host_func_stats) - 2*sizeof(u32)); + estats->error_bytes_received_hi = 0; + estats->error_bytes_received_lo = 0; + estats->etherstatsoverrsizepkts_hi = 0; + estats->etherstatsoverrsizepkts_lo = 0; + estats->no_buff_discard_hi = 0; + estats->no_buff_discard_lo = 0; + + for_each_queue(bp, i) { + struct bnx2x_fastpath *fp = &bp->fp[i]; + int cl_id = fp->cl_id; + struct tstorm_per_client_stats *tclient = + &stats->tstorm_common.client_statistics[cl_id]; + struct tstorm_per_client_stats *old_tclient = &fp->old_tclient; + struct ustorm_per_client_stats *uclient = + &stats->ustorm_common.client_statistics[cl_id]; + struct ustorm_per_client_stats *old_uclient = &fp->old_uclient; + struct xstorm_per_client_stats *xclient = + &stats->xstorm_common.client_statistics[cl_id]; + struct xstorm_per_client_stats *old_xclient = &fp->old_xclient; + struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats; + u32 diff; + + /* are storm stats valid? */ + if (le16_to_cpu(xclient->stats_counter) != cur_stats_counter) { + DP(BNX2X_MSG_STATS, "[%d] stats not updated by xstorm" + " xstorm counter (0x%x) != stats_counter (0x%x)\n", + i, xclient->stats_counter, cur_stats_counter + 1); + return -1; + } + if (le16_to_cpu(tclient->stats_counter) != cur_stats_counter) { + DP(BNX2X_MSG_STATS, "[%d] stats not updated by tstorm" + " tstorm counter (0x%x) != stats_counter (0x%x)\n", + i, tclient->stats_counter, cur_stats_counter + 1); + return -2; + } + if (le16_to_cpu(uclient->stats_counter) != cur_stats_counter) { + DP(BNX2X_MSG_STATS, "[%d] stats not updated by ustorm" + " ustorm counter (0x%x) != stats_counter (0x%x)\n", + i, uclient->stats_counter, cur_stats_counter + 1); + return -4; + } + + qstats->total_bytes_received_hi = + le32_to_cpu(tclient->rcv_broadcast_bytes.hi); + qstats->total_bytes_received_lo = + le32_to_cpu(tclient->rcv_broadcast_bytes.lo); + + ADD_64(qstats->total_bytes_received_hi, + le32_to_cpu(tclient->rcv_multicast_bytes.hi), + qstats->total_bytes_received_lo, + le32_to_cpu(tclient->rcv_multicast_bytes.lo)); + + ADD_64(qstats->total_bytes_received_hi, + le32_to_cpu(tclient->rcv_unicast_bytes.hi), + qstats->total_bytes_received_lo, + le32_to_cpu(tclient->rcv_unicast_bytes.lo)); + + SUB_64(qstats->total_bytes_received_hi, + le32_to_cpu(uclient->bcast_no_buff_bytes.hi), + qstats->total_bytes_received_lo, + le32_to_cpu(uclient->bcast_no_buff_bytes.lo)); + + SUB_64(qstats->total_bytes_received_hi, + le32_to_cpu(uclient->mcast_no_buff_bytes.hi), + qstats->total_bytes_received_lo, + le32_to_cpu(uclient->mcast_no_buff_bytes.lo)); + + SUB_64(qstats->total_bytes_received_hi, + le32_to_cpu(uclient->ucast_no_buff_bytes.hi), + qstats->total_bytes_received_lo, + le32_to_cpu(uclient->ucast_no_buff_bytes.lo)); + + qstats->valid_bytes_received_hi = + qstats->total_bytes_received_hi; + qstats->valid_bytes_received_lo = + qstats->total_bytes_received_lo; + + qstats->error_bytes_received_hi = + le32_to_cpu(tclient->rcv_error_bytes.hi); + qstats->error_bytes_received_lo = + le32_to_cpu(tclient->rcv_error_bytes.lo); + + ADD_64(qstats->total_bytes_received_hi, + qstats->error_bytes_received_hi, + qstats->total_bytes_received_lo, + qstats->error_bytes_received_lo); + + UPDATE_EXTEND_TSTAT(rcv_unicast_pkts, + total_unicast_packets_received); + UPDATE_EXTEND_TSTAT(rcv_multicast_pkts, + total_multicast_packets_received); + UPDATE_EXTEND_TSTAT(rcv_broadcast_pkts, + total_broadcast_packets_received); + UPDATE_EXTEND_TSTAT(packets_too_big_discard, + etherstatsoverrsizepkts); + UPDATE_EXTEND_TSTAT(no_buff_discard, no_buff_discard); + + SUB_EXTEND_USTAT(ucast_no_buff_pkts, + total_unicast_packets_received); + SUB_EXTEND_USTAT(mcast_no_buff_pkts, + total_multicast_packets_received); + SUB_EXTEND_USTAT(bcast_no_buff_pkts, + total_broadcast_packets_received); + UPDATE_EXTEND_USTAT(ucast_no_buff_pkts, no_buff_discard); + UPDATE_EXTEND_USTAT(mcast_no_buff_pkts, no_buff_discard); + UPDATE_EXTEND_USTAT(bcast_no_buff_pkts, no_buff_discard); + + qstats->total_bytes_transmitted_hi = + le32_to_cpu(xclient->unicast_bytes_sent.hi); + qstats->total_bytes_transmitted_lo = + le32_to_cpu(xclient->unicast_bytes_sent.lo); + + ADD_64(qstats->total_bytes_transmitted_hi, + le32_to_cpu(xclient->multicast_bytes_sent.hi), + qstats->total_bytes_transmitted_lo, + le32_to_cpu(xclient->multicast_bytes_sent.lo)); + + ADD_64(qstats->total_bytes_transmitted_hi, + le32_to_cpu(xclient->broadcast_bytes_sent.hi), + qstats->total_bytes_transmitted_lo, + le32_to_cpu(xclient->broadcast_bytes_sent.lo)); + + UPDATE_EXTEND_XSTAT(unicast_pkts_sent, + total_unicast_packets_transmitted); + UPDATE_EXTEND_XSTAT(multicast_pkts_sent, + total_multicast_packets_transmitted); + UPDATE_EXTEND_XSTAT(broadcast_pkts_sent, + total_broadcast_packets_transmitted); + + old_tclient->checksum_discard = tclient->checksum_discard; + old_tclient->ttl0_discard = tclient->ttl0_discard; + + ADD_64(fstats->total_bytes_received_hi, + qstats->total_bytes_received_hi, + fstats->total_bytes_received_lo, + qstats->total_bytes_received_lo); + ADD_64(fstats->total_bytes_transmitted_hi, + qstats->total_bytes_transmitted_hi, + fstats->total_bytes_transmitted_lo, + qstats->total_bytes_transmitted_lo); + ADD_64(fstats->total_unicast_packets_received_hi, + qstats->total_unicast_packets_received_hi, + fstats->total_unicast_packets_received_lo, + qstats->total_unicast_packets_received_lo); + ADD_64(fstats->total_multicast_packets_received_hi, + qstats->total_multicast_packets_received_hi, + fstats->total_multicast_packets_received_lo, + qstats->total_multicast_packets_received_lo); + ADD_64(fstats->total_broadcast_packets_received_hi, + qstats->total_broadcast_packets_received_hi, + fstats->total_broadcast_packets_received_lo, + qstats->total_broadcast_packets_received_lo); + ADD_64(fstats->total_unicast_packets_transmitted_hi, + qstats->total_unicast_packets_transmitted_hi, + fstats->total_unicast_packets_transmitted_lo, + qstats->total_unicast_packets_transmitted_lo); + ADD_64(fstats->total_multicast_packets_transmitted_hi, + qstats->total_multicast_packets_transmitted_hi, + fstats->total_multicast_packets_transmitted_lo, + qstats->total_multicast_packets_transmitted_lo); + ADD_64(fstats->total_broadcast_packets_transmitted_hi, + qstats->total_broadcast_packets_transmitted_hi, + fstats->total_broadcast_packets_transmitted_lo, + qstats->total_broadcast_packets_transmitted_lo); + ADD_64(fstats->valid_bytes_received_hi, + qstats->valid_bytes_received_hi, + fstats->valid_bytes_received_lo, + qstats->valid_bytes_received_lo); + + ADD_64(estats->error_bytes_received_hi, + qstats->error_bytes_received_hi, + estats->error_bytes_received_lo, + qstats->error_bytes_received_lo); + ADD_64(estats->etherstatsoverrsizepkts_hi, + qstats->etherstatsoverrsizepkts_hi, + estats->etherstatsoverrsizepkts_lo, + qstats->etherstatsoverrsizepkts_lo); + ADD_64(estats->no_buff_discard_hi, qstats->no_buff_discard_hi, + estats->no_buff_discard_lo, qstats->no_buff_discard_lo); + } + + ADD_64(fstats->total_bytes_received_hi, + estats->rx_stat_ifhcinbadoctets_hi, + fstats->total_bytes_received_lo, + estats->rx_stat_ifhcinbadoctets_lo); + + memcpy(estats, &(fstats->total_bytes_received_hi), + sizeof(struct host_func_stats) - 2*sizeof(u32)); + + ADD_64(estats->etherstatsoverrsizepkts_hi, + estats->rx_stat_dot3statsframestoolong_hi, + estats->etherstatsoverrsizepkts_lo, + estats->rx_stat_dot3statsframestoolong_lo); + ADD_64(estats->error_bytes_received_hi, + estats->rx_stat_ifhcinbadoctets_hi, + estats->error_bytes_received_lo, + estats->rx_stat_ifhcinbadoctets_lo); + + if (bp->port.pmf) { + estats->mac_filter_discard = + le32_to_cpu(tport->mac_filter_discard); + estats->xxoverflow_discard = + le32_to_cpu(tport->xxoverflow_discard); + estats->brb_truncate_discard = + le32_to_cpu(tport->brb_truncate_discard); + estats->mac_discard = le32_to_cpu(tport->mac_discard); + } + + fstats->host_func_stats_start = ++fstats->host_func_stats_end; + + bp->stats_pending = 0; + + return 0; +} + +static void bnx2x_net_stats_update(struct bnx2x *bp) +{ + struct bnx2x_eth_stats *estats = &bp->eth_stats; + struct net_device_stats *nstats = &bp->dev->stats; + int i; + + nstats->rx_packets = + bnx2x_hilo(&estats->total_unicast_packets_received_hi) + + bnx2x_hilo(&estats->total_multicast_packets_received_hi) + + bnx2x_hilo(&estats->total_broadcast_packets_received_hi); + + nstats->tx_packets = + bnx2x_hilo(&estats->total_unicast_packets_transmitted_hi) + + bnx2x_hilo(&estats->total_multicast_packets_transmitted_hi) + + bnx2x_hilo(&estats->total_broadcast_packets_transmitted_hi); + + nstats->rx_bytes = bnx2x_hilo(&estats->total_bytes_received_hi); + + nstats->tx_bytes = bnx2x_hilo(&estats->total_bytes_transmitted_hi); + + nstats->rx_dropped = estats->mac_discard; + for_each_queue(bp, i) + nstats->rx_dropped += + le32_to_cpu(bp->fp[i].old_tclient.checksum_discard); + + nstats->tx_dropped = 0; + + nstats->multicast = + bnx2x_hilo(&estats->total_multicast_packets_received_hi); + + nstats->collisions = + bnx2x_hilo(&estats->tx_stat_etherstatscollisions_hi); + + nstats->rx_length_errors = + bnx2x_hilo(&estats->rx_stat_etherstatsundersizepkts_hi) + + bnx2x_hilo(&estats->etherstatsoverrsizepkts_hi); + nstats->rx_over_errors = bnx2x_hilo(&estats->brb_drop_hi) + + bnx2x_hilo(&estats->brb_truncate_hi); + nstats->rx_crc_errors = + bnx2x_hilo(&estats->rx_stat_dot3statsfcserrors_hi); + nstats->rx_frame_errors = + bnx2x_hilo(&estats->rx_stat_dot3statsalignmenterrors_hi); + nstats->rx_fifo_errors = bnx2x_hilo(&estats->no_buff_discard_hi); + nstats->rx_missed_errors = estats->xxoverflow_discard; + + nstats->rx_errors = nstats->rx_length_errors + + nstats->rx_over_errors + + nstats->rx_crc_errors + + nstats->rx_frame_errors + + nstats->rx_fifo_errors + + nstats->rx_missed_errors; + + nstats->tx_aborted_errors = + bnx2x_hilo(&estats->tx_stat_dot3statslatecollisions_hi) + + bnx2x_hilo(&estats->tx_stat_dot3statsexcessivecollisions_hi); + nstats->tx_carrier_errors = + bnx2x_hilo(&estats->rx_stat_dot3statscarriersenseerrors_hi); + nstats->tx_fifo_errors = 0; + nstats->tx_heartbeat_errors = 0; + nstats->tx_window_errors = 0; + + nstats->tx_errors = nstats->tx_aborted_errors + + nstats->tx_carrier_errors + + bnx2x_hilo(&estats->tx_stat_dot3statsinternalmactransmiterrors_hi); +} + +static void bnx2x_drv_stats_update(struct bnx2x *bp) +{ + struct bnx2x_eth_stats *estats = &bp->eth_stats; + int i; + + estats->driver_xoff = 0; + estats->rx_err_discard_pkt = 0; + estats->rx_skb_alloc_failed = 0; + estats->hw_csum_err = 0; + for_each_queue(bp, i) { + struct bnx2x_eth_q_stats *qstats = &bp->fp[i].eth_q_stats; + + estats->driver_xoff += qstats->driver_xoff; + estats->rx_err_discard_pkt += qstats->rx_err_discard_pkt; + estats->rx_skb_alloc_failed += qstats->rx_skb_alloc_failed; + estats->hw_csum_err += qstats->hw_csum_err; + } +} + +static void bnx2x_stats_update(struct bnx2x *bp) +{ + u32 *stats_comp = bnx2x_sp(bp, stats_comp); + + if (*stats_comp != DMAE_COMP_VAL) + return; + + if (bp->port.pmf) + bnx2x_hw_stats_update(bp); + + if (bnx2x_storm_stats_update(bp) && (bp->stats_pending++ == 3)) { + BNX2X_ERR("storm stats were not updated for 3 times\n"); + bnx2x_panic(); + return; + } + + bnx2x_net_stats_update(bp); + bnx2x_drv_stats_update(bp); + + if (netif_msg_timer(bp)) { + struct bnx2x_eth_stats *estats = &bp->eth_stats; + int i; + + printk(KERN_DEBUG "%s: brb drops %u brb truncate %u\n", + bp->dev->name, + estats->brb_drop_lo, estats->brb_truncate_lo); + + for_each_queue(bp, i) { + struct bnx2x_fastpath *fp = &bp->fp[i]; + struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats; + + printk(KERN_DEBUG "%s: rx usage(%4u) *rx_cons_sb(%u)" + " rx pkt(%lu) rx calls(%lu %lu)\n", + fp->name, (le16_to_cpu(*fp->rx_cons_sb) - + fp->rx_comp_cons), + le16_to_cpu(*fp->rx_cons_sb), + bnx2x_hilo(&qstats-> + total_unicast_packets_received_hi), + fp->rx_calls, fp->rx_pkt); + } + + for_each_queue(bp, i) { + struct bnx2x_fastpath *fp = &bp->fp[i]; + struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats; + struct netdev_queue *txq = + netdev_get_tx_queue(bp->dev, i); + + printk(KERN_DEBUG "%s: tx avail(%4u) *tx_cons_sb(%u)" + " tx pkt(%lu) tx calls (%lu)" + " %s (Xoff events %u)\n", + fp->name, bnx2x_tx_avail(fp), + le16_to_cpu(*fp->tx_cons_sb), + bnx2x_hilo(&qstats-> + total_unicast_packets_transmitted_hi), + fp->tx_pkt, + (netif_tx_queue_stopped(txq) ? "Xoff" : "Xon"), + qstats->driver_xoff); + } + } + + bnx2x_hw_stats_post(bp); + bnx2x_storm_stats_post(bp); +} + +static void bnx2x_port_stats_stop(struct bnx2x *bp) +{ + struct dmae_command *dmae; + u32 opcode; + int loader_idx = PMF_DMAE_C(bp); + u32 *stats_comp = bnx2x_sp(bp, stats_comp); + + bp->executer_idx = 0; + + opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC | + DMAE_CMD_C_ENABLE | + DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET | +#ifdef __BIG_ENDIAN + DMAE_CMD_ENDIANITY_B_DW_SWAP | +#else + DMAE_CMD_ENDIANITY_DW_SWAP | +#endif + (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) | + (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT)); + + if (bp->port.port_stx) { + + dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); + if (bp->func_stx) + dmae->opcode = (opcode | DMAE_CMD_C_DST_GRC); + else + dmae->opcode = (opcode | DMAE_CMD_C_DST_PCI); + dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats)); + dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats)); + dmae->dst_addr_lo = bp->port.port_stx >> 2; + dmae->dst_addr_hi = 0; + dmae->len = sizeof(struct host_port_stats) >> 2; + if (bp->func_stx) { + dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; + dmae->comp_addr_hi = 0; + dmae->comp_val = 1; + } else { + dmae->comp_addr_lo = + U64_LO(bnx2x_sp_mapping(bp, stats_comp)); + dmae->comp_addr_hi = + U64_HI(bnx2x_sp_mapping(bp, stats_comp)); + dmae->comp_val = DMAE_COMP_VAL; + + *stats_comp = 0; + } + } + + if (bp->func_stx) { + + dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); + dmae->opcode = (opcode | DMAE_CMD_C_DST_PCI); + dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, func_stats)); + dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, func_stats)); + dmae->dst_addr_lo = bp->func_stx >> 2; + dmae->dst_addr_hi = 0; + dmae->len = sizeof(struct host_func_stats) >> 2; + dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp)); + dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp)); + dmae->comp_val = DMAE_COMP_VAL; + + *stats_comp = 0; + } +} + +static void bnx2x_stats_stop(struct bnx2x *bp) +{ + int update = 0; + + bnx2x_stats_comp(bp); + + if (bp->port.pmf) + update = (bnx2x_hw_stats_update(bp) == 0); + + update |= (bnx2x_storm_stats_update(bp) == 0); + + if (update) { + bnx2x_net_stats_update(bp); + + if (bp->port.pmf) + bnx2x_port_stats_stop(bp); + + bnx2x_hw_stats_post(bp); + bnx2x_stats_comp(bp); + } +} + +static void bnx2x_stats_do_nothing(struct bnx2x *bp) +{ +} + +static const struct { + void (*action)(struct bnx2x *bp); + enum bnx2x_stats_state next_state; +} bnx2x_stats_stm[STATS_STATE_MAX][STATS_EVENT_MAX] = { +/* state event */ +{ +/* DISABLED PMF */ {bnx2x_stats_pmf_update, STATS_STATE_DISABLED}, +/* LINK_UP */ {bnx2x_stats_start, STATS_STATE_ENABLED}, +/* UPDATE */ {bnx2x_stats_do_nothing, STATS_STATE_DISABLED}, +/* STOP */ {bnx2x_stats_do_nothing, STATS_STATE_DISABLED} +}, +{ +/* ENABLED PMF */ {bnx2x_stats_pmf_start, STATS_STATE_ENABLED}, +/* LINK_UP */ {bnx2x_stats_restart, STATS_STATE_ENABLED}, +/* UPDATE */ {bnx2x_stats_update, STATS_STATE_ENABLED}, +/* STOP */ {bnx2x_stats_stop, STATS_STATE_DISABLED} +} +}; + +void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event) +{ + enum bnx2x_stats_state state; + + if (unlikely(bp->panic)) + return; + + /* Protect a state change flow */ + spin_lock_bh(&bp->stats_lock); + state = bp->stats_state; + bp->stats_state = bnx2x_stats_stm[state][event].next_state; + spin_unlock_bh(&bp->stats_lock); + + bnx2x_stats_stm[state][event].action(bp); + + if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp)) + DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n", + state, event, bp->stats_state); +} + +static void bnx2x_port_stats_base_init(struct bnx2x *bp) +{ + struct dmae_command *dmae; + u32 *stats_comp = bnx2x_sp(bp, stats_comp); + + /* sanity */ + if (!bp->port.pmf || !bp->port.port_stx) { + BNX2X_ERR("BUG!\n"); + return; + } + + bp->executer_idx = 0; + + dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]); + dmae->opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC | + DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE | + DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET | +#ifdef __BIG_ENDIAN + DMAE_CMD_ENDIANITY_B_DW_SWAP | +#else + DMAE_CMD_ENDIANITY_DW_SWAP | +#endif + (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) | + (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT)); + dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats)); + dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats)); + dmae->dst_addr_lo = bp->port.port_stx >> 2; + dmae->dst_addr_hi = 0; + dmae->len = sizeof(struct host_port_stats) >> 2; + dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp)); + dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp)); + dmae->comp_val = DMAE_COMP_VAL; + + *stats_comp = 0; + bnx2x_hw_stats_post(bp); + bnx2x_stats_comp(bp); +} + +static void bnx2x_func_stats_base_init(struct bnx2x *bp) +{ + int vn, vn_max = IS_E1HMF(bp) ? E1HVN_MAX : E1VN_MAX; + int port = BP_PORT(bp); + int func; + u32 func_stx; + + /* sanity */ + if (!bp->port.pmf || !bp->func_stx) { + BNX2X_ERR("BUG!\n"); + return; + } + + /* save our func_stx */ + func_stx = bp->func_stx; + + for (vn = VN_0; vn < vn_max; vn++) { + func = 2*vn + port; + + bp->func_stx = SHMEM_RD(bp, func_mb[func].fw_mb_param); + bnx2x_func_stats_init(bp); + bnx2x_hw_stats_post(bp); + bnx2x_stats_comp(bp); + } + + /* restore our func_stx */ + bp->func_stx = func_stx; +} + +static void bnx2x_func_stats_base_update(struct bnx2x *bp) +{ + struct dmae_command *dmae = &bp->stats_dmae; + u32 *stats_comp = bnx2x_sp(bp, stats_comp); + + /* sanity */ + if (!bp->func_stx) { + BNX2X_ERR("BUG!\n"); + return; + } + + bp->executer_idx = 0; + memset(dmae, 0, sizeof(struct dmae_command)); + + dmae->opcode = (DMAE_CMD_SRC_GRC | DMAE_CMD_DST_PCI | + DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE | + DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET | +#ifdef __BIG_ENDIAN + DMAE_CMD_ENDIANITY_B_DW_SWAP | +#else + DMAE_CMD_ENDIANITY_DW_SWAP | +#endif + (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) | + (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT)); + dmae->src_addr_lo = bp->func_stx >> 2; + dmae->src_addr_hi = 0; + dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, func_stats_base)); + dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, func_stats_base)); + dmae->len = sizeof(struct host_func_stats) >> 2; + dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp)); + dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp)); + dmae->comp_val = DMAE_COMP_VAL; + + *stats_comp = 0; + bnx2x_hw_stats_post(bp); + bnx2x_stats_comp(bp); +} + +void bnx2x_stats_init(struct bnx2x *bp) +{ + int port = BP_PORT(bp); + int func = BP_FUNC(bp); + int i; + + bp->stats_pending = 0; + bp->executer_idx = 0; + bp->stats_counter = 0; + + /* port and func stats for management */ + if (!BP_NOMCP(bp)) { + bp->port.port_stx = SHMEM_RD(bp, port_mb[port].port_stx); + bp->func_stx = SHMEM_RD(bp, func_mb[func].fw_mb_param); + + } else { + bp->port.port_stx = 0; + bp->func_stx = 0; + } + DP(BNX2X_MSG_STATS, "port_stx 0x%x func_stx 0x%x\n", + bp->port.port_stx, bp->func_stx); + + /* port stats */ + memset(&(bp->port.old_nig_stats), 0, sizeof(struct nig_stats)); + bp->port.old_nig_stats.brb_discard = + REG_RD(bp, NIG_REG_STAT0_BRB_DISCARD + port*0x38); + bp->port.old_nig_stats.brb_truncate = + REG_RD(bp, NIG_REG_STAT0_BRB_TRUNCATE + port*0x38); + REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT0 + port*0x50, + &(bp->port.old_nig_stats.egress_mac_pkt0_lo), 2); + REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT1 + port*0x50, + &(bp->port.old_nig_stats.egress_mac_pkt1_lo), 2); + + /* function stats */ + for_each_queue(bp, i) { + struct bnx2x_fastpath *fp = &bp->fp[i]; + + memset(&fp->old_tclient, 0, + sizeof(struct tstorm_per_client_stats)); + memset(&fp->old_uclient, 0, + sizeof(struct ustorm_per_client_stats)); + memset(&fp->old_xclient, 0, + sizeof(struct xstorm_per_client_stats)); + memset(&fp->eth_q_stats, 0, sizeof(struct bnx2x_eth_q_stats)); + } + + memset(&bp->dev->stats, 0, sizeof(struct net_device_stats)); + memset(&bp->eth_stats, 0, sizeof(struct bnx2x_eth_stats)); + + bp->stats_state = STATS_STATE_DISABLED; + + if (bp->port.pmf) { + if (bp->port.port_stx) + bnx2x_port_stats_base_init(bp); + + if (bp->func_stx) + bnx2x_func_stats_base_init(bp); + + } else if (bp->func_stx) + bnx2x_func_stats_base_update(bp); +} diff --git a/drivers/net/bnx2x/bnx2x_stats.h b/drivers/net/bnx2x/bnx2x_stats.h new file mode 100644 index 00000000000..38a4e908f4f --- /dev/null +++ b/drivers/net/bnx2x/bnx2x_stats.h @@ -0,0 +1,239 @@ +/* bnx2x_stats.h: Broadcom Everest network driver. + * + * Copyright (c) 2007-2010 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * Maintained by: Eilon Greenstein <eilong@broadcom.com> + * Written by: Eliezer Tamir + * Based on code from Michael Chan's bnx2 driver + */ + +#ifndef BNX2X_STATS_H +#define BNX2X_STATS_H + +#include <linux/types.h> + +struct bnx2x_eth_q_stats { + u32 total_bytes_received_hi; + u32 total_bytes_received_lo; + u32 total_bytes_transmitted_hi; + u32 total_bytes_transmitted_lo; + u32 total_unicast_packets_received_hi; + u32 total_unicast_packets_received_lo; + u32 total_multicast_packets_received_hi; + u32 total_multicast_packets_received_lo; + u32 total_broadcast_packets_received_hi; + u32 total_broadcast_packets_received_lo; + u32 total_unicast_packets_transmitted_hi; + u32 total_unicast_packets_transmitted_lo; + u32 total_multicast_packets_transmitted_hi; + u32 total_multicast_packets_transmitted_lo; + u32 total_broadcast_packets_transmitted_hi; + u32 total_broadcast_packets_transmitted_lo; + u32 valid_bytes_received_hi; + u32 valid_bytes_received_lo; + + u32 error_bytes_received_hi; + u32 error_bytes_received_lo; + u32 etherstatsoverrsizepkts_hi; + u32 etherstatsoverrsizepkts_lo; + u32 no_buff_discard_hi; + u32 no_buff_discard_lo; + + u32 driver_xoff; + u32 rx_err_discard_pkt; + u32 rx_skb_alloc_failed; + u32 hw_csum_err; +}; + +#define BNX2X_NUM_Q_STATS 13 +#define Q_STATS_OFFSET32(stat_name) \ + (offsetof(struct bnx2x_eth_q_stats, stat_name) / 4) + +struct nig_stats { + u32 brb_discard; + u32 brb_packet; + u32 brb_truncate; + u32 flow_ctrl_discard; + u32 flow_ctrl_octets; + u32 flow_ctrl_packet; + u32 mng_discard; + u32 mng_octet_inp; + u32 mng_octet_out; + u32 mng_packet_inp; + u32 mng_packet_out; + u32 pbf_octets; + u32 pbf_packet; + u32 safc_inp; + u32 egress_mac_pkt0_lo; + u32 egress_mac_pkt0_hi; + u32 egress_mac_pkt1_lo; + u32 egress_mac_pkt1_hi; +}; + + +enum bnx2x_stats_event { + STATS_EVENT_PMF = 0, + STATS_EVENT_LINK_UP, + STATS_EVENT_UPDATE, + STATS_EVENT_STOP, + STATS_EVENT_MAX +}; + +enum bnx2x_stats_state { + STATS_STATE_DISABLED = 0, + STATS_STATE_ENABLED, + STATS_STATE_MAX +}; + +struct bnx2x_eth_stats { + u32 total_bytes_received_hi; + u32 total_bytes_received_lo; + u32 total_bytes_transmitted_hi; + u32 total_bytes_transmitted_lo; + u32 total_unicast_packets_received_hi; + u32 total_unicast_packets_received_lo; + u32 total_multicast_packets_received_hi; + u32 total_multicast_packets_received_lo; + u32 total_broadcast_packets_received_hi; + u32 total_broadcast_packets_received_lo; + u32 total_unicast_packets_transmitted_hi; + u32 total_unicast_packets_transmitted_lo; + u32 total_multicast_packets_transmitted_hi; + u32 total_multicast_packets_transmitted_lo; + u32 total_broadcast_packets_transmitted_hi; + u32 total_broadcast_packets_transmitted_lo; + u32 valid_bytes_received_hi; + u32 valid_bytes_received_lo; + + u32 error_bytes_received_hi; + u32 error_bytes_received_lo; + u32 etherstatsoverrsizepkts_hi; + u32 etherstatsoverrsizepkts_lo; + u32 no_buff_discard_hi; + u32 no_buff_discard_lo; + + u32 rx_stat_ifhcinbadoctets_hi; + u32 rx_stat_ifhcinbadoctets_lo; + u32 tx_stat_ifhcoutbadoctets_hi; + u32 tx_stat_ifhcoutbadoctets_lo; + u32 rx_stat_dot3statsfcserrors_hi; + u32 rx_stat_dot3statsfcserrors_lo; + u32 rx_stat_dot3statsalignmenterrors_hi; + u32 rx_stat_dot3statsalignmenterrors_lo; + u32 rx_stat_dot3statscarriersenseerrors_hi; + u32 rx_stat_dot3statscarriersenseerrors_lo; + u32 rx_stat_falsecarriererrors_hi; + u32 rx_stat_falsecarriererrors_lo; + u32 rx_stat_etherstatsundersizepkts_hi; + u32 rx_stat_etherstatsundersizepkts_lo; + u32 rx_stat_dot3statsframestoolong_hi; + u32 rx_stat_dot3statsframestoolong_lo; + u32 rx_stat_etherstatsfragments_hi; + u32 rx_stat_etherstatsfragments_lo; + u32 rx_stat_etherstatsjabbers_hi; + u32 rx_stat_etherstatsjabbers_lo; + u32 rx_stat_maccontrolframesreceived_hi; + u32 rx_stat_maccontrolframesreceived_lo; + u32 rx_stat_bmac_xpf_hi; + u32 rx_stat_bmac_xpf_lo; + u32 rx_stat_bmac_xcf_hi; + u32 rx_stat_bmac_xcf_lo; + u32 rx_stat_xoffstateentered_hi; + u32 rx_stat_xoffstateentered_lo; + u32 rx_stat_xonpauseframesreceived_hi; + u32 rx_stat_xonpauseframesreceived_lo; + u32 rx_stat_xoffpauseframesreceived_hi; + u32 rx_stat_xoffpauseframesreceived_lo; + u32 tx_stat_outxonsent_hi; + u32 tx_stat_outxonsent_lo; + u32 tx_stat_outxoffsent_hi; + u32 tx_stat_outxoffsent_lo; + u32 tx_stat_flowcontroldone_hi; + u32 tx_stat_flowcontroldone_lo; + u32 tx_stat_etherstatscollisions_hi; + u32 tx_stat_etherstatscollisions_lo; + u32 tx_stat_dot3statssinglecollisionframes_hi; + u32 tx_stat_dot3statssinglecollisionframes_lo; + u32 tx_stat_dot3statsmultiplecollisionframes_hi; + u32 tx_stat_dot3statsmultiplecollisionframes_lo; + u32 tx_stat_dot3statsdeferredtransmissions_hi; + u32 tx_stat_dot3statsdeferredtransmissions_lo; + u32 tx_stat_dot3statsexcessivecollisions_hi; + u32 tx_stat_dot3statsexcessivecollisions_lo; + u32 tx_stat_dot3statslatecollisions_hi; + u32 tx_stat_dot3statslatecollisions_lo; + u32 tx_stat_etherstatspkts64octets_hi; + u32 tx_stat_etherstatspkts64octets_lo; + u32 tx_stat_etherstatspkts65octetsto127octets_hi; + u32 tx_stat_etherstatspkts65octetsto127octets_lo; + u32 tx_stat_etherstatspkts128octetsto255octets_hi; + u32 tx_stat_etherstatspkts128octetsto255octets_lo; + u32 tx_stat_etherstatspkts256octetsto511octets_hi; + u32 tx_stat_etherstatspkts256octetsto511octets_lo; + u32 tx_stat_etherstatspkts512octetsto1023octets_hi; + u32 tx_stat_etherstatspkts512octetsto1023octets_lo; + u32 tx_stat_etherstatspkts1024octetsto1522octets_hi; + u32 tx_stat_etherstatspkts1024octetsto1522octets_lo; + u32 tx_stat_etherstatspktsover1522octets_hi; + u32 tx_stat_etherstatspktsover1522octets_lo; + u32 tx_stat_bmac_2047_hi; + u32 tx_stat_bmac_2047_lo; + u32 tx_stat_bmac_4095_hi; + u32 tx_stat_bmac_4095_lo; + u32 tx_stat_bmac_9216_hi; + u32 tx_stat_bmac_9216_lo; + u32 tx_stat_bmac_16383_hi; + u32 tx_stat_bmac_16383_lo; + u32 tx_stat_dot3statsinternalmactransmiterrors_hi; + u32 tx_stat_dot3statsinternalmactransmiterrors_lo; + u32 tx_stat_bmac_ufl_hi; + u32 tx_stat_bmac_ufl_lo; + + u32 pause_frames_received_hi; + u32 pause_frames_received_lo; + u32 pause_frames_sent_hi; + u32 pause_frames_sent_lo; + + u32 etherstatspkts1024octetsto1522octets_hi; + u32 etherstatspkts1024octetsto1522octets_lo; + u32 etherstatspktsover1522octets_hi; + u32 etherstatspktsover1522octets_lo; + + u32 brb_drop_hi; + u32 brb_drop_lo; + u32 brb_truncate_hi; + u32 brb_truncate_lo; + + u32 mac_filter_discard; + u32 xxoverflow_discard; + u32 brb_truncate_discard; + u32 mac_discard; + + u32 driver_xoff; + u32 rx_err_discard_pkt; + u32 rx_skb_alloc_failed; + u32 hw_csum_err; + + u32 nig_timer_max; +}; + +#define BNX2X_NUM_STATS 43 +#define STATS_OFFSET32(stat_name) \ + (offsetof(struct bnx2x_eth_stats, stat_name) / 4) + +/* Forward declaration */ +struct bnx2x; + + +void bnx2x_stats_init(struct bnx2x *bp); + +extern const u32 dmae_reg_go_c[]; +extern int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, + u32 data_hi, u32 data_lo, int common); + + +#endif /* BNX2X_STATS_H */ diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 3662d6e446a..c746b331771 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -682,7 +682,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon client_info->ntt = 0; } - if (!list_empty(&bond->vlan_list)) { + if (bond->vlgrp) { if (!vlan_get_tag(skb, &client_info->vlan_id)) client_info->tag = 1; } @@ -815,7 +815,7 @@ static int rlb_initialize(struct bonding *bond) /*initialize packet type*/ pk_type->type = cpu_to_be16(ETH_P_ARP); - pk_type->dev = NULL; + pk_type->dev = bond->dev; pk_type->func = rlb_arp_recv; /* register to receive ARPs */ @@ -904,7 +904,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]) skb->priority = TC_PRIO_CONTROL; skb->dev = slave->dev; - if (!list_empty(&bond->vlan_list)) { + if (bond->vlgrp) { struct vlan_entry *vlan; vlan = bond_next_vlan(bond, diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 20f45cbf961..2cc4cfc3189 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -424,6 +424,7 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, { unsigned short uninitialized_var(vlan_id); + /* Test vlan_list not vlgrp to catch and handle 802.1p tags */ if (!list_empty(&bond->vlan_list) && !(slave_dev->features & NETIF_F_HW_VLAN_TX) && vlan_get_tag(skb, &vlan_id) == 0) { @@ -487,7 +488,9 @@ static void bond_vlan_rx_register(struct net_device *bond_dev, struct slave *slave; int i; + write_lock(&bond->lock); bond->vlgrp = grp; + write_unlock(&bond->lock); bond_for_each_slave(bond, slave, i) { struct net_device *slave_dev = slave->dev; @@ -567,10 +570,8 @@ static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *sla struct vlan_entry *vlan; const struct net_device_ops *slave_ops = slave_dev->netdev_ops; - write_lock_bh(&bond->lock); - - if (list_empty(&bond->vlan_list)) - goto out; + if (!bond->vlgrp) + return; if ((slave_dev->features & NETIF_F_HW_VLAN_RX) && slave_ops->ndo_vlan_rx_register) @@ -578,13 +579,10 @@ static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *sla if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) || !(slave_ops->ndo_vlan_rx_add_vid)) - goto out; + return; list_for_each_entry(vlan, &bond->vlan_list, vlan_list) slave_ops->ndo_vlan_rx_add_vid(slave_dev, vlan->vlan_id); - -out: - write_unlock_bh(&bond->lock); } static void bond_del_vlans_from_slave(struct bonding *bond, @@ -594,16 +592,16 @@ static void bond_del_vlans_from_slave(struct bonding *bond, struct vlan_entry *vlan; struct net_device *vlan_dev; - write_lock_bh(&bond->lock); - - if (list_empty(&bond->vlan_list)) - goto out; + if (!bond->vlgrp) + return; if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) || !(slave_ops->ndo_vlan_rx_kill_vid)) goto unreg; list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { + if (!vlan->vlan_id) + continue; /* Save and then restore vlan_dev in the grp array, * since the slave's driver might clear it. */ @@ -616,9 +614,6 @@ unreg: if ((slave_dev->features & NETIF_F_HW_VLAN_RX) && slave_ops->ndo_vlan_rx_register) slave_ops->ndo_vlan_rx_register(slave_dev, NULL); - -out: - write_unlock_bh(&bond->lock); } /*------------------------------- Link status -------------------------------*/ @@ -1443,7 +1438,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) /* no need to lock since we're protected by rtnl_lock */ if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) { pr_debug("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name); - if (!list_empty(&bond->vlan_list)) { + if (bond->vlgrp) { pr_err("%s: Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n", bond_dev->name, slave_dev->name, bond_dev->name); return -EPERM; @@ -1942,7 +1937,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) */ memset(bond_dev->dev_addr, 0, bond_dev->addr_len); - if (list_empty(&bond->vlan_list)) { + if (!bond->vlgrp) { bond_dev->features |= NETIF_F_VLAN_CHALLENGED; } else { pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n", @@ -2134,9 +2129,9 @@ static int bond_release_all(struct net_device *bond_dev) */ memset(bond_dev->dev_addr, 0, bond_dev->addr_len); - if (list_empty(&bond->vlan_list)) + if (!bond->vlgrp) { bond_dev->features |= NETIF_F_VLAN_CHALLENGED; - else { + } else { pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n", bond_dev->name, bond_dev->name); pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n", @@ -2569,7 +2564,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) if (!targets[i]) break; pr_debug("basa: target %x\n", targets[i]); - if (list_empty(&bond->vlan_list)) { + if (!bond->vlgrp) { pr_debug("basa: empty vlan: arp_send\n"); bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], bond->master_ip, 0); @@ -2658,6 +2653,9 @@ static void bond_send_gratuitous_arp(struct bonding *bond) bond->master_ip, 0); } + if (!bond->vlgrp) + return; + list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id); if (vlan->vlan_ip) { @@ -3590,6 +3588,8 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event, } list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { + if (!bond->vlgrp) + continue; vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id); if (vlan_dev == event_dev) { switch (event) { @@ -4686,6 +4686,7 @@ static void bond_work_cancel_all(struct bonding *bond) static void bond_uninit(struct net_device *bond_dev) { struct bonding *bond = netdev_priv(bond_dev); + struct vlan_entry *vlan, *tmp; bond_netpoll_cleanup(bond_dev); @@ -4699,6 +4700,11 @@ static void bond_uninit(struct net_device *bond_dev) bond_remove_proc_entry(bond); __hw_addr_flush(&bond->mc_list); + + list_for_each_entry_safe(vlan, tmp, &bond->vlan_list, vlan_list) { + list_del(&vlan->vlan_list); + kfree(vlan); + } } /*------------------------- Module initialization ---------------------------*/ diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 1a997648709..c311aed9bd0 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -313,19 +313,26 @@ static ssize_t bonding_store_mode(struct device *d, bond->dev->name, (int)strlen(buf) - 1, buf); ret = -EINVAL; goto out; - } else { - if (bond->params.mode == BOND_MODE_8023AD) - bond_unset_master_3ad_flags(bond); + } + if ((new_value == BOND_MODE_ALB || + new_value == BOND_MODE_TLB) && + bond->params.arp_interval) { + pr_err("%s: %s mode is incompatible with arp monitoring.\n", + bond->dev->name, bond_mode_tbl[new_value].modename); + ret = -EINVAL; + goto out; + } + if (bond->params.mode == BOND_MODE_8023AD) + bond_unset_master_3ad_flags(bond); - if (bond->params.mode == BOND_MODE_ALB) - bond_unset_master_alb_flags(bond); + if (bond->params.mode == BOND_MODE_ALB) + bond_unset_master_alb_flags(bond); - bond->params.mode = new_value; - bond_set_mode_ops(bond, bond->params.mode); - pr_info("%s: setting mode to %s (%d).\n", - bond->dev->name, bond_mode_tbl[new_value].modename, - new_value); - } + bond->params.mode = new_value; + bond_set_mode_ops(bond, bond->params.mode); + pr_info("%s: setting mode to %s (%d).\n", + bond->dev->name, bond_mode_tbl[new_value].modename, + new_value); out: return ret; } @@ -510,7 +517,13 @@ static ssize_t bonding_store_arp_interval(struct device *d, ret = -EINVAL; goto out; } - + if (bond->params.mode == BOND_MODE_ALB || + bond->params.mode == BOND_MODE_TLB) { + pr_info("%s: ARP monitoring cannot be used with ALB/TLB. Only MII monitoring is supported on %s.\n", + bond->dev->name, bond->dev->name); + ret = -EINVAL; + goto out; + } pr_info("%s: Setting ARP monitoring interval to %d.\n", bond->dev->name, new_value); bond->params.arp_interval = new_value; diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c index 6c948037fc7..f5058ff2b21 100644 --- a/drivers/net/caif/caif_spi.c +++ b/drivers/net/caif/caif_spi.c @@ -165,6 +165,9 @@ static ssize_t dbgfs_state(struct file *file, char __user *user_buf, len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len), "Next RX len: %d\n", cfspi->rx_npck_len); + if (len > DEBUGFS_BUF_SIZE) + len = DEBUGFS_BUF_SIZE; + size = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index 2c5227c02fa..9d9e4539443 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -73,6 +73,15 @@ config CAN_JANZ_ICAN3 This driver can also be built as a module. If so, the module will be called janz-ican3.ko. +config HAVE_CAN_FLEXCAN + bool + +config CAN_FLEXCAN + tristate "Support for Freescale FLEXCAN based chips" + depends on CAN_DEV && HAVE_CAN_FLEXCAN + ---help--- + Say Y here if you want to support for Freescale FlexCAN. + source "drivers/net/can/mscan/Kconfig" source "drivers/net/can/sja1000/Kconfig" diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile index 9047cd066fe..00575373bbd 100644 --- a/drivers/net/can/Makefile +++ b/drivers/net/can/Makefile @@ -16,5 +16,6 @@ obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o obj-$(CONFIG_CAN_MCP251X) += mcp251x.o obj-$(CONFIG_CAN_BFIN) += bfin_can.o obj-$(CONFIG_CAN_JANZ_ICAN3) += janz-ican3.o +obj-$(CONFIG_CAN_FLEXCAN) += flexcan.o ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c new file mode 100644 index 00000000000..ef443a090ba --- /dev/null +++ b/drivers/net/can/flexcan.c @@ -0,0 +1,1030 @@ +/* + * flexcan.c - FLEXCAN CAN controller driver + * + * Copyright (c) 2005-2006 Varma Electronics Oy + * Copyright (c) 2009 Sascha Hauer, Pengutronix + * Copyright (c) 2010 Marc Kleine-Budde, Pengutronix + * + * Based on code originally by Andrey Volkov <avolkov@varma-el.com> + * + * LICENCE: + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/netdevice.h> +#include <linux/can.h> +#include <linux/can/dev.h> +#include <linux/can/error.h> +#include <linux/can/platform/flexcan.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/if_arp.h> +#include <linux/if_ether.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +#include <mach/clock.h> + +#define DRV_NAME "flexcan" + +/* 8 for RX fifo and 2 error handling */ +#define FLEXCAN_NAPI_WEIGHT (8 + 2) + +/* FLEXCAN module configuration register (CANMCR) bits */ +#define FLEXCAN_MCR_MDIS BIT(31) +#define FLEXCAN_MCR_FRZ BIT(30) +#define FLEXCAN_MCR_FEN BIT(29) +#define FLEXCAN_MCR_HALT BIT(28) +#define FLEXCAN_MCR_NOT_RDY BIT(27) +#define FLEXCAN_MCR_WAK_MSK BIT(26) +#define FLEXCAN_MCR_SOFTRST BIT(25) +#define FLEXCAN_MCR_FRZ_ACK BIT(24) +#define FLEXCAN_MCR_SUPV BIT(23) +#define FLEXCAN_MCR_SLF_WAK BIT(22) +#define FLEXCAN_MCR_WRN_EN BIT(21) +#define FLEXCAN_MCR_LPM_ACK BIT(20) +#define FLEXCAN_MCR_WAK_SRC BIT(19) +#define FLEXCAN_MCR_DOZE BIT(18) +#define FLEXCAN_MCR_SRX_DIS BIT(17) +#define FLEXCAN_MCR_BCC BIT(16) +#define FLEXCAN_MCR_LPRIO_EN BIT(13) +#define FLEXCAN_MCR_AEN BIT(12) +#define FLEXCAN_MCR_MAXMB(x) ((x) & 0xf) +#define FLEXCAN_MCR_IDAM_A (0 << 8) +#define FLEXCAN_MCR_IDAM_B (1 << 8) +#define FLEXCAN_MCR_IDAM_C (2 << 8) +#define FLEXCAN_MCR_IDAM_D (3 << 8) + +/* FLEXCAN control register (CANCTRL) bits */ +#define FLEXCAN_CTRL_PRESDIV(x) (((x) & 0xff) << 24) +#define FLEXCAN_CTRL_RJW(x) (((x) & 0x03) << 22) +#define FLEXCAN_CTRL_PSEG1(x) (((x) & 0x07) << 19) +#define FLEXCAN_CTRL_PSEG2(x) (((x) & 0x07) << 16) +#define FLEXCAN_CTRL_BOFF_MSK BIT(15) +#define FLEXCAN_CTRL_ERR_MSK BIT(14) +#define FLEXCAN_CTRL_CLK_SRC BIT(13) +#define FLEXCAN_CTRL_LPB BIT(12) +#define FLEXCAN_CTRL_TWRN_MSK BIT(11) +#define FLEXCAN_CTRL_RWRN_MSK BIT(10) +#define FLEXCAN_CTRL_SMP BIT(7) +#define FLEXCAN_CTRL_BOFF_REC BIT(6) +#define FLEXCAN_CTRL_TSYN BIT(5) +#define FLEXCAN_CTRL_LBUF BIT(4) +#define FLEXCAN_CTRL_LOM BIT(3) +#define FLEXCAN_CTRL_PROPSEG(x) ((x) & 0x07) +#define FLEXCAN_CTRL_ERR_BUS (FLEXCAN_CTRL_ERR_MSK) +#define FLEXCAN_CTRL_ERR_STATE \ + (FLEXCAN_CTRL_TWRN_MSK | FLEXCAN_CTRL_RWRN_MSK | \ + FLEXCAN_CTRL_BOFF_MSK) +#define FLEXCAN_CTRL_ERR_ALL \ + (FLEXCAN_CTRL_ERR_BUS | FLEXCAN_CTRL_ERR_STATE) + +/* FLEXCAN error and status register (ESR) bits */ +#define FLEXCAN_ESR_TWRN_INT BIT(17) +#define FLEXCAN_ESR_RWRN_INT BIT(16) +#define FLEXCAN_ESR_BIT1_ERR BIT(15) +#define FLEXCAN_ESR_BIT0_ERR BIT(14) +#define FLEXCAN_ESR_ACK_ERR BIT(13) +#define FLEXCAN_ESR_CRC_ERR BIT(12) +#define FLEXCAN_ESR_FRM_ERR BIT(11) +#define FLEXCAN_ESR_STF_ERR BIT(10) +#define FLEXCAN_ESR_TX_WRN BIT(9) +#define FLEXCAN_ESR_RX_WRN BIT(8) +#define FLEXCAN_ESR_IDLE BIT(7) +#define FLEXCAN_ESR_TXRX BIT(6) +#define FLEXCAN_EST_FLT_CONF_SHIFT (4) +#define FLEXCAN_ESR_FLT_CONF_MASK (0x3 << FLEXCAN_EST_FLT_CONF_SHIFT) +#define FLEXCAN_ESR_FLT_CONF_ACTIVE (0x0 << FLEXCAN_EST_FLT_CONF_SHIFT) +#define FLEXCAN_ESR_FLT_CONF_PASSIVE (0x1 << FLEXCAN_EST_FLT_CONF_SHIFT) +#define FLEXCAN_ESR_BOFF_INT BIT(2) +#define FLEXCAN_ESR_ERR_INT BIT(1) +#define FLEXCAN_ESR_WAK_INT BIT(0) +#define FLEXCAN_ESR_ERR_BUS \ + (FLEXCAN_ESR_BIT1_ERR | FLEXCAN_ESR_BIT0_ERR | \ + FLEXCAN_ESR_ACK_ERR | FLEXCAN_ESR_CRC_ERR | \ + FLEXCAN_ESR_FRM_ERR | FLEXCAN_ESR_STF_ERR) +#define FLEXCAN_ESR_ERR_STATE \ + (FLEXCAN_ESR_TWRN_INT | FLEXCAN_ESR_RWRN_INT | FLEXCAN_ESR_BOFF_INT) +#define FLEXCAN_ESR_ERR_ALL \ + (FLEXCAN_ESR_ERR_BUS | FLEXCAN_ESR_ERR_STATE) + +/* FLEXCAN interrupt flag register (IFLAG) bits */ +#define FLEXCAN_TX_BUF_ID 8 +#define FLEXCAN_IFLAG_BUF(x) BIT(x) +#define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW BIT(7) +#define FLEXCAN_IFLAG_RX_FIFO_WARN BIT(6) +#define FLEXCAN_IFLAG_RX_FIFO_AVAILABLE BIT(5) +#define FLEXCAN_IFLAG_DEFAULT \ + (FLEXCAN_IFLAG_RX_FIFO_OVERFLOW | FLEXCAN_IFLAG_RX_FIFO_AVAILABLE | \ + FLEXCAN_IFLAG_BUF(FLEXCAN_TX_BUF_ID)) + +/* FLEXCAN message buffers */ +#define FLEXCAN_MB_CNT_CODE(x) (((x) & 0xf) << 24) +#define FLEXCAN_MB_CNT_SRR BIT(22) +#define FLEXCAN_MB_CNT_IDE BIT(21) +#define FLEXCAN_MB_CNT_RTR BIT(20) +#define FLEXCAN_MB_CNT_LENGTH(x) (((x) & 0xf) << 16) +#define FLEXCAN_MB_CNT_TIMESTAMP(x) ((x) & 0xffff) + +#define FLEXCAN_MB_CODE_MASK (0xf0ffffff) + +/* Structure of the message buffer */ +struct flexcan_mb { + u32 can_ctrl; + u32 can_id; + u32 data[2]; +}; + +/* Structure of the hardware registers */ +struct flexcan_regs { + u32 mcr; /* 0x00 */ + u32 ctrl; /* 0x04 */ + u32 timer; /* 0x08 */ + u32 _reserved1; /* 0x0c */ + u32 rxgmask; /* 0x10 */ + u32 rx14mask; /* 0x14 */ + u32 rx15mask; /* 0x18 */ + u32 ecr; /* 0x1c */ + u32 esr; /* 0x20 */ + u32 imask2; /* 0x24 */ + u32 imask1; /* 0x28 */ + u32 iflag2; /* 0x2c */ + u32 iflag1; /* 0x30 */ + u32 _reserved2[19]; + struct flexcan_mb cantxfg[64]; +}; + +struct flexcan_priv { + struct can_priv can; + struct net_device *dev; + struct napi_struct napi; + + void __iomem *base; + u32 reg_esr; + u32 reg_ctrl_default; + + struct clk *clk; + struct flexcan_platform_data *pdata; +}; + +static struct can_bittiming_const flexcan_bittiming_const = { + .name = DRV_NAME, + .tseg1_min = 4, + .tseg1_max = 16, + .tseg2_min = 2, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 256, + .brp_inc = 1, +}; + +/* + * Swtich transceiver on or off + */ +static void flexcan_transceiver_switch(const struct flexcan_priv *priv, int on) +{ + if (priv->pdata && priv->pdata->transceiver_switch) + priv->pdata->transceiver_switch(on); +} + +static inline int flexcan_has_and_handle_berr(const struct flexcan_priv *priv, + u32 reg_esr) +{ + return (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) && + (reg_esr & FLEXCAN_ESR_ERR_BUS); +} + +static inline void flexcan_chip_enable(struct flexcan_priv *priv) +{ + struct flexcan_regs __iomem *regs = priv->base; + u32 reg; + + reg = readl(®s->mcr); + reg &= ~FLEXCAN_MCR_MDIS; + writel(reg, ®s->mcr); + + udelay(10); +} + +static inline void flexcan_chip_disable(struct flexcan_priv *priv) +{ + struct flexcan_regs __iomem *regs = priv->base; + u32 reg; + + reg = readl(®s->mcr); + reg |= FLEXCAN_MCR_MDIS; + writel(reg, ®s->mcr); +} + +static int flexcan_get_berr_counter(const struct net_device *dev, + struct can_berr_counter *bec) +{ + const struct flexcan_priv *priv = netdev_priv(dev); + struct flexcan_regs __iomem *regs = priv->base; + u32 reg = readl(®s->ecr); + + bec->txerr = (reg >> 0) & 0xff; + bec->rxerr = (reg >> 8) & 0xff; + + return 0; +} + +static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + const struct flexcan_priv *priv = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; + struct flexcan_regs __iomem *regs = priv->base; + struct can_frame *cf = (struct can_frame *)skb->data; + u32 can_id; + u32 ctrl = FLEXCAN_MB_CNT_CODE(0xc) | (cf->can_dlc << 16); + + if (can_dropped_invalid_skb(dev, skb)) + return NETDEV_TX_OK; + + netif_stop_queue(dev); + + if (cf->can_id & CAN_EFF_FLAG) { + can_id = cf->can_id & CAN_EFF_MASK; + ctrl |= FLEXCAN_MB_CNT_IDE | FLEXCAN_MB_CNT_SRR; + } else { + can_id = (cf->can_id & CAN_SFF_MASK) << 18; + } + + if (cf->can_id & CAN_RTR_FLAG) + ctrl |= FLEXCAN_MB_CNT_RTR; + + if (cf->can_dlc > 0) { + u32 data = be32_to_cpup((__be32 *)&cf->data[0]); + writel(data, ®s->cantxfg[FLEXCAN_TX_BUF_ID].data[0]); + } + if (cf->can_dlc > 3) { + u32 data = be32_to_cpup((__be32 *)&cf->data[4]); + writel(data, ®s->cantxfg[FLEXCAN_TX_BUF_ID].data[1]); + } + + writel(can_id, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_id); + writel(ctrl, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); + + kfree_skb(skb); + + /* tx_packets is incremented in flexcan_irq */ + stats->tx_bytes += cf->can_dlc; + + return NETDEV_TX_OK; +} + +static void do_bus_err(struct net_device *dev, + struct can_frame *cf, u32 reg_esr) +{ + struct flexcan_priv *priv = netdev_priv(dev); + int rx_errors = 0, tx_errors = 0; + + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; + + if (reg_esr & FLEXCAN_ESR_BIT1_ERR) { + dev_dbg(dev->dev.parent, "BIT1_ERR irq\n"); + cf->data[2] |= CAN_ERR_PROT_BIT1; + tx_errors = 1; + } + if (reg_esr & FLEXCAN_ESR_BIT0_ERR) { + dev_dbg(dev->dev.parent, "BIT0_ERR irq\n"); + cf->data[2] |= CAN_ERR_PROT_BIT0; + tx_errors = 1; + } + if (reg_esr & FLEXCAN_ESR_ACK_ERR) { + dev_dbg(dev->dev.parent, "ACK_ERR irq\n"); + cf->can_id |= CAN_ERR_ACK; + cf->data[3] |= CAN_ERR_PROT_LOC_ACK; + tx_errors = 1; + } + if (reg_esr & FLEXCAN_ESR_CRC_ERR) { + dev_dbg(dev->dev.parent, "CRC_ERR irq\n"); + cf->data[2] |= CAN_ERR_PROT_BIT; + cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ; + rx_errors = 1; + } + if (reg_esr & FLEXCAN_ESR_FRM_ERR) { + dev_dbg(dev->dev.parent, "FRM_ERR irq\n"); + cf->data[2] |= CAN_ERR_PROT_FORM; + rx_errors = 1; + } + if (reg_esr & FLEXCAN_ESR_STF_ERR) { + dev_dbg(dev->dev.parent, "STF_ERR irq\n"); + cf->data[2] |= CAN_ERR_PROT_STUFF; + rx_errors = 1; + } + + priv->can.can_stats.bus_error++; + if (rx_errors) + dev->stats.rx_errors++; + if (tx_errors) + dev->stats.tx_errors++; +} + +static int flexcan_poll_bus_err(struct net_device *dev, u32 reg_esr) +{ + struct sk_buff *skb; + struct can_frame *cf; + + skb = alloc_can_err_skb(dev, &cf); + if (unlikely(!skb)) + return 0; + + do_bus_err(dev, cf, reg_esr); + netif_receive_skb(skb); + + dev->stats.rx_packets++; + dev->stats.rx_bytes += cf->can_dlc; + + return 1; +} + +static void do_state(struct net_device *dev, + struct can_frame *cf, enum can_state new_state) +{ + struct flexcan_priv *priv = netdev_priv(dev); + struct can_berr_counter bec; + + flexcan_get_berr_counter(dev, &bec); + + switch (priv->can.state) { + case CAN_STATE_ERROR_ACTIVE: + /* + * from: ERROR_ACTIVE + * to : ERROR_WARNING, ERROR_PASSIVE, BUS_OFF + * => : there was a warning int + */ + if (new_state >= CAN_STATE_ERROR_WARNING && + new_state <= CAN_STATE_BUS_OFF) { + dev_dbg(dev->dev.parent, "Error Warning IRQ\n"); + priv->can.can_stats.error_warning++; + + cf->can_id |= CAN_ERR_CRTL; + cf->data[1] = (bec.txerr > bec.rxerr) ? + CAN_ERR_CRTL_TX_WARNING : + CAN_ERR_CRTL_RX_WARNING; + } + case CAN_STATE_ERROR_WARNING: /* fallthrough */ + /* + * from: ERROR_ACTIVE, ERROR_WARNING + * to : ERROR_PASSIVE, BUS_OFF + * => : error passive int + */ + if (new_state >= CAN_STATE_ERROR_PASSIVE && + new_state <= CAN_STATE_BUS_OFF) { + dev_dbg(dev->dev.parent, "Error Passive IRQ\n"); + priv->can.can_stats.error_passive++; + + cf->can_id |= CAN_ERR_CRTL; + cf->data[1] = (bec.txerr > bec.rxerr) ? + CAN_ERR_CRTL_TX_PASSIVE : + CAN_ERR_CRTL_RX_PASSIVE; + } + break; + case CAN_STATE_BUS_OFF: + dev_err(dev->dev.parent, + "BUG! hardware recovered automatically from BUS_OFF\n"); + break; + default: + break; + } + + /* process state changes depending on the new state */ + switch (new_state) { + case CAN_STATE_ERROR_ACTIVE: + dev_dbg(dev->dev.parent, "Error Active\n"); + cf->can_id |= CAN_ERR_PROT; + cf->data[2] = CAN_ERR_PROT_ACTIVE; + break; + case CAN_STATE_BUS_OFF: + cf->can_id |= CAN_ERR_BUSOFF; + can_bus_off(dev); + break; + default: + break; + } +} + +static int flexcan_poll_state(struct net_device *dev, u32 reg_esr) +{ + struct flexcan_priv *priv = netdev_priv(dev); + struct sk_buff *skb; + struct can_frame *cf; + enum can_state new_state; + int flt; + + flt = reg_esr & FLEXCAN_ESR_FLT_CONF_MASK; + if (likely(flt == FLEXCAN_ESR_FLT_CONF_ACTIVE)) { + if (likely(!(reg_esr & (FLEXCAN_ESR_TX_WRN | + FLEXCAN_ESR_RX_WRN)))) + new_state = CAN_STATE_ERROR_ACTIVE; + else + new_state = CAN_STATE_ERROR_WARNING; + } else if (unlikely(flt == FLEXCAN_ESR_FLT_CONF_PASSIVE)) + new_state = CAN_STATE_ERROR_PASSIVE; + else + new_state = CAN_STATE_BUS_OFF; + + /* state hasn't changed */ + if (likely(new_state == priv->can.state)) + return 0; + + skb = alloc_can_err_skb(dev, &cf); + if (unlikely(!skb)) + return 0; + + do_state(dev, cf, new_state); + priv->can.state = new_state; + netif_receive_skb(skb); + + dev->stats.rx_packets++; + dev->stats.rx_bytes += cf->can_dlc; + + return 1; +} + +static void flexcan_read_fifo(const struct net_device *dev, + struct can_frame *cf) +{ + const struct flexcan_priv *priv = netdev_priv(dev); + struct flexcan_regs __iomem *regs = priv->base; + struct flexcan_mb __iomem *mb = ®s->cantxfg[0]; + u32 reg_ctrl, reg_id; + + reg_ctrl = readl(&mb->can_ctrl); + reg_id = readl(&mb->can_id); + if (reg_ctrl & FLEXCAN_MB_CNT_IDE) + cf->can_id = ((reg_id >> 0) & CAN_EFF_MASK) | CAN_EFF_FLAG; + else + cf->can_id = (reg_id >> 18) & CAN_SFF_MASK; + + if (reg_ctrl & FLEXCAN_MB_CNT_RTR) + cf->can_id |= CAN_RTR_FLAG; + cf->can_dlc = get_can_dlc((reg_ctrl >> 16) & 0xf); + + *(__be32 *)(cf->data + 0) = cpu_to_be32(readl(&mb->data[0])); + *(__be32 *)(cf->data + 4) = cpu_to_be32(readl(&mb->data[1])); + + /* mark as read */ + writel(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, ®s->iflag1); + readl(®s->timer); +} + +static int flexcan_read_frame(struct net_device *dev) +{ + struct net_device_stats *stats = &dev->stats; + struct can_frame *cf; + struct sk_buff *skb; + + skb = alloc_can_skb(dev, &cf); + if (unlikely(!skb)) { + stats->rx_dropped++; + return 0; + } + + flexcan_read_fifo(dev, cf); + netif_receive_skb(skb); + + stats->rx_packets++; + stats->rx_bytes += cf->can_dlc; + + return 1; +} + +static int flexcan_poll(struct napi_struct *napi, int quota) +{ + struct net_device *dev = napi->dev; + const struct flexcan_priv *priv = netdev_priv(dev); + struct flexcan_regs __iomem *regs = priv->base; + u32 reg_iflag1, reg_esr; + int work_done = 0; + + /* + * The error bits are cleared on read, + * use saved value from irq handler. + */ + reg_esr = readl(®s->esr) | priv->reg_esr; + + /* handle state changes */ + work_done += flexcan_poll_state(dev, reg_esr); + + /* handle RX-FIFO */ + reg_iflag1 = readl(®s->iflag1); + while (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE && + work_done < quota) { + work_done += flexcan_read_frame(dev); + reg_iflag1 = readl(®s->iflag1); + } + + /* report bus errors */ + if (flexcan_has_and_handle_berr(priv, reg_esr) && work_done < quota) + work_done += flexcan_poll_bus_err(dev, reg_esr); + + if (work_done < quota) { + napi_complete(napi); + /* enable IRQs */ + writel(FLEXCAN_IFLAG_DEFAULT, ®s->imask1); + writel(priv->reg_ctrl_default, ®s->ctrl); + } + + return work_done; +} + +static irqreturn_t flexcan_irq(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct net_device_stats *stats = &dev->stats; + struct flexcan_priv *priv = netdev_priv(dev); + struct flexcan_regs __iomem *regs = priv->base; + u32 reg_iflag1, reg_esr; + + reg_iflag1 = readl(®s->iflag1); + reg_esr = readl(®s->esr); + writel(FLEXCAN_ESR_ERR_INT, ®s->esr); /* ACK err IRQ */ + + /* + * schedule NAPI in case of: + * - rx IRQ + * - state change IRQ + * - bus error IRQ and bus error reporting is activated + */ + if ((reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE) || + (reg_esr & FLEXCAN_ESR_ERR_STATE) || + flexcan_has_and_handle_berr(priv, reg_esr)) { + /* + * The error bits are cleared on read, + * save them for later use. + */ + priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS; + writel(FLEXCAN_IFLAG_DEFAULT & ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, + ®s->imask1); + writel(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL, + ®s->ctrl); + napi_schedule(&priv->napi); + } + + /* FIFO overflow */ + if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_OVERFLOW) { + writel(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, ®s->iflag1); + dev->stats.rx_over_errors++; + dev->stats.rx_errors++; + } + + /* transmission complete interrupt */ + if (reg_iflag1 & (1 << FLEXCAN_TX_BUF_ID)) { + /* tx_bytes is incremented in flexcan_start_xmit */ + stats->tx_packets++; + writel((1 << FLEXCAN_TX_BUF_ID), ®s->iflag1); + netif_wake_queue(dev); + } + + return IRQ_HANDLED; +} + +static void flexcan_set_bittiming(struct net_device *dev) +{ + const struct flexcan_priv *priv = netdev_priv(dev); + const struct can_bittiming *bt = &priv->can.bittiming; + struct flexcan_regs __iomem *regs = priv->base; + u32 reg; + + reg = readl(®s->ctrl); + reg &= ~(FLEXCAN_CTRL_PRESDIV(0xff) | + FLEXCAN_CTRL_RJW(0x3) | + FLEXCAN_CTRL_PSEG1(0x7) | + FLEXCAN_CTRL_PSEG2(0x7) | + FLEXCAN_CTRL_PROPSEG(0x7) | + FLEXCAN_CTRL_LPB | + FLEXCAN_CTRL_SMP | + FLEXCAN_CTRL_LOM); + + reg |= FLEXCAN_CTRL_PRESDIV(bt->brp - 1) | + FLEXCAN_CTRL_PSEG1(bt->phase_seg1 - 1) | + FLEXCAN_CTRL_PSEG2(bt->phase_seg2 - 1) | + FLEXCAN_CTRL_RJW(bt->sjw - 1) | + FLEXCAN_CTRL_PROPSEG(bt->prop_seg - 1); + + if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) + reg |= FLEXCAN_CTRL_LPB; + if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) + reg |= FLEXCAN_CTRL_LOM; + if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) + reg |= FLEXCAN_CTRL_SMP; + + dev_info(dev->dev.parent, "writing ctrl=0x%08x\n", reg); + writel(reg, ®s->ctrl); + + /* print chip status */ + dev_dbg(dev->dev.parent, "%s: mcr=0x%08x ctrl=0x%08x\n", __func__, + readl(®s->mcr), readl(®s->ctrl)); +} + +/* + * flexcan_chip_start + * + * this functions is entered with clocks enabled + * + */ +static int flexcan_chip_start(struct net_device *dev) +{ + struct flexcan_priv *priv = netdev_priv(dev); + struct flexcan_regs __iomem *regs = priv->base; + unsigned int i; + int err; + u32 reg_mcr, reg_ctrl; + + /* enable module */ + flexcan_chip_enable(priv); + + /* soft reset */ + writel(FLEXCAN_MCR_SOFTRST, ®s->mcr); + udelay(10); + + reg_mcr = readl(®s->mcr); + if (reg_mcr & FLEXCAN_MCR_SOFTRST) { + dev_err(dev->dev.parent, + "Failed to softreset can module (mcr=0x%08x)\n", + reg_mcr); + err = -ENODEV; + goto out; + } + + flexcan_set_bittiming(dev); + + /* + * MCR + * + * enable freeze + * enable fifo + * halt now + * only supervisor access + * enable warning int + * choose format C + * + */ + reg_mcr = readl(®s->mcr); + reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT | + FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | + FLEXCAN_MCR_IDAM_C; + dev_dbg(dev->dev.parent, "%s: writing mcr=0x%08x", __func__, reg_mcr); + writel(reg_mcr, ®s->mcr); + + /* + * CTRL + * + * disable timer sync feature + * + * disable auto busoff recovery + * transmit lowest buffer first + * + * enable tx and rx warning interrupt + * enable bus off interrupt + * (== FLEXCAN_CTRL_ERR_STATE) + * + * _note_: we enable the "error interrupt" + * (FLEXCAN_CTRL_ERR_MSK), too. Otherwise we don't get any + * warning or bus passive interrupts. + */ + reg_ctrl = readl(®s->ctrl); + reg_ctrl &= ~FLEXCAN_CTRL_TSYN; + reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF | + FLEXCAN_CTRL_ERR_STATE | FLEXCAN_CTRL_ERR_MSK; + + /* save for later use */ + priv->reg_ctrl_default = reg_ctrl; + dev_dbg(dev->dev.parent, "%s: writing ctrl=0x%08x", __func__, reg_ctrl); + writel(reg_ctrl, ®s->ctrl); + + for (i = 0; i < ARRAY_SIZE(regs->cantxfg); i++) { + writel(0, ®s->cantxfg[i].can_ctrl); + writel(0, ®s->cantxfg[i].can_id); + writel(0, ®s->cantxfg[i].data[0]); + writel(0, ®s->cantxfg[i].data[1]); + + /* put MB into rx queue */ + writel(FLEXCAN_MB_CNT_CODE(0x4), ®s->cantxfg[i].can_ctrl); + } + + /* acceptance mask/acceptance code (accept everything) */ + writel(0x0, ®s->rxgmask); + writel(0x0, ®s->rx14mask); + writel(0x0, ®s->rx15mask); + + flexcan_transceiver_switch(priv, 1); + + /* synchronize with the can bus */ + reg_mcr = readl(®s->mcr); + reg_mcr &= ~FLEXCAN_MCR_HALT; + writel(reg_mcr, ®s->mcr); + + priv->can.state = CAN_STATE_ERROR_ACTIVE; + + /* enable FIFO interrupts */ + writel(FLEXCAN_IFLAG_DEFAULT, ®s->imask1); + + /* print chip status */ + dev_dbg(dev->dev.parent, "%s: reading mcr=0x%08x ctrl=0x%08x\n", + __func__, readl(®s->mcr), readl(®s->ctrl)); + + return 0; + + out: + flexcan_chip_disable(priv); + return err; +} + +/* + * flexcan_chip_stop + * + * this functions is entered with clocks enabled + * + */ +static void flexcan_chip_stop(struct net_device *dev) +{ + struct flexcan_priv *priv = netdev_priv(dev); + struct flexcan_regs __iomem *regs = priv->base; + u32 reg; + + /* Disable all interrupts */ + writel(0, ®s->imask1); + + /* Disable + halt module */ + reg = readl(®s->mcr); + reg |= FLEXCAN_MCR_MDIS | FLEXCAN_MCR_HALT; + writel(reg, ®s->mcr); + + flexcan_transceiver_switch(priv, 0); + priv->can.state = CAN_STATE_STOPPED; + + return; +} + +static int flexcan_open(struct net_device *dev) +{ + struct flexcan_priv *priv = netdev_priv(dev); + int err; + + clk_enable(priv->clk); + + err = open_candev(dev); + if (err) + goto out; + + err = request_irq(dev->irq, flexcan_irq, IRQF_SHARED, dev->name, dev); + if (err) + goto out_close; + + /* start chip and queuing */ + err = flexcan_chip_start(dev); + if (err) + goto out_close; + napi_enable(&priv->napi); + netif_start_queue(dev); + + return 0; + + out_close: + close_candev(dev); + out: + clk_disable(priv->clk); + + return err; +} + +static int flexcan_close(struct net_device *dev) +{ + struct flexcan_priv *priv = netdev_priv(dev); + + netif_stop_queue(dev); + napi_disable(&priv->napi); + flexcan_chip_stop(dev); + + free_irq(dev->irq, dev); + clk_disable(priv->clk); + + close_candev(dev); + + return 0; +} + +static int flexcan_set_mode(struct net_device *dev, enum can_mode mode) +{ + int err; + + switch (mode) { + case CAN_MODE_START: + err = flexcan_chip_start(dev); + if (err) + return err; + + netif_wake_queue(dev); + break; + + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static const struct net_device_ops flexcan_netdev_ops = { + .ndo_open = flexcan_open, + .ndo_stop = flexcan_close, + .ndo_start_xmit = flexcan_start_xmit, +}; + +static int __devinit register_flexcandev(struct net_device *dev) +{ + struct flexcan_priv *priv = netdev_priv(dev); + struct flexcan_regs __iomem *regs = priv->base; + u32 reg, err; + + clk_enable(priv->clk); + + /* select "bus clock", chip must be disabled */ + flexcan_chip_disable(priv); + reg = readl(®s->ctrl); + reg |= FLEXCAN_CTRL_CLK_SRC; + writel(reg, ®s->ctrl); + + flexcan_chip_enable(priv); + + /* set freeze, halt and activate FIFO, restrict register access */ + reg = readl(®s->mcr); + reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT | + FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV; + writel(reg, ®s->mcr); + + /* + * Currently we only support newer versions of this core + * featuring a RX FIFO. Older cores found on some Coldfire + * derivates are not yet supported. + */ + reg = readl(®s->mcr); + if (!(reg & FLEXCAN_MCR_FEN)) { + dev_err(dev->dev.parent, + "Could not enable RX FIFO, unsupported core\n"); + err = -ENODEV; + goto out; + } + + err = register_candev(dev); + + out: + /* disable core and turn off clocks */ + flexcan_chip_disable(priv); + clk_disable(priv->clk); + + return err; +} + +static void __devexit unregister_flexcandev(struct net_device *dev) +{ + unregister_candev(dev); +} + +static int __devinit flexcan_probe(struct platform_device *pdev) +{ + struct net_device *dev; + struct flexcan_priv *priv; + struct resource *mem; + struct clk *clk; + void __iomem *base; + resource_size_t mem_size; + int err, irq; + + clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "no clock defined\n"); + err = PTR_ERR(clk); + goto failed_clock; + } + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq = platform_get_irq(pdev, 0); + if (!mem || irq <= 0) { + err = -ENODEV; + goto failed_get; + } + + mem_size = resource_size(mem); + if (!request_mem_region(mem->start, mem_size, pdev->name)) { + err = -EBUSY; + goto failed_req; + } + + base = ioremap(mem->start, mem_size); + if (!base) { + err = -ENOMEM; + goto failed_map; + } + + dev = alloc_candev(sizeof(struct flexcan_priv), 0); + if (!dev) { + err = -ENOMEM; + goto failed_alloc; + } + + dev->netdev_ops = &flexcan_netdev_ops; + dev->irq = irq; + dev->flags |= IFF_ECHO; /* we support local echo in hardware */ + + priv = netdev_priv(dev); + priv->can.clock.freq = clk_get_rate(clk); + priv->can.bittiming_const = &flexcan_bittiming_const; + priv->can.do_set_mode = flexcan_set_mode; + priv->can.do_get_berr_counter = flexcan_get_berr_counter; + priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | + CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_BERR_REPORTING; + priv->base = base; + priv->dev = dev; + priv->clk = clk; + priv->pdata = pdev->dev.platform_data; + + netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT); + + dev_set_drvdata(&pdev->dev, dev); + SET_NETDEV_DEV(dev, &pdev->dev); + + err = register_flexcandev(dev); + if (err) { + dev_err(&pdev->dev, "registering netdev failed\n"); + goto failed_register; + } + + dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%d)\n", + priv->base, dev->irq); + + return 0; + + failed_register: + free_candev(dev); + failed_alloc: + iounmap(base); + failed_map: + release_mem_region(mem->start, mem_size); + failed_req: + clk_put(clk); + failed_get: + failed_clock: + return err; +} + +static int __devexit flexcan_remove(struct platform_device *pdev) +{ + struct net_device *dev = platform_get_drvdata(pdev); + struct flexcan_priv *priv = netdev_priv(dev); + struct resource *mem; + + unregister_flexcandev(dev); + platform_set_drvdata(pdev, NULL); + free_candev(dev); + iounmap(priv->base); + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(mem->start, resource_size(mem)); + + clk_put(priv->clk); + + return 0; +} + +static struct platform_driver flexcan_driver = { + .driver.name = DRV_NAME, + .probe = flexcan_probe, + .remove = __devexit_p(flexcan_remove), +}; + +static int __init flexcan_init(void) +{ + pr_info("%s netdevice driver\n", DRV_NAME); + return platform_driver_register(&flexcan_driver); +} + +static void __exit flexcan_exit(void) +{ + platform_driver_unregister(&flexcan_driver); + pr_info("%s: driver removed\n", DRV_NAME); +} + +module_init(flexcan_init); +module_exit(flexcan_exit); + +MODULE_AUTHOR("Sascha Hauer <kernel@pengutronix.de>, " + "Marc Kleine-Budde <kernel@pengutronix.de>"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("CAN port driver for flexcan based chip"); diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 5ecf0bcf372..09610323a94 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -40,9 +40,9 @@ #include "cnic_if.h" #include "bnx2.h" -#include "bnx2x_reg.h" -#include "bnx2x_fw_defs.h" -#include "bnx2x_hsi.h" +#include "bnx2x/bnx2x_reg.h" +#include "bnx2x/bnx2x_fw_defs.h" +#include "bnx2x/bnx2x_hsi.h" #include "../scsi/bnx2i/57xx_iscsi_constants.h" #include "../scsi/bnx2i/57xx_iscsi_hsi.h" #include "cnic.h" diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 25e14d2da75..2fe709f98cc 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -298,6 +298,11 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_CTRL_EWCTL (0x4) #define EMAC_CTRL_EWINTTCNT (0x8) +/* EMAC DM644x control module masks */ +#define EMAC_DM644X_EWINTCNT_MASK 0x1FFFF +#define EMAC_DM644X_INTMIN_INTVL 0x1 +#define EMAC_DM644X_INTMAX_INTVL (EMAC_DM644X_EWINTCNT_MASK) + /* EMAC MDIO related */ /* Mask & Control defines */ #define MDIO_CONTROL_CLKDIV (0xFF) @@ -318,8 +323,20 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define MDIO_CONTROL (0x04) /* EMAC DM646X control module registers */ -#define EMAC_DM646X_CMRXINTEN (0x14) -#define EMAC_DM646X_CMTXINTEN (0x18) +#define EMAC_DM646X_CMINTCTRL 0x0C +#define EMAC_DM646X_CMRXINTEN 0x14 +#define EMAC_DM646X_CMTXINTEN 0x18 +#define EMAC_DM646X_CMRXINTMAX 0x70 +#define EMAC_DM646X_CMTXINTMAX 0x74 + +/* EMAC DM646X control module masks */ +#define EMAC_DM646X_INTPACEEN (0x3 << 16) +#define EMAC_DM646X_INTPRESCALE_MASK (0x7FF << 0) +#define EMAC_DM646X_CMINTMAX_CNT 63 +#define EMAC_DM646X_CMINTMIN_CNT 2 +#define EMAC_DM646X_CMINTMAX_INTVL (1000 / EMAC_DM646X_CMINTMIN_CNT) +#define EMAC_DM646X_CMINTMIN_INTVL ((1000 / EMAC_DM646X_CMINTMAX_CNT) + 1) + /* EMAC EOI codes for C0 */ #define EMAC_DM646X_MAC_EOI_C0_RXEN (0x01) @@ -468,6 +485,8 @@ struct emac_priv { u32 duplex; /* Link duplex: 0=Half, 1=Full */ u32 rx_buf_size; u32 isr_count; + u32 coal_intvl; + u32 bus_freq_mhz; u8 rmii_en; u8 version; u32 mac_hash1; @@ -545,9 +564,11 @@ static void emac_dump_regs(struct emac_priv *priv) /* Print important registers in EMAC */ dev_info(emac_dev, "EMAC Basic registers\n"); - dev_info(emac_dev, "EMAC: EWCTL: %08X, EWINTTCNT: %08X\n", - emac_ctrl_read(EMAC_CTRL_EWCTL), - emac_ctrl_read(EMAC_CTRL_EWINTTCNT)); + if (priv->version == EMAC_VERSION_1) { + dev_info(emac_dev, "EMAC: EWCTL: %08X, EWINTTCNT: %08X\n", + emac_ctrl_read(EMAC_CTRL_EWCTL), + emac_ctrl_read(EMAC_CTRL_EWINTTCNT)); + } dev_info(emac_dev, "EMAC: TXID: %08X %s, RXID: %08X %s\n", emac_read(EMAC_TXIDVER), ((emac_read(EMAC_TXCONTROL)) ? "enabled" : "disabled"), @@ -691,6 +712,103 @@ static int emac_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) } /** + * emac_get_coalesce : Get interrupt coalesce settings for this device + * @ndev : The DaVinci EMAC network adapter + * @coal : ethtool coalesce settings structure + * + * Fetch the current interrupt coalesce settings + * + */ +static int emac_get_coalesce(struct net_device *ndev, + struct ethtool_coalesce *coal) +{ + struct emac_priv *priv = netdev_priv(ndev); + + coal->rx_coalesce_usecs = priv->coal_intvl; + return 0; + +} + +/** + * emac_set_coalesce : Set interrupt coalesce settings for this device + * @ndev : The DaVinci EMAC network adapter + * @coal : ethtool coalesce settings structure + * + * Set interrupt coalesce parameters + * + */ +static int emac_set_coalesce(struct net_device *ndev, + struct ethtool_coalesce *coal) +{ + struct emac_priv *priv = netdev_priv(ndev); + u32 int_ctrl, num_interrupts = 0; + u32 prescale = 0, addnl_dvdr = 1, coal_intvl = 0; + + if (!coal->rx_coalesce_usecs) + return -EINVAL; + + coal_intvl = coal->rx_coalesce_usecs; + + switch (priv->version) { + case EMAC_VERSION_2: + int_ctrl = emac_ctrl_read(EMAC_DM646X_CMINTCTRL); + prescale = priv->bus_freq_mhz * 4; + + if (coal_intvl < EMAC_DM646X_CMINTMIN_INTVL) + coal_intvl = EMAC_DM646X_CMINTMIN_INTVL; + + if (coal_intvl > EMAC_DM646X_CMINTMAX_INTVL) { + /* + * Interrupt pacer works with 4us Pulse, we can + * throttle further by dilating the 4us pulse. + */ + addnl_dvdr = EMAC_DM646X_INTPRESCALE_MASK / prescale; + + if (addnl_dvdr > 1) { + prescale *= addnl_dvdr; + if (coal_intvl > (EMAC_DM646X_CMINTMAX_INTVL + * addnl_dvdr)) + coal_intvl = (EMAC_DM646X_CMINTMAX_INTVL + * addnl_dvdr); + } else { + addnl_dvdr = 1; + coal_intvl = EMAC_DM646X_CMINTMAX_INTVL; + } + } + + num_interrupts = (1000 * addnl_dvdr) / coal_intvl; + + int_ctrl |= EMAC_DM646X_INTPACEEN; + int_ctrl &= (~EMAC_DM646X_INTPRESCALE_MASK); + int_ctrl |= (prescale & EMAC_DM646X_INTPRESCALE_MASK); + emac_ctrl_write(EMAC_DM646X_CMINTCTRL, int_ctrl); + + emac_ctrl_write(EMAC_DM646X_CMRXINTMAX, num_interrupts); + emac_ctrl_write(EMAC_DM646X_CMTXINTMAX, num_interrupts); + + break; + default: + int_ctrl = emac_ctrl_read(EMAC_CTRL_EWINTTCNT); + int_ctrl &= (~EMAC_DM644X_EWINTCNT_MASK); + prescale = coal_intvl * priv->bus_freq_mhz; + if (prescale > EMAC_DM644X_EWINTCNT_MASK) { + prescale = EMAC_DM644X_EWINTCNT_MASK; + coal_intvl = prescale / priv->bus_freq_mhz; + } + emac_ctrl_write(EMAC_CTRL_EWINTTCNT, (int_ctrl | prescale)); + + break; + } + + printk(KERN_INFO"Set coalesce to %d usecs.\n", coal_intvl); + priv->coal_intvl = coal_intvl; + + return 0; + +} + + +/** * ethtool_ops: DaVinci EMAC Ethtool structure * * Ethtool support for EMAC adapter @@ -701,6 +819,8 @@ static const struct ethtool_ops ethtool_ops = { .get_settings = emac_get_settings, .set_settings = emac_set_settings, .get_link = ethtool_op_get_link, + .get_coalesce = emac_get_coalesce, + .set_coalesce = emac_set_coalesce, }; /** @@ -2148,7 +2268,7 @@ static int emac_poll(struct napi_struct *napi, int budget) struct net_device *ndev = priv->ndev; struct device *emac_dev = &ndev->dev; u32 status = 0; - u32 num_pkts = 0; + u32 num_tx_pkts = 0, num_rx_pkts = 0; /* Check interrupt vectors and call packet processing */ status = emac_read(EMAC_MACINVECTOR); @@ -2159,27 +2279,19 @@ static int emac_poll(struct napi_struct *napi, int budget) mask = EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC; if (status & mask) { - num_pkts = emac_tx_bdproc(priv, EMAC_DEF_TX_CH, + num_tx_pkts = emac_tx_bdproc(priv, EMAC_DEF_TX_CH, EMAC_DEF_TX_MAX_SERVICE); } /* TX processing */ - if (num_pkts) - return budget; - mask = EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC; if (priv->version == EMAC_VERSION_2) mask = EMAC_DM646X_MAC_IN_VECTOR_RX_INT_VEC; if (status & mask) { - num_pkts = emac_rx_bdproc(priv, EMAC_DEF_RX_CH, budget); + num_rx_pkts = emac_rx_bdproc(priv, EMAC_DEF_RX_CH, budget); } /* RX processing */ - if (num_pkts < budget) { - napi_complete(napi); - emac_int_enable(priv); - } - mask = EMAC_DM644X_MAC_IN_VECTOR_HOST_INT; if (priv->version == EMAC_VERSION_2) mask = EMAC_DM646X_MAC_IN_VECTOR_HOST_INT; @@ -2210,9 +2322,12 @@ static int emac_poll(struct napi_struct *napi, int budget) dev_err(emac_dev, "RX Host error %s on ch=%d\n", &emac_rxhost_errcodes[cause][0], ch); } - } /* Host error processing */ + } else if (num_rx_pkts < budget) { + napi_complete(napi); + emac_int_enable(priv); + } - return num_pkts; + return num_rx_pkts; } #ifdef CONFIG_NET_POLL_CONTROLLER @@ -2437,6 +2552,14 @@ static int emac_dev_open(struct net_device *ndev) /* Start/Enable EMAC hardware */ emac_hw_enable(priv); + /* Enable Interrupt pacing if configured */ + if (priv->coal_intvl != 0) { + struct ethtool_coalesce coal; + + coal.rx_coalesce_usecs = (priv->coal_intvl << 4); + emac_set_coalesce(ndev, &coal); + } + /* find the first phy */ priv->phydev = NULL; if (priv->phy_mask) { @@ -2677,6 +2800,9 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) priv->int_enable = pdata->interrupt_enable; priv->int_disable = pdata->interrupt_disable; + priv->coal_intvl = 0; + priv->bus_freq_mhz = (u32)(emac_bus_frequency / 1000000); + emac_dev = &ndev->dev; /* Get EMAC platform data */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c index 4ea7141f525..7c075756611 100644 --- a/drivers/net/dnet.c +++ b/drivers/net/dnet.c @@ -854,7 +854,7 @@ static int __devinit dnet_probe(struct platform_device *pdev) dev = alloc_etherdev(sizeof(*bp)); if (!dev) { dev_err(&pdev->dev, "etherdev alloc failed, aborting.\n"); - goto err_out; + goto err_out_release_mem; } /* TODO: Actually, we have some interesting features... */ @@ -911,7 +911,8 @@ static int __devinit dnet_probe(struct platform_device *pdev) if (err) dev_warn(&pdev->dev, "Cannot register PHY board fixup.\n"); - if (dnet_mii_init(bp) != 0) + err = dnet_mii_init(bp); + if (err) goto err_out_unregister_netdev; dev_info(&pdev->dev, "Dave DNET at 0x%p (0x%08x) irq %d %pM\n", @@ -936,6 +937,8 @@ err_out_iounmap: iounmap(bp->regs); err_out_free_dev: free_netdev(dev); +err_out_release_mem: + release_mem_region(mem_base, mem_size); err_out: return err; } diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 65298a6d9af..99288b95aea 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -324,18 +324,20 @@ enum e1000_state_t { extern struct net_device *e1000_get_hw_dev(struct e1000_hw *hw); #define e_dbg(format, arg...) \ netdev_dbg(e1000_get_hw_dev(hw), format, ## arg) -#define e_err(format, arg...) \ - netdev_err(adapter->netdev, format, ## arg) -#define e_info(format, arg...) \ - netdev_info(adapter->netdev, format, ## arg) -#define e_warn(format, arg...) \ - netdev_warn(adapter->netdev, format, ## arg) -#define e_notice(format, arg...) \ - netdev_notice(adapter->netdev, format, ## arg) +#define e_err(msglvl, format, arg...) \ + netif_err(adapter, msglvl, adapter->netdev, format, ## arg) +#define e_info(msglvl, format, arg...) \ + netif_info(adapter, msglvl, adapter->netdev, format, ## arg) +#define e_warn(msglvl, format, arg...) \ + netif_warn(adapter, msglvl, adapter->netdev, format, ## arg) +#define e_notice(msglvl, format, arg...) \ + netif_notice(adapter, msglvl, adapter->netdev, format, ## arg) #define e_dev_info(format, arg...) \ dev_info(&adapter->pdev->dev, format, ## arg) #define e_dev_warn(format, arg...) \ dev_warn(&adapter->pdev->dev, format, ## arg) +#define e_dev_err(format, arg...) \ + dev_err(&adapter->pdev->dev, format, ## arg) extern char e1000_driver_name[]; extern const char e1000_driver_version[]; diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index d5ff029aa7b..f4d0922ec65 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -346,7 +346,7 @@ static int e1000_set_tso(struct net_device *netdev, u32 data) netdev->features &= ~NETIF_F_TSO6; - e_info("TSO is %s\n", data ? "Enabled" : "Disabled"); + e_info(probe, "TSO is %s\n", data ? "Enabled" : "Disabled"); adapter->tso_force = true; return 0; } @@ -714,9 +714,9 @@ static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data, int reg, writel(write & test[i], address); read = readl(address); if (read != (write & test[i] & mask)) { - e_info("pattern test reg %04X failed: " - "got 0x%08X expected 0x%08X\n", - reg, read, (write & test[i] & mask)); + e_err(drv, "pattern test reg %04X failed: " + "got 0x%08X expected 0x%08X\n", + reg, read, (write & test[i] & mask)); *data = reg; return true; } @@ -734,7 +734,7 @@ static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data, int reg, writel(write & mask, address); read = readl(address); if ((read & mask) != (write & mask)) { - e_err("set/check reg %04X test failed: " + e_err(drv, "set/check reg %04X test failed: " "got 0x%08X expected 0x%08X\n", reg, (read & mask), (write & mask)); *data = reg; @@ -779,7 +779,7 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) ew32(STATUS, toggle); after = er32(STATUS) & toggle; if (value != after) { - e_err("failed STATUS register test got: " + e_err(drv, "failed STATUS register test got: " "0x%08X expected: 0x%08X\n", after, value); *data = 1; return 1; @@ -894,7 +894,8 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) *data = 1; return -1; } - e_info("testing %s interrupt\n", (shared_int ? "shared" : "unshared")); + e_info(hw, "testing %s interrupt\n", (shared_int ? + "shared" : "unshared")); /* Disable all the interrupts */ ew32(IMC, 0xFFFFFFFF); @@ -1561,7 +1562,7 @@ static void e1000_diag_test(struct net_device *netdev, u8 forced_speed_duplex = hw->forced_speed_duplex; u8 autoneg = hw->autoneg; - e_info("offline testing starting\n"); + e_info(hw, "offline testing starting\n"); /* Link test performed before hardware reset so autoneg doesn't * interfere with test result */ @@ -1601,7 +1602,7 @@ static void e1000_diag_test(struct net_device *netdev, if (if_running) dev_open(netdev); } else { - e_info("online testing starting\n"); + e_info(hw, "online testing starting\n"); /* Online tests */ if (e1000_link_test(adapter, &data[4])) eth_test->flags |= ETH_TEST_FL_FAILED; @@ -1694,8 +1695,8 @@ static void e1000_get_wol(struct net_device *netdev, wol->supported &= ~WAKE_UCAST; if (adapter->wol & E1000_WUFC_EX) - e_err("Interface does not support " - "directed (unicast) frame wake-up packets\n"); + e_err(drv, "Interface does not support directed " + "(unicast) frame wake-up packets\n"); break; default: break; @@ -1726,8 +1727,8 @@ static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) switch (hw->device_id) { case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: if (wol->wolopts & WAKE_UCAST) { - e_err("Interface does not support " - "directed (unicast) frame wake-up packets\n"); + e_err(drv, "Interface does not support directed " + "(unicast) frame wake-up packets\n"); return -EOPNOTSUPP; } break; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 68a80893dce..02833af8a0b 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -275,7 +275,7 @@ static int e1000_request_irq(struct e1000_adapter *adapter) err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name, netdev); if (err) { - e_err("Unable to allocate interrupt Error: %d\n", err); + e_err(probe, "Unable to allocate interrupt Error: %d\n", err); } return err; @@ -657,7 +657,7 @@ void e1000_reset(struct e1000_adapter *adapter) ew32(WUC, 0); if (e1000_init_hw(hw)) - e_err("Hardware Error\n"); + e_dev_err("Hardware Error\n"); e1000_update_mng_vlan(adapter); /* if (adapter->hwflags & HWFLAGS_PHY_PWR_BIT) { */ @@ -925,7 +925,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, /* initialize eeprom parameters */ if (e1000_init_eeprom_params(hw)) { - e_err("EEPROM initialization failed\n"); + e_err(probe, "EEPROM initialization failed\n"); goto err_eeprom; } @@ -936,7 +936,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, /* make sure the EEPROM is good */ if (e1000_validate_eeprom_checksum(hw) < 0) { - e_err("The EEPROM Checksum Is Not Valid\n"); + e_err(probe, "The EEPROM Checksum Is Not Valid\n"); e1000_dump_eeprom(adapter); /* * set MAC address to all zeroes to invalidate and temporary @@ -950,14 +950,14 @@ static int __devinit e1000_probe(struct pci_dev *pdev, } else { /* copy the MAC address out of the EEPROM */ if (e1000_read_mac_addr(hw)) - e_err("EEPROM Read Error\n"); + e_err(probe, "EEPROM Read Error\n"); } /* don't block initalization here due to bad MAC address */ memcpy(netdev->dev_addr, hw->mac_addr, netdev->addr_len); memcpy(netdev->perm_addr, hw->mac_addr, netdev->addr_len); if (!is_valid_ether_addr(netdev->perm_addr)) - e_err("Invalid MAC Address\n"); + e_err(probe, "Invalid MAC Address\n"); e1000_get_bus_info(hw); @@ -1047,7 +1047,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, goto err_register; /* print bus type/speed/width info */ - e_info("(PCI%s:%dMHz:%d-bit) %pM\n", + e_info(probe, "(PCI%s:%dMHz:%d-bit) %pM\n", ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""), ((hw->bus_speed == e1000_bus_speed_133) ? 133 : (hw->bus_speed == e1000_bus_speed_120) ? 120 : @@ -1059,7 +1059,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, /* carrier off reporting is important to ethtool even BEFORE open */ netif_carrier_off(netdev); - e_info("Intel(R) PRO/1000 Network Connection\n"); + e_info(probe, "Intel(R) PRO/1000 Network Connection\n"); cards_found++; return 0; @@ -1159,7 +1159,7 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter) /* identify the MAC */ if (e1000_set_mac_type(hw)) { - e_err("Unknown MAC Type\n"); + e_err(probe, "Unknown MAC Type\n"); return -EIO; } @@ -1192,7 +1192,7 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter) adapter->num_rx_queues = 1; if (e1000_alloc_queues(adapter)) { - e_err("Unable to allocate memory for queues\n"); + e_err(probe, "Unable to allocate memory for queues\n"); return -ENOMEM; } @@ -1386,7 +1386,8 @@ static int e1000_setup_tx_resources(struct e1000_adapter *adapter, size = sizeof(struct e1000_buffer) * txdr->count; txdr->buffer_info = vmalloc(size); if (!txdr->buffer_info) { - e_err("Unable to allocate memory for the Tx descriptor ring\n"); + e_err(probe, "Unable to allocate memory for the Tx descriptor " + "ring\n"); return -ENOMEM; } memset(txdr->buffer_info, 0, size); @@ -1401,7 +1402,8 @@ static int e1000_setup_tx_resources(struct e1000_adapter *adapter, if (!txdr->desc) { setup_tx_desc_die: vfree(txdr->buffer_info); - e_err("Unable to allocate memory for the Tx descriptor ring\n"); + e_err(probe, "Unable to allocate memory for the Tx descriptor " + "ring\n"); return -ENOMEM; } @@ -1409,7 +1411,7 @@ setup_tx_desc_die: if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) { void *olddesc = txdr->desc; dma_addr_t olddma = txdr->dma; - e_err("txdr align check failed: %u bytes at %p\n", + e_err(tx_err, "txdr align check failed: %u bytes at %p\n", txdr->size, txdr->desc); /* Try again, without freeing the previous */ txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, @@ -1427,7 +1429,7 @@ setup_tx_desc_die: txdr->dma); dma_free_coherent(&pdev->dev, txdr->size, olddesc, olddma); - e_err("Unable to allocate aligned memory " + e_err(probe, "Unable to allocate aligned memory " "for the transmit descriptor ring\n"); vfree(txdr->buffer_info); return -ENOMEM; @@ -1460,7 +1462,7 @@ int e1000_setup_all_tx_resources(struct e1000_adapter *adapter) for (i = 0; i < adapter->num_tx_queues; i++) { err = e1000_setup_tx_resources(adapter, &adapter->tx_ring[i]); if (err) { - e_err("Allocation for Tx Queue %u failed\n", i); + e_err(probe, "Allocation for Tx Queue %u failed\n", i); for (i-- ; i >= 0; i--) e1000_free_tx_resources(adapter, &adapter->tx_ring[i]); @@ -1580,7 +1582,8 @@ static int e1000_setup_rx_resources(struct e1000_adapter *adapter, size = sizeof(struct e1000_buffer) * rxdr->count; rxdr->buffer_info = vmalloc(size); if (!rxdr->buffer_info) { - e_err("Unable to allocate memory for the Rx descriptor ring\n"); + e_err(probe, "Unable to allocate memory for the Rx descriptor " + "ring\n"); return -ENOMEM; } memset(rxdr->buffer_info, 0, size); @@ -1596,7 +1599,8 @@ static int e1000_setup_rx_resources(struct e1000_adapter *adapter, GFP_KERNEL); if (!rxdr->desc) { - e_err("Unable to allocate memory for the Rx descriptor ring\n"); + e_err(probe, "Unable to allocate memory for the Rx descriptor " + "ring\n"); setup_rx_desc_die: vfree(rxdr->buffer_info); return -ENOMEM; @@ -1606,7 +1610,7 @@ setup_rx_desc_die: if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { void *olddesc = rxdr->desc; dma_addr_t olddma = rxdr->dma; - e_err("rxdr align check failed: %u bytes at %p\n", + e_err(rx_err, "rxdr align check failed: %u bytes at %p\n", rxdr->size, rxdr->desc); /* Try again, without freeing the previous */ rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, @@ -1615,8 +1619,8 @@ setup_rx_desc_die: if (!rxdr->desc) { dma_free_coherent(&pdev->dev, rxdr->size, olddesc, olddma); - e_err("Unable to allocate memory for the Rx descriptor " - "ring\n"); + e_err(probe, "Unable to allocate memory for the Rx " + "descriptor ring\n"); goto setup_rx_desc_die; } @@ -1626,8 +1630,8 @@ setup_rx_desc_die: rxdr->dma); dma_free_coherent(&pdev->dev, rxdr->size, olddesc, olddma); - e_err("Unable to allocate aligned memory for the Rx " - "descriptor ring\n"); + e_err(probe, "Unable to allocate aligned memory for " + "the Rx descriptor ring\n"); goto setup_rx_desc_die; } else { /* Free old allocation, new allocation was successful */ @@ -1659,7 +1663,7 @@ int e1000_setup_all_rx_resources(struct e1000_adapter *adapter) for (i = 0; i < adapter->num_rx_queues; i++) { err = e1000_setup_rx_resources(adapter, &adapter->rx_ring[i]); if (err) { - e_err("Allocation for Rx Queue %u failed\n", i); + e_err(probe, "Allocation for Rx Queue %u failed\n", i); for (i-- ; i >= 0; i--) e1000_free_rx_resources(adapter, &adapter->rx_ring[i]); @@ -2110,7 +2114,7 @@ static void e1000_set_rx_mode(struct net_device *netdev) u32 *mcarray = kcalloc(mta_reg_count, sizeof(u32), GFP_ATOMIC); if (!mcarray) { - e_err("memory allocation failed\n"); + e_err(probe, "memory allocation failed\n"); return; } @@ -2648,7 +2652,8 @@ static bool e1000_tx_csum(struct e1000_adapter *adapter, break; default: if (unlikely(net_ratelimit())) - e_warn("checksum_partial proto=%x!\n", skb->protocol); + e_warn(drv, "checksum_partial proto=%x!\n", + skb->protocol); break; } @@ -2992,7 +2997,8 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, /* fall through */ pull_size = min((unsigned int)4, skb->data_len); if (!__pskb_pull_tail(skb, pull_size)) { - e_err("__pskb_pull_tail failed.\n"); + e_err(drv, "__pskb_pull_tail " + "failed.\n"); dev_kfree_skb_any(skb); return NETDEV_TX_OK; } @@ -3140,7 +3146,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || (max_frame > MAX_JUMBO_FRAME_SIZE)) { - e_err("Invalid MTU setting\n"); + e_err(probe, "Invalid MTU setting\n"); return -EINVAL; } @@ -3148,7 +3154,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) switch (hw->mac_type) { case e1000_undefined ... e1000_82542_rev2_1: if (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)) { - e_err("Jumbo Frames not supported.\n"); + e_err(probe, "Jumbo Frames not supported.\n"); return -EINVAL; } break; @@ -3500,7 +3506,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, !(er32(STATUS) & E1000_STATUS_TXOFF)) { /* detected Tx unit hang */ - e_err("Detected Tx Unit Hang\n" + e_err(drv, "Detected Tx Unit Hang\n" " Tx Queue <%lu>\n" " TDH <%x>\n" " TDT <%x>\n" @@ -3749,7 +3755,7 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter, /* eth type trans needs skb->data to point to something */ if (!pskb_may_pull(skb, ETH_HLEN)) { - e_err("pskb_may_pull failed.\n"); + e_err(drv, "pskb_may_pull failed.\n"); dev_kfree_skb(skb); goto next_desc; } @@ -3874,7 +3880,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, if (adapter->discarding) { /* All receives must fit into a single buffer */ - e_info("Receive packet consumed multiple buffers\n"); + e_dbg("Receive packet consumed multiple buffers\n"); /* recycle */ buffer_info->skb = skb; if (status & E1000_RXD_STAT_EOP) @@ -3986,8 +3992,8 @@ e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter, /* Fix for errata 23, can't cross 64kB boundary */ if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) { struct sk_buff *oldskb = skb; - e_err("skb align check failed: %u bytes at %p\n", - bufsz, skb->data); + e_err(rx_err, "skb align check failed: %u bytes at " + "%p\n", bufsz, skb->data); /* Try again, without freeing the previous */ skb = netdev_alloc_skb_ip_align(netdev, bufsz); /* Failed allocation, critical failure */ @@ -4095,8 +4101,8 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter, /* Fix for errata 23, can't cross 64kB boundary */ if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) { struct sk_buff *oldskb = skb; - e_err("skb align check failed: %u bytes at %p\n", - bufsz, skb->data); + e_err(rx_err, "skb align check failed: %u bytes at " + "%p\n", bufsz, skb->data); /* Try again, without freeing the previous */ skb = netdev_alloc_skb_ip_align(netdev, bufsz); /* Failed allocation, critical failure */ @@ -4141,8 +4147,8 @@ map_skb: if (!e1000_check_64k_bound(adapter, (void *)(unsigned long)buffer_info->dma, adapter->rx_buffer_len)) { - e_err("dma align check failed: %u bytes at %p\n", - adapter->rx_buffer_len, + e_err(rx_err, "dma align check failed: %u bytes at " + "%p\n", adapter->rx_buffer_len, (void *)(unsigned long)buffer_info->dma); dev_kfree_skb(skb); buffer_info->skb = NULL; @@ -4355,7 +4361,7 @@ void e1000_pci_set_mwi(struct e1000_hw *hw) int ret_val = pci_set_mwi(adapter->pdev); if (ret_val) - e_err("Error in setting MWI\n"); + e_err(probe, "Error in setting MWI\n"); } void e1000_pci_clear_mwi(struct e1000_hw *hw) @@ -4486,7 +4492,7 @@ int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) /* Fiber NICs only allow 1000 gbps Full duplex */ if ((hw->media_type == e1000_media_type_fiber) && spddplx != (SPEED_1000 + DUPLEX_FULL)) { - e_err("Unsupported Speed/Duplex configuration\n"); + e_err(probe, "Unsupported Speed/Duplex configuration\n"); return -EINVAL; } @@ -4509,7 +4515,7 @@ int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) break; case SPEED_1000 + DUPLEX_HALF: /* not supported */ default: - e_err("Unsupported Speed/Duplex configuration\n"); + e_err(probe, "Unsupported Speed/Duplex configuration\n"); return -EINVAL; } return 0; diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 6aa795a6160..afd01295fbe 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -5650,8 +5650,6 @@ static int __devinit e1000_probe(struct pci_dev *pdev, if (err) goto err_sw_init; - err = -EIO; - memcpy(&hw->mac.ops, ei->mac_ops, sizeof(hw->mac.ops)); memcpy(&hw->nvm.ops, ei->nvm_ops, sizeof(hw->nvm.ops)); memcpy(&hw->phy.ops, ei->phy_ops, sizeof(hw->phy.ops)); diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index 38c282e6565..6d653c459c1 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c @@ -632,7 +632,7 @@ static void ethoc_mdio_poll(struct net_device *dev) { } -static int ethoc_mdio_probe(struct net_device *dev) +static int __devinit ethoc_mdio_probe(struct net_device *dev) { struct ethoc *priv = netdev_priv(dev); struct phy_device *phy; @@ -871,7 +871,7 @@ static const struct net_device_ops ethoc_netdev_ops = { * ethoc_probe() - initialize OpenCores ethernet MAC * pdev: platform device */ -static int ethoc_probe(struct platform_device *pdev) +static int __devinit ethoc_probe(struct platform_device *pdev) { struct net_device *netdev = NULL; struct resource *res = NULL; @@ -1080,7 +1080,7 @@ out: * ethoc_remove() - shutdown OpenCores ethernet MAC * @pdev: platform device */ -static int ethoc_remove(struct platform_device *pdev) +static int __devexit ethoc_remove(struct platform_device *pdev) { struct net_device *netdev = platform_get_drvdata(pdev); struct ethoc *priv = netdev_priv(netdev); @@ -1121,7 +1121,7 @@ static int ethoc_resume(struct platform_device *pdev) static struct platform_driver ethoc_driver = { .probe = ethoc_probe, - .remove = ethoc_remove, + .remove = __devexit_p(ethoc_remove), .suspend = ethoc_suspend, .resume = ethoc_resume, .driver = { diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 391a553a3ad..768b840aeb6 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -118,6 +118,8 @@ static unsigned char fec_mac_default[] = { #define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */ #define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */ +#define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII) + /* The FEC stores dest/src/type, data, and checksum for receive packets. */ #define PKT_MAXBUF_SIZE 1518 @@ -1213,8 +1215,7 @@ fec_restart(struct net_device *dev, int duplex) writel(0, fep->hwp + FEC_R_DES_ACTIVE); /* Enable interrupts we wish to service */ - writel(FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII, - fep->hwp + FEC_IMASK); + writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); } static void @@ -1233,8 +1234,8 @@ fec_stop(struct net_device *dev) /* Whack a reset. We should wait for this. */ writel(1, fep->hwp + FEC_ECNTRL); udelay(10); - writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); + writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); } static int __devinit diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 9ef6a9d5fbc..4da05b1b445 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -89,8 +89,10 @@ #define DEV_HAS_MSI_X 0x0000080 /* device supports MSI-X */ #define DEV_HAS_POWER_CNTRL 0x0000100 /* device supports power savings */ #define DEV_HAS_STATISTICS_V1 0x0000200 /* device supports hw statistics version 1 */ -#define DEV_HAS_STATISTICS_V2 0x0000600 /* device supports hw statistics version 2 */ -#define DEV_HAS_STATISTICS_V3 0x0000e00 /* device supports hw statistics version 3 */ +#define DEV_HAS_STATISTICS_V2 0x0000400 /* device supports hw statistics version 2 */ +#define DEV_HAS_STATISTICS_V3 0x0000800 /* device supports hw statistics version 3 */ +#define DEV_HAS_STATISTICS_V12 0x0000600 /* device supports hw statistics version 1 and 2 */ +#define DEV_HAS_STATISTICS_V123 0x0000e00 /* device supports hw statistics version 1, 2, and 3 */ #define DEV_HAS_TEST_EXTENDED 0x0001000 /* device supports extended diagnostic test */ #define DEV_HAS_MGMT_UNIT 0x0002000 /* device supports management unit */ #define DEV_HAS_CORRECT_MACADDR 0x0004000 /* device supports correct mac address order */ @@ -6067,111 +6069,111 @@ static DEFINE_PCI_DEVICE_TABLE(pci_tbl) = { }, { /* MCP55 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x0372), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_NEED_TX_LIMIT|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V12|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_NEED_TX_LIMIT|DEV_NEED_MSI_FIX, }, { /* MCP55 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x0373), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_NEED_TX_LIMIT|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V12|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_NEED_TX_LIMIT|DEV_NEED_MSI_FIX, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x03E5), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V12|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_MSI_FIX, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x03E6), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V12|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_MSI_FIX, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x03EE), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V12|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_MSI_FIX, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x03EF), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V12|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_MSI_FIX, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x0450), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V12|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x0451), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V12|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x0452), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V12|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x0453), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V12|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x054C), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V12|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x054D), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V12|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x054E), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V12|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x054F), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V12|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP73 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x07DC), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V12|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP73 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x07DD), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V12|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP73 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x07DE), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V12|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP73 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x07DF), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V12|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP77 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x0760), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V123|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, }, { /* MCP77 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x0761), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V123|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, }, { /* MCP77 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x0762), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V123|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, }, { /* MCP77 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x0763), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V123|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, }, { /* MCP79 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x0AB0), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V123|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, }, { /* MCP79 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x0AB1), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V123|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, }, { /* MCP79 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x0AB2), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V123|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, }, { /* MCP79 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x0AB3), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V123|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, }, { /* MCP89 Ethernet Controller */ PCI_DEVICE(0x10DE, 0x0D7D), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V123|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX, }, {0,}, }; diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index 06251a9e9f1..cc58227af42 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -70,6 +70,35 @@ static const u16 e1000_82580_rxpbs_table[] = #define E1000_82580_RXPBS_TABLE_SIZE \ (sizeof(e1000_82580_rxpbs_table)/sizeof(u16)) +/** + * igb_sgmii_uses_mdio_82575 - Determine if I2C pins are for external MDIO + * @hw: pointer to the HW structure + * + * Called to determine if the I2C pins are being used for I2C or as an + * external MDIO interface since the two options are mutually exclusive. + **/ +static bool igb_sgmii_uses_mdio_82575(struct e1000_hw *hw) +{ + u32 reg = 0; + bool ext_mdio = false; + + switch (hw->mac.type) { + case e1000_82575: + case e1000_82576: + reg = rd32(E1000_MDIC); + ext_mdio = !!(reg & E1000_MDIC_DEST); + break; + case e1000_82580: + case e1000_i350: + reg = rd32(E1000_MDICNFG); + ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO); + break; + default: + break; + } + return ext_mdio; +} + static s32 igb_get_invariants_82575(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; @@ -144,13 +173,6 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) wr32(E1000_CTRL_EXT, ctrl_ext); - /* - * if using i2c make certain the MDICNFG register is cleared to prevent - * communications from being misrouted to the mdic registers - */ - if ((ctrl_ext & E1000_CTRL_I2C_ENA) && (hw->mac.type == e1000_82580)) - wr32(E1000_MDICNFG, 0); - /* Set mta register count */ mac->mta_reg_count = 128; /* Set rar entry count */ @@ -229,18 +251,20 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) phy->reset_delay_us = 100; /* PHY function pointers */ - if (igb_sgmii_active_82575(hw)) { - phy->ops.reset = igb_phy_hw_reset_sgmii_82575; - phy->ops.read_reg = igb_read_phy_reg_sgmii_82575; - phy->ops.write_reg = igb_write_phy_reg_sgmii_82575; + if (igb_sgmii_active_82575(hw)) + phy->ops.reset = igb_phy_hw_reset_sgmii_82575; + else + phy->ops.reset = igb_phy_hw_reset; + + if (igb_sgmii_active_82575(hw) && !igb_sgmii_uses_mdio_82575(hw)) { + phy->ops.read_reg = igb_read_phy_reg_sgmii_82575; + phy->ops.write_reg = igb_write_phy_reg_sgmii_82575; } else if (hw->mac.type >= e1000_82580) { - phy->ops.reset = igb_phy_hw_reset; - phy->ops.read_reg = igb_read_phy_reg_82580; - phy->ops.write_reg = igb_write_phy_reg_82580; + phy->ops.read_reg = igb_read_phy_reg_82580; + phy->ops.write_reg = igb_write_phy_reg_82580; } else { - phy->ops.reset = igb_phy_hw_reset; - phy->ops.read_reg = igb_read_phy_reg_igp; - phy->ops.write_reg = igb_write_phy_reg_igp; + phy->ops.read_reg = igb_read_phy_reg_igp; + phy->ops.write_reg = igb_write_phy_reg_igp; } /* set lan id */ @@ -400,6 +424,7 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw) s32 ret_val = 0; u16 phy_id; u32 ctrl_ext; + u32 mdic; /* * For SGMII PHYs, we try the list of possible addresses until @@ -414,6 +439,29 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw) goto out; } + if (igb_sgmii_uses_mdio_82575(hw)) { + switch (hw->mac.type) { + case e1000_82575: + case e1000_82576: + mdic = rd32(E1000_MDIC); + mdic &= E1000_MDIC_PHY_MASK; + phy->addr = mdic >> E1000_MDIC_PHY_SHIFT; + break; + case e1000_82580: + case e1000_i350: + mdic = rd32(E1000_MDICNFG); + mdic &= E1000_MDICNFG_PHY_MASK; + phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT; + break; + default: + ret_val = -E1000_ERR_PHY; + goto out; + break; + } + ret_val = igb_get_phy_id(hw); + goto out; + } + /* Power on sgmii phy if it is disabled */ ctrl_ext = rd32(E1000_CTRL_EXT); wr32(E1000_CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_SDP3_DATA); @@ -1501,6 +1549,43 @@ out: } /** + * igb_reset_mdicnfg_82580 - Reset MDICNFG destination and com_mdio bits + * @hw: pointer to the HW structure + * + * This resets the the MDICNFG.Destination and MDICNFG.Com_MDIO bits based on + * the values found in the EEPROM. This addresses an issue in which these + * bits are not restored from EEPROM after reset. + **/ +static s32 igb_reset_mdicnfg_82580(struct e1000_hw *hw) +{ + s32 ret_val = 0; + u32 mdicnfg; + u16 nvm_data; + + if (hw->mac.type != e1000_82580) + goto out; + if (!igb_sgmii_active_82575(hw)) + goto out; + + ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A + + NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1, + &nvm_data); + if (ret_val) { + hw_dbg("NVM Read Error\n"); + goto out; + } + + mdicnfg = rd32(E1000_MDICNFG); + if (nvm_data & NVM_WORD24_EXT_MDIO) + mdicnfg |= E1000_MDICNFG_EXT_MDIO; + if (nvm_data & NVM_WORD24_COM_MDIO) + mdicnfg |= E1000_MDICNFG_COM_MDIO; + wr32(E1000_MDICNFG, mdicnfg); +out: + return ret_val; +} + +/** * igb_reset_hw_82580 - Reset hardware * @hw: pointer to the HW structure * @@ -1575,6 +1660,10 @@ static s32 igb_reset_hw_82580(struct e1000_hw *hw) wr32(E1000_IMC, 0xffffffff); icr = rd32(E1000_ICR); + ret_val = igb_reset_mdicnfg_82580(hw); + if (ret_val) + hw_dbg("Could not reset MDICNFG based on EEPROM\n"); + /* Install any alternate MAC address into RAR0 */ ret_val = igb_check_alt_mac_addr(hw); diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index 90bc29d7e18..bbd2ec308eb 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -468,6 +468,11 @@ #define E1000_TIMINCA_16NS_SHIFT 24 +#define E1000_MDICNFG_EXT_MDIO 0x80000000 /* MDI ext/int destination */ +#define E1000_MDICNFG_COM_MDIO 0x40000000 /* MDI shared w/ lan 0 */ +#define E1000_MDICNFG_PHY_MASK 0x03E00000 +#define E1000_MDICNFG_PHY_SHIFT 21 + /* PCI Express Control */ #define E1000_GCR_CMPL_TMOUT_MASK 0x0000F000 #define E1000_GCR_CMPL_TMOUT_10ms 0x00001000 @@ -565,6 +570,10 @@ #define NVM_82580_LAN_FUNC_OFFSET(a) (a ? (0x40 + (0x40 * a)) : 0) +/* Mask bits for fields in Word 0x24 of the NVM */ +#define NVM_WORD24_COM_MDIO 0x0008 /* MDIO interface shared */ +#define NVM_WORD24_EXT_MDIO 0x0004 /* MDIO accesses routed external */ + /* Mask bits for fields in Word 0x0f of the NVM */ #define NVM_WORD0F_PAUSE_MASK 0x3000 #define NVM_WORD0F_ASM_DIR 0x2000 @@ -698,12 +707,17 @@ #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X 0x0800 /* MDI Control */ +#define E1000_MDIC_DATA_MASK 0x0000FFFF +#define E1000_MDIC_REG_MASK 0x001F0000 #define E1000_MDIC_REG_SHIFT 16 +#define E1000_MDIC_PHY_MASK 0x03E00000 #define E1000_MDIC_PHY_SHIFT 21 #define E1000_MDIC_OP_WRITE 0x04000000 #define E1000_MDIC_OP_READ 0x08000000 #define E1000_MDIC_READY 0x10000000 +#define E1000_MDIC_INT_EN 0x20000000 #define E1000_MDIC_ERROR 0x40000000 +#define E1000_MDIC_DEST 0x80000000 /* SerDes Control */ #define E1000_GEN_CTL_READY 0x80000000 diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 94656179441..667b527b031 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1722,6 +1722,15 @@ static int __devinit igb_probe(struct pci_dev *pdev, u16 eeprom_apme_mask = IGB_EEPROM_APME; u32 part_num; + /* Catch broken hardware that put the wrong VF device ID in + * the PCIe SR-IOV capability. + */ + if (pdev->is_virtfn) { + WARN(1, KERN_ERR "%s (%hx:%hx) should not be a VF!\n", + pci_name(pdev), pdev->vendor, pdev->device); + return -EINVAL; + } + err = pci_enable_device_mem(pdev); if (err) return err; diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index 5e2b2a8c56c..048595bc79a 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c @@ -2751,7 +2751,7 @@ static int __devinit igbvf_probe(struct pci_dev *pdev, dev_info(&pdev->dev, "PF still in reset state, assigning new address." " Is the PF interface up?\n"); - random_ether_addr(hw->mac.addr); + dev_hw_addr_random(adapter->netdev, hw->mac.addr); } else { err = hw->mac.ops.read_mac_addr(hw); if (err) { diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index da54b38bb48..dcebc82c6f4 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -54,14 +54,14 @@ struct ixgbe_stats { sizeof(((struct ixgbe_adapter *)0)->m), \ offsetof(struct ixgbe_adapter, m) #define IXGBE_NETDEV_STAT(m) NETDEV_STATS, \ - sizeof(((struct net_device *)0)->m), \ - offsetof(struct net_device, m) - offsetof(struct net_device, stats) + sizeof(((struct rtnl_link_stats64 *)0)->m), \ + offsetof(struct rtnl_link_stats64, m) static struct ixgbe_stats ixgbe_gstrings_stats[] = { - {"rx_packets", IXGBE_NETDEV_STAT(stats.rx_packets)}, - {"tx_packets", IXGBE_NETDEV_STAT(stats.tx_packets)}, - {"rx_bytes", IXGBE_NETDEV_STAT(stats.rx_bytes)}, - {"tx_bytes", IXGBE_NETDEV_STAT(stats.tx_bytes)}, + {"rx_packets", IXGBE_NETDEV_STAT(rx_packets)}, + {"tx_packets", IXGBE_NETDEV_STAT(tx_packets)}, + {"rx_bytes", IXGBE_NETDEV_STAT(rx_bytes)}, + {"tx_bytes", IXGBE_NETDEV_STAT(tx_bytes)}, {"rx_pkts_nic", IXGBE_STAT(stats.gprc)}, {"tx_pkts_nic", IXGBE_STAT(stats.gptc)}, {"rx_bytes_nic", IXGBE_STAT(stats.gorc)}, @@ -69,27 +69,27 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = { {"lsc_int", IXGBE_STAT(lsc_int)}, {"tx_busy", IXGBE_STAT(tx_busy)}, {"non_eop_descs", IXGBE_STAT(non_eop_descs)}, - {"rx_errors", IXGBE_NETDEV_STAT(stats.rx_errors)}, - {"tx_errors", IXGBE_NETDEV_STAT(stats.tx_errors)}, - {"rx_dropped", IXGBE_NETDEV_STAT(stats.rx_dropped)}, - {"tx_dropped", IXGBE_NETDEV_STAT(stats.tx_dropped)}, - {"multicast", IXGBE_NETDEV_STAT(stats.multicast)}, + {"rx_errors", IXGBE_NETDEV_STAT(rx_errors)}, + {"tx_errors", IXGBE_NETDEV_STAT(tx_errors)}, + {"rx_dropped", IXGBE_NETDEV_STAT(rx_dropped)}, + {"tx_dropped", IXGBE_NETDEV_STAT(tx_dropped)}, + {"multicast", IXGBE_NETDEV_STAT(multicast)}, {"broadcast", IXGBE_STAT(stats.bprc)}, {"rx_no_buffer_count", IXGBE_STAT(stats.rnbc[0]) }, - {"collisions", IXGBE_NETDEV_STAT(stats.collisions)}, - {"rx_over_errors", IXGBE_NETDEV_STAT(stats.rx_over_errors)}, - {"rx_crc_errors", IXGBE_NETDEV_STAT(stats.rx_crc_errors)}, - {"rx_frame_errors", IXGBE_NETDEV_STAT(stats.rx_frame_errors)}, + {"collisions", IXGBE_NETDEV_STAT(collisions)}, + {"rx_over_errors", IXGBE_NETDEV_STAT(rx_over_errors)}, + {"rx_crc_errors", IXGBE_NETDEV_STAT(rx_crc_errors)}, + {"rx_frame_errors", IXGBE_NETDEV_STAT(rx_frame_errors)}, {"hw_rsc_aggregated", IXGBE_STAT(rsc_total_count)}, {"hw_rsc_flushed", IXGBE_STAT(rsc_total_flush)}, {"fdir_match", IXGBE_STAT(stats.fdirmatch)}, {"fdir_miss", IXGBE_STAT(stats.fdirmiss)}, - {"rx_fifo_errors", IXGBE_NETDEV_STAT(stats.rx_fifo_errors)}, - {"rx_missed_errors", IXGBE_NETDEV_STAT(stats.rx_missed_errors)}, - {"tx_aborted_errors", IXGBE_NETDEV_STAT(stats.tx_aborted_errors)}, - {"tx_carrier_errors", IXGBE_NETDEV_STAT(stats.tx_carrier_errors)}, - {"tx_fifo_errors", IXGBE_NETDEV_STAT(stats.tx_fifo_errors)}, - {"tx_heartbeat_errors", IXGBE_NETDEV_STAT(stats.tx_heartbeat_errors)}, + {"rx_fifo_errors", IXGBE_NETDEV_STAT(rx_fifo_errors)}, + {"rx_missed_errors", IXGBE_NETDEV_STAT(rx_missed_errors)}, + {"tx_aborted_errors", IXGBE_NETDEV_STAT(tx_aborted_errors)}, + {"tx_carrier_errors", IXGBE_NETDEV_STAT(tx_carrier_errors)}, + {"tx_fifo_errors", IXGBE_NETDEV_STAT(tx_fifo_errors)}, + {"tx_heartbeat_errors", IXGBE_NETDEV_STAT(tx_heartbeat_errors)}, {"tx_timeout_count", IXGBE_STAT(tx_timeout_count)}, {"tx_restart_queue", IXGBE_STAT(restart_queue)}, {"rx_long_length_errors", IXGBE_STAT(stats.roc)}, diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 92037595145..7d6a415bcf8 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -4783,6 +4783,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) #ifdef CONFIG_IXGBE_DCB /* Default traffic class to use for FCoE */ adapter->fcoe.tc = IXGBE_FCOE_DEFTC; + adapter->fcoe.up = IXGBE_FCOE_DEFTC; #endif #endif /* IXGBE_FCOE */ } @@ -6147,21 +6148,26 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb) struct ixgbe_adapter *adapter = netdev_priv(dev); int txq = smp_processor_id(); +#ifdef IXGBE_FCOE + if ((skb->protocol == htons(ETH_P_FCOE)) || + (skb->protocol == htons(ETH_P_FIP))) { + if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { + txq &= (adapter->ring_feature[RING_F_FCOE].indices - 1); + txq += adapter->ring_feature[RING_F_FCOE].mask; + return txq; + } else if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { + txq = adapter->fcoe.up; + return txq; + } + } +#endif + if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) { while (unlikely(txq >= dev->real_num_tx_queues)) txq -= dev->real_num_tx_queues; return txq; } -#ifdef IXGBE_FCOE - if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED) && - ((skb->protocol == htons(ETH_P_FCOE)) || - (skb->protocol == htons(ETH_P_FIP)))) { - txq &= (adapter->ring_feature[RING_F_FCOE].indices - 1); - txq += adapter->ring_feature[RING_F_FCOE].mask; - return txq; - } -#endif if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { if (skb->priority == TC_PRIO_CONTROL) txq = adapter->ring_feature[RING_F_DCB].indices-1; @@ -6205,18 +6211,15 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb, tx_ring = adapter->tx_ring[skb->queue_mapping]; #ifdef IXGBE_FCOE - if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { -#ifdef CONFIG_IXGBE_DCB - /* for FCoE with DCB, we force the priority to what - * was specified by the switch */ - if ((skb->protocol == htons(ETH_P_FCOE)) || - (skb->protocol == htons(ETH_P_FIP))) { - tx_flags &= ~(IXGBE_TX_FLAGS_VLAN_PRIO_MASK - << IXGBE_TX_FLAGS_VLAN_SHIFT); - tx_flags |= ((adapter->fcoe.up << 13) - << IXGBE_TX_FLAGS_VLAN_SHIFT); - } -#endif + /* for FCoE with DCB, we force the priority to what + * was specified by the switch */ + if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED && + (skb->protocol == htons(ETH_P_FCOE) || + skb->protocol == htons(ETH_P_FIP))) { + tx_flags &= ~(IXGBE_TX_FLAGS_VLAN_PRIO_MASK + << IXGBE_TX_FLAGS_VLAN_SHIFT); + tx_flags |= ((adapter->fcoe.up << 13) + << IXGBE_TX_FLAGS_VLAN_SHIFT); /* flag for FCoE offloads */ if (skb->protocol == htons(ETH_P_FCOE)) tx_flags |= IXGBE_TX_FLAGS_FCOE; @@ -6536,6 +6539,15 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, #endif u32 part_num, eec; + /* Catch broken hardware that put the wrong VF device ID in + * the PCIe SR-IOV capability. + */ + if (pdev->is_virtfn) { + WARN(1, KERN_ERR "%s (%hx:%hx) should not be a VF!\n", + pci_name(pdev), pdev->vendor, pdev->device); + return -EINVAL; + } + err = pci_enable_device_mem(pdev); if (err) return err; @@ -6549,8 +6561,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (err) { - e_dev_err("No usable DMA configuration, " - "aborting\n"); + dev_err(&pdev->dev, + "No usable DMA configuration, aborting\n"); goto err_dma; } } @@ -6560,7 +6572,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, err = pci_request_selected_regions(pdev, pci_select_bars(pdev, IORESOURCE_MEM), ixgbe_driver_name); if (err) { - e_dev_err("pci_request_selected_regions failed 0x%x\n", err); + dev_err(&pdev->dev, + "pci_request_selected_regions failed 0x%x\n", err); goto err_pci_reg; } diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c index af491352b5e..4867440ecfa 100644 --- a/drivers/net/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ixgbevf/ixgbevf_main.c @@ -2229,7 +2229,7 @@ static int __devinit ixgbevf_sw_init(struct ixgbevf_adapter *adapter) if (err) { dev_info(&pdev->dev, "PF still in reset state, assigning new address\n"); - random_ether_addr(hw->mac.addr); + dev_hw_addr_random(adapter->netdev, hw->mac.addr); } else { err = hw->mac.ops.init_hw(hw); if (err) { diff --git a/drivers/net/ks8842.c b/drivers/net/ks8842.c index 634dad1c8b4..928b2b83cef 100644 --- a/drivers/net/ks8842.c +++ b/drivers/net/ks8842.c @@ -30,11 +30,19 @@ #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/ks8842.h> +#include <linux/dmaengine.h> +#include <linux/dma-mapping.h> +#include <linux/scatterlist.h> #define DRV_NAME "ks8842" /* Timberdale specific Registers */ -#define REG_TIMB_RST 0x1c +#define REG_TIMB_RST 0x1c +#define REG_TIMB_FIFO 0x20 +#define REG_TIMB_ISR 0x24 +#define REG_TIMB_IER 0x28 +#define REG_TIMB_IAR 0x2C +#define REQ_TIMB_DMA_RESUME 0x30 /* KS8842 registers */ @@ -77,6 +85,15 @@ #define IRQ_RX_ERROR 0x0080 #define ENABLED_IRQS (IRQ_LINK_CHANGE | IRQ_TX | IRQ_RX | IRQ_RX_STOPPED | \ IRQ_TX_STOPPED | IRQ_RX_OVERRUN | IRQ_RX_ERROR) +/* When running via timberdale in DMA mode, the RX interrupt should be + enabled in the KS8842, but not in the FPGA IP, since the IP handles + RX DMA internally. + TX interrupts are not needed it is handled by the FPGA the driver is + notified via DMA callbacks. +*/ +#define ENABLED_IRQS_DMA_IP (IRQ_LINK_CHANGE | IRQ_RX_STOPPED | \ + IRQ_TX_STOPPED | IRQ_RX_OVERRUN | IRQ_RX_ERROR) +#define ENABLED_IRQS_DMA (ENABLED_IRQS_DMA_IP | IRQ_RX) #define REG_ISR 0x02 #define REG_RXSR 0x04 #define RXSR_VALID 0x8000 @@ -119,6 +136,28 @@ #define MICREL_KS884X 0x01 /* 0=Timeberdale(FPGA), 1=Micrel */ #define KS884X_16BIT 0x02 /* 1=16bit, 0=32bit */ +#define DMA_BUFFER_SIZE 2048 + +struct ks8842_tx_dma_ctl { + struct dma_chan *chan; + struct dma_async_tx_descriptor *adesc; + void *buf; + struct scatterlist sg; + int channel; +}; + +struct ks8842_rx_dma_ctl { + struct dma_chan *chan; + struct dma_async_tx_descriptor *adesc; + struct sk_buff *skb; + struct scatterlist sg; + struct tasklet_struct tasklet; + int channel; +}; + +#define KS8842_USE_DMA(adapter) (((adapter)->dma_tx.channel != -1) && \ + ((adapter)->dma_rx.channel != -1)) + struct ks8842_adapter { void __iomem *hw_addr; int irq; @@ -127,8 +166,19 @@ struct ks8842_adapter { spinlock_t lock; /* spinlock to be interrupt safe */ struct work_struct timeout_work; struct net_device *netdev; + struct device *dev; + struct ks8842_tx_dma_ctl dma_tx; + struct ks8842_rx_dma_ctl dma_rx; }; +static void ks8842_dma_rx_cb(void *data); +static void ks8842_dma_tx_cb(void *data); + +static inline void ks8842_resume_dma(struct ks8842_adapter *adapter) +{ + iowrite32(1, adapter->hw_addr + REQ_TIMB_DMA_RESUME); +} + static inline void ks8842_select_bank(struct ks8842_adapter *adapter, u16 bank) { iowrite16(bank, adapter->hw_addr + REG_SELECT_BANK); @@ -282,10 +332,6 @@ static void ks8842_reset_hw(struct ks8842_adapter *adapter) /* restart port auto-negotiation */ ks8842_enable_bits(adapter, 49, 1 << 13, REG_P1CR4); - if (!(adapter->conf_flags & MICREL_KS884X)) - /* only advertise 10Mbps */ - ks8842_clear_bits(adapter, 49, 3 << 2, REG_P1CR4); - /* Enable the transmitter */ ks8842_enable_tx(adapter); @@ -296,8 +342,19 @@ static void ks8842_reset_hw(struct ks8842_adapter *adapter) ks8842_write16(adapter, 18, 0xffff, REG_ISR); /* enable interrupts */ - ks8842_write16(adapter, 18, ENABLED_IRQS, REG_IER); - + if (KS8842_USE_DMA(adapter)) { + /* When running in DMA Mode the RX interrupt is not enabled in + timberdale because RX data is received by DMA callbacks + it must still be enabled in the KS8842 because it indicates + to timberdale when there is RX data for it's DMA FIFOs */ + iowrite16(ENABLED_IRQS_DMA_IP, adapter->hw_addr + REG_TIMB_IER); + ks8842_write16(adapter, 18, ENABLED_IRQS_DMA, REG_IER); + } else { + if (!(adapter->conf_flags & MICREL_KS884X)) + iowrite16(ENABLED_IRQS, + adapter->hw_addr + REG_TIMB_IER); + ks8842_write16(adapter, 18, ENABLED_IRQS, REG_IER); + } /* enable the switch */ ks8842_write16(adapter, 32, 0x1, REG_SW_ID_AND_ENABLE); } @@ -370,6 +427,53 @@ static inline u16 ks8842_tx_fifo_space(struct ks8842_adapter *adapter) return ks8842_read16(adapter, 16, REG_TXMIR) & 0x1fff; } +static int ks8842_tx_frame_dma(struct sk_buff *skb, struct net_device *netdev) +{ + struct ks8842_adapter *adapter = netdev_priv(netdev); + struct ks8842_tx_dma_ctl *ctl = &adapter->dma_tx; + u8 *buf = ctl->buf; + + if (ctl->adesc) { + netdev_dbg(netdev, "%s: TX ongoing\n", __func__); + /* transfer ongoing */ + return NETDEV_TX_BUSY; + } + + sg_dma_len(&ctl->sg) = skb->len + sizeof(u32); + + /* copy data to the TX buffer */ + /* the control word, enable IRQ, port 1 and the length */ + *buf++ = 0x00; + *buf++ = 0x01; /* Port 1 */ + *buf++ = skb->len & 0xff; + *buf++ = (skb->len >> 8) & 0xff; + skb_copy_from_linear_data(skb, buf, skb->len); + + dma_sync_single_range_for_device(adapter->dev, + sg_dma_address(&ctl->sg), 0, sg_dma_len(&ctl->sg), + DMA_TO_DEVICE); + + /* make sure the length is a multiple of 4 */ + if (sg_dma_len(&ctl->sg) % 4) + sg_dma_len(&ctl->sg) += 4 - sg_dma_len(&ctl->sg) % 4; + + ctl->adesc = ctl->chan->device->device_prep_slave_sg(ctl->chan, + &ctl->sg, 1, DMA_TO_DEVICE, + DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP); + if (!ctl->adesc) + return NETDEV_TX_BUSY; + + ctl->adesc->callback_param = netdev; + ctl->adesc->callback = ks8842_dma_tx_cb; + ctl->adesc->tx_submit(ctl->adesc); + + netdev->stats.tx_bytes += skb->len; + + dev_kfree_skb(skb); + + return NETDEV_TX_OK; +} + static int ks8842_tx_frame(struct sk_buff *skb, struct net_device *netdev) { struct ks8842_adapter *adapter = netdev_priv(netdev); @@ -421,6 +525,121 @@ static int ks8842_tx_frame(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_OK; } +static void ks8842_update_rx_err_counters(struct net_device *netdev, u32 status) +{ + netdev_dbg(netdev, "RX error, status: %x\n", status); + + netdev->stats.rx_errors++; + if (status & RXSR_TOO_LONG) + netdev->stats.rx_length_errors++; + if (status & RXSR_CRC_ERROR) + netdev->stats.rx_crc_errors++; + if (status & RXSR_RUNT) + netdev->stats.rx_frame_errors++; +} + +static void ks8842_update_rx_counters(struct net_device *netdev, u32 status, + int len) +{ + netdev_dbg(netdev, "RX packet, len: %d\n", len); + + netdev->stats.rx_packets++; + netdev->stats.rx_bytes += len; + if (status & RXSR_MULTICAST) + netdev->stats.multicast++; +} + +static int __ks8842_start_new_rx_dma(struct net_device *netdev) +{ + struct ks8842_adapter *adapter = netdev_priv(netdev); + struct ks8842_rx_dma_ctl *ctl = &adapter->dma_rx; + struct scatterlist *sg = &ctl->sg; + int err; + + ctl->skb = netdev_alloc_skb(netdev, DMA_BUFFER_SIZE); + if (ctl->skb) { + sg_init_table(sg, 1); + sg_dma_address(sg) = dma_map_single(adapter->dev, + ctl->skb->data, DMA_BUFFER_SIZE, DMA_FROM_DEVICE); + err = dma_mapping_error(adapter->dev, sg_dma_address(sg)); + if (unlikely(err)) { + sg_dma_address(sg) = 0; + goto out; + } + + sg_dma_len(sg) = DMA_BUFFER_SIZE; + + ctl->adesc = ctl->chan->device->device_prep_slave_sg(ctl->chan, + sg, 1, DMA_FROM_DEVICE, + DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP); + + if (!ctl->adesc) + goto out; + + ctl->adesc->callback_param = netdev; + ctl->adesc->callback = ks8842_dma_rx_cb; + ctl->adesc->tx_submit(ctl->adesc); + } else { + err = -ENOMEM; + sg_dma_address(sg) = 0; + goto out; + } + + return err; +out: + if (sg_dma_address(sg)) + dma_unmap_single(adapter->dev, sg_dma_address(sg), + DMA_BUFFER_SIZE, DMA_FROM_DEVICE); + sg_dma_address(sg) = 0; + if (ctl->skb) + dev_kfree_skb(ctl->skb); + + ctl->skb = NULL; + + printk(KERN_ERR DRV_NAME": Failed to start RX DMA: %d\n", err); + return err; +} + +static void ks8842_rx_frame_dma_tasklet(unsigned long arg) +{ + struct net_device *netdev = (struct net_device *)arg; + struct ks8842_adapter *adapter = netdev_priv(netdev); + struct ks8842_rx_dma_ctl *ctl = &adapter->dma_rx; + struct sk_buff *skb = ctl->skb; + dma_addr_t addr = sg_dma_address(&ctl->sg); + u32 status; + + ctl->adesc = NULL; + + /* kick next transfer going */ + __ks8842_start_new_rx_dma(netdev); + + /* now handle the data we got */ + dma_unmap_single(adapter->dev, addr, DMA_BUFFER_SIZE, DMA_FROM_DEVICE); + + status = *((u32 *)skb->data); + + netdev_dbg(netdev, "%s - rx_data: status: %x\n", + __func__, status & 0xffff); + + /* check the status */ + if ((status & RXSR_VALID) && !(status & RXSR_ERROR)) { + int len = (status >> 16) & 0x7ff; + + ks8842_update_rx_counters(netdev, status, len); + + /* reserve 4 bytes which is the status word */ + skb_reserve(skb, 4); + skb_put(skb, len); + + skb->protocol = eth_type_trans(skb, netdev); + netif_rx(skb); + } else { + ks8842_update_rx_err_counters(netdev, status); + dev_kfree_skb(skb); + } +} + static void ks8842_rx_frame(struct net_device *netdev, struct ks8842_adapter *adapter) { @@ -444,13 +663,9 @@ static void ks8842_rx_frame(struct net_device *netdev, if ((status & RXSR_VALID) && !(status & RXSR_ERROR)) { struct sk_buff *skb = netdev_alloc_skb_ip_align(netdev, len); - netdev_dbg(netdev, "%s, got package, len: %d\n", __func__, len); if (skb) { - netdev->stats.rx_packets++; - netdev->stats.rx_bytes += len; - if (status & RXSR_MULTICAST) - netdev->stats.multicast++; + ks8842_update_rx_counters(netdev, status, len); if (adapter->conf_flags & KS884X_16BIT) { u16 *data16 = (u16 *)skb_put(skb, len); @@ -476,16 +691,8 @@ static void ks8842_rx_frame(struct net_device *netdev, netif_rx(skb); } else netdev->stats.rx_dropped++; - } else { - netdev_dbg(netdev, "RX error, status: %x\n", status); - netdev->stats.rx_errors++; - if (status & RXSR_TOO_LONG) - netdev->stats.rx_length_errors++; - if (status & RXSR_CRC_ERROR) - netdev->stats.rx_crc_errors++; - if (status & RXSR_RUNT) - netdev->stats.rx_frame_errors++; - } + } else + ks8842_update_rx_err_counters(netdev, status); /* set high watermark to 3K */ ks8842_clear_bits(adapter, 0, 1 << 12, REG_QRFCR); @@ -540,18 +747,30 @@ void ks8842_tasklet(unsigned long arg) isr = ks8842_read16(adapter, 18, REG_ISR); netdev_dbg(netdev, "%s - ISR: 0x%x\n", __func__, isr); + /* when running in DMA mode, do not ack RX interrupts, it is handled + internally by timberdale, otherwise it's DMA FIFO:s would stop + */ + if (KS8842_USE_DMA(adapter)) + isr &= ~IRQ_RX; + /* Ack */ ks8842_write16(adapter, 18, isr, REG_ISR); + if (!(adapter->conf_flags & MICREL_KS884X)) + /* Ack in the timberdale IP as well */ + iowrite32(0x1, adapter->hw_addr + REG_TIMB_IAR); + if (!netif_running(netdev)) return; if (isr & IRQ_LINK_CHANGE) ks8842_update_link_status(netdev, adapter); - if (isr & (IRQ_RX | IRQ_RX_ERROR)) + /* should not get IRQ_RX when running DMA mode */ + if (isr & (IRQ_RX | IRQ_RX_ERROR) && !KS8842_USE_DMA(adapter)) ks8842_handle_rx(netdev, adapter); + /* should only happen when in PIO mode */ if (isr & IRQ_TX) ks8842_handle_tx(netdev, adapter); @@ -570,8 +789,17 @@ void ks8842_tasklet(unsigned long arg) /* re-enable interrupts, put back the bank selection register */ spin_lock_irqsave(&adapter->lock, flags); - ks8842_write16(adapter, 18, ENABLED_IRQS, REG_IER); + if (KS8842_USE_DMA(adapter)) + ks8842_write16(adapter, 18, ENABLED_IRQS_DMA, REG_IER); + else + ks8842_write16(adapter, 18, ENABLED_IRQS, REG_IER); iowrite16(entry_bank, adapter->hw_addr + REG_SELECT_BANK); + + /* Make sure timberdale continues DMA operations, they are stopped while + we are handling the ks8842 because we might change bank */ + if (KS8842_USE_DMA(adapter)) + ks8842_resume_dma(adapter); + spin_unlock_irqrestore(&adapter->lock, flags); } @@ -587,8 +815,12 @@ static irqreturn_t ks8842_irq(int irq, void *devid) netdev_dbg(netdev, "%s - ISR: 0x%x\n", __func__, isr); if (isr) { - /* disable IRQ */ - ks8842_write16(adapter, 18, 0x00, REG_IER); + if (KS8842_USE_DMA(adapter)) + /* disable all but RX IRQ, since the FPGA relies on it*/ + ks8842_write16(adapter, 18, IRQ_RX, REG_IER); + else + /* disable IRQ */ + ks8842_write16(adapter, 18, 0x00, REG_IER); /* schedule tasklet */ tasklet_schedule(&adapter->tasklet); @@ -598,9 +830,151 @@ static irqreturn_t ks8842_irq(int irq, void *devid) iowrite16(entry_bank, adapter->hw_addr + REG_SELECT_BANK); + /* After an interrupt, tell timberdale to continue DMA operations. + DMA is disabled while we are handling the ks8842 because we might + change bank */ + ks8842_resume_dma(adapter); + return ret; } +static void ks8842_dma_rx_cb(void *data) +{ + struct net_device *netdev = data; + struct ks8842_adapter *adapter = netdev_priv(netdev); + + netdev_dbg(netdev, "RX DMA finished\n"); + /* schedule tasklet */ + if (adapter->dma_rx.adesc) + tasklet_schedule(&adapter->dma_rx.tasklet); +} + +static void ks8842_dma_tx_cb(void *data) +{ + struct net_device *netdev = data; + struct ks8842_adapter *adapter = netdev_priv(netdev); + struct ks8842_tx_dma_ctl *ctl = &adapter->dma_tx; + + netdev_dbg(netdev, "TX DMA finished\n"); + + if (!ctl->adesc) + return; + + netdev->stats.tx_packets++; + ctl->adesc = NULL; + + if (netif_queue_stopped(netdev)) + netif_wake_queue(netdev); +} + +static void ks8842_stop_dma(struct ks8842_adapter *adapter) +{ + struct ks8842_tx_dma_ctl *tx_ctl = &adapter->dma_tx; + struct ks8842_rx_dma_ctl *rx_ctl = &adapter->dma_rx; + + tx_ctl->adesc = NULL; + if (tx_ctl->chan) + tx_ctl->chan->device->device_control(tx_ctl->chan, + DMA_TERMINATE_ALL, 0); + + rx_ctl->adesc = NULL; + if (rx_ctl->chan) + rx_ctl->chan->device->device_control(rx_ctl->chan, + DMA_TERMINATE_ALL, 0); + + if (sg_dma_address(&rx_ctl->sg)) + dma_unmap_single(adapter->dev, sg_dma_address(&rx_ctl->sg), + DMA_BUFFER_SIZE, DMA_FROM_DEVICE); + sg_dma_address(&rx_ctl->sg) = 0; + + dev_kfree_skb(rx_ctl->skb); + rx_ctl->skb = NULL; +} + +static void ks8842_dealloc_dma_bufs(struct ks8842_adapter *adapter) +{ + struct ks8842_tx_dma_ctl *tx_ctl = &adapter->dma_tx; + struct ks8842_rx_dma_ctl *rx_ctl = &adapter->dma_rx; + + ks8842_stop_dma(adapter); + + if (tx_ctl->chan) + dma_release_channel(tx_ctl->chan); + tx_ctl->chan = NULL; + + if (rx_ctl->chan) + dma_release_channel(rx_ctl->chan); + rx_ctl->chan = NULL; + + tasklet_kill(&rx_ctl->tasklet); + + if (sg_dma_address(&tx_ctl->sg)) + dma_unmap_single(adapter->dev, sg_dma_address(&tx_ctl->sg), + DMA_BUFFER_SIZE, DMA_TO_DEVICE); + sg_dma_address(&tx_ctl->sg) = 0; + + kfree(tx_ctl->buf); + tx_ctl->buf = NULL; +} + +static bool ks8842_dma_filter_fn(struct dma_chan *chan, void *filter_param) +{ + return chan->chan_id == (long)filter_param; +} + +static int ks8842_alloc_dma_bufs(struct net_device *netdev) +{ + struct ks8842_adapter *adapter = netdev_priv(netdev); + struct ks8842_tx_dma_ctl *tx_ctl = &adapter->dma_tx; + struct ks8842_rx_dma_ctl *rx_ctl = &adapter->dma_rx; + int err; + + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_PRIVATE, mask); + + sg_init_table(&tx_ctl->sg, 1); + + tx_ctl->chan = dma_request_channel(mask, ks8842_dma_filter_fn, + (void *)(long)tx_ctl->channel); + if (!tx_ctl->chan) { + err = -ENODEV; + goto err; + } + + /* allocate DMA buffer */ + tx_ctl->buf = kmalloc(DMA_BUFFER_SIZE, GFP_KERNEL); + if (!tx_ctl->buf) { + err = -ENOMEM; + goto err; + } + + sg_dma_address(&tx_ctl->sg) = dma_map_single(adapter->dev, + tx_ctl->buf, DMA_BUFFER_SIZE, DMA_TO_DEVICE); + err = dma_mapping_error(adapter->dev, + sg_dma_address(&tx_ctl->sg)); + if (err) { + sg_dma_address(&tx_ctl->sg) = 0; + goto err; + } + + rx_ctl->chan = dma_request_channel(mask, ks8842_dma_filter_fn, + (void *)(long)rx_ctl->channel); + if (!rx_ctl->chan) { + err = -ENODEV; + goto err; + } + + tasklet_init(&rx_ctl->tasklet, ks8842_rx_frame_dma_tasklet, + (unsigned long)netdev); + + return 0; +err: + ks8842_dealloc_dma_bufs(adapter); + return err; +} /* Netdevice operations */ @@ -611,6 +985,25 @@ static int ks8842_open(struct net_device *netdev) netdev_dbg(netdev, "%s - entry\n", __func__); + if (KS8842_USE_DMA(adapter)) { + err = ks8842_alloc_dma_bufs(netdev); + + if (!err) { + /* start RX dma */ + err = __ks8842_start_new_rx_dma(netdev); + if (err) + ks8842_dealloc_dma_bufs(adapter); + } + + if (err) { + printk(KERN_WARNING DRV_NAME + ": Failed to initiate DMA, running PIO\n"); + ks8842_dealloc_dma_bufs(adapter); + adapter->dma_rx.channel = -1; + adapter->dma_tx.channel = -1; + } + } + /* reset the HW */ ks8842_reset_hw(adapter); @@ -636,6 +1029,9 @@ static int ks8842_close(struct net_device *netdev) cancel_work_sync(&adapter->timeout_work); + if (KS8842_USE_DMA(adapter)) + ks8842_dealloc_dma_bufs(adapter); + /* free the irq */ free_irq(adapter->irq, netdev); @@ -653,6 +1049,17 @@ static netdev_tx_t ks8842_xmit_frame(struct sk_buff *skb, netdev_dbg(netdev, "%s: entry\n", __func__); + if (KS8842_USE_DMA(adapter)) { + unsigned long flags; + ret = ks8842_tx_frame_dma(skb, netdev); + /* for now only allow one transfer at the time */ + spin_lock_irqsave(&adapter->lock, flags); + if (adapter->dma_tx.adesc) + netif_stop_queue(netdev); + spin_unlock_irqrestore(&adapter->lock, flags); + return ret; + } + ret = ks8842_tx_frame(skb, netdev); if (ks8842_tx_fifo_space(adapter) < netdev->mtu + 8) @@ -688,6 +1095,10 @@ static void ks8842_tx_timeout_work(struct work_struct *work) netdev_dbg(netdev, "%s: entry\n", __func__); spin_lock_irqsave(&adapter->lock, flags); + + if (KS8842_USE_DMA(adapter)) + ks8842_stop_dma(adapter); + /* disable interrupts */ ks8842_write16(adapter, 18, 0, REG_IER); ks8842_write16(adapter, 18, 0xFFFF, REG_ISR); @@ -701,6 +1112,9 @@ static void ks8842_tx_timeout_work(struct work_struct *work) ks8842_write_mac_addr(adapter, netdev->dev_addr); ks8842_update_link_status(netdev, adapter); + + if (KS8842_USE_DMA(adapter)) + __ks8842_start_new_rx_dma(netdev); } static void ks8842_tx_timeout(struct net_device *netdev) @@ -760,6 +1174,19 @@ static int __devinit ks8842_probe(struct platform_device *pdev) goto err_get_irq; } + adapter->dev = (pdev->dev.parent) ? pdev->dev.parent : &pdev->dev; + + /* DMA is only supported when accessed via timberdale */ + if (!(adapter->conf_flags & MICREL_KS884X) && pdata && + (pdata->tx_dma_channel != -1) && + (pdata->rx_dma_channel != -1)) { + adapter->dma_rx.channel = pdata->rx_dma_channel; + adapter->dma_tx.channel = pdata->tx_dma_channel; + } else { + adapter->dma_rx.channel = -1; + adapter->dma_tx.channel = -1; + } + tasklet_init(&adapter->tasklet, ks8842_tasklet, (unsigned long)netdev); spin_lock_init(&adapter->lock); diff --git a/drivers/net/ksz884x.c b/drivers/net/ksz884x.c index b3c010b8565..8b32cc107f0 100644 --- a/drivers/net/ksz884x.c +++ b/drivers/net/ksz884x.c @@ -6894,13 +6894,12 @@ static void get_mac_addr(struct dev_info *hw_priv, u8 *macaddr, int port) i = j = num = got_num = 0; while (j < MAC_ADDR_LEN) { if (macaddr[i]) { + int digit; + got_num = 1; - if ('0' <= macaddr[i] && macaddr[i] <= '9') - num = num * 16 + macaddr[i] - '0'; - else if ('A' <= macaddr[i] && macaddr[i] <= 'F') - num = num * 16 + 10 + macaddr[i] - 'A'; - else if ('a' <= macaddr[i] && macaddr[i] <= 'f') - num = num * 16 + 10 + macaddr[i] - 'a'; + digit = hex_to_bin(macaddr[i]); + if (digit >= 0) + num = num * 16 + digit; else if (':' == macaddr[i]) got_num = 2; else diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 1b28aaec0a5..0ef0eb0db94 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -158,7 +158,8 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb) const struct macvlan_dev *vlan; const struct macvlan_dev *src; struct net_device *dev; - unsigned int len; + unsigned int len = 0; + int ret = NET_RX_DROP; port = macvlan_port_get_rcu(skb->dev); if (is_multicast_ether_addr(eth->h_dest)) { @@ -195,14 +196,16 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb) } len = skb->len + ETH_HLEN; skb = skb_share_check(skb, GFP_ATOMIC); - macvlan_count_rx(vlan, len, skb != NULL, 0); if (!skb) - return NULL; + goto out; skb->dev = dev; skb->pkt_type = PACKET_HOST; - vlan->receive(skb); + ret = vlan->receive(skb); + +out: + macvlan_count_rx(vlan, len, ret == NET_RX_SUCCESS, 0); return NULL; } @@ -515,7 +518,7 @@ static const struct net_device_ops macvlan_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; -static void macvlan_setup(struct net_device *dev) +void macvlan_common_setup(struct net_device *dev) { ether_setup(dev); @@ -524,6 +527,12 @@ static void macvlan_setup(struct net_device *dev) dev->destructor = free_netdev; dev->header_ops = &macvlan_hard_header_ops, dev->ethtool_ops = &macvlan_ethtool_ops; +} +EXPORT_SYMBOL_GPL(macvlan_common_setup); + +static void macvlan_setup(struct net_device *dev) +{ + macvlan_common_setup(dev); dev->tx_queue_len = 0; } @@ -735,7 +744,6 @@ int macvlan_link_register(struct rtnl_link_ops *ops) /* common fields */ ops->priv_size = sizeof(struct macvlan_dev); ops->get_tx_queues = macvlan_get_tx_queues; - ops->setup = macvlan_setup; ops->validate = macvlan_validate; ops->maxtype = IFLA_MACVLAN_MAX; ops->policy = macvlan_policy; @@ -749,6 +757,7 @@ EXPORT_SYMBOL_GPL(macvlan_link_register); static struct rtnl_link_ops macvlan_link_ops = { .kind = "macvlan", + .setup = macvlan_setup, .newlink = macvlan_newlink, .dellink = macvlan_dellink, }; diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 2b4d59b58b2..3b1c54a9c6e 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -180,11 +180,18 @@ static int macvtap_forward(struct net_device *dev, struct sk_buff *skb) { struct macvtap_queue *q = macvtap_get_queue(dev, skb); if (!q) - return -ENOLINK; + goto drop; + + if (skb_queue_len(&q->sk.sk_receive_queue) >= dev->tx_queue_len) + goto drop; skb_queue_tail(&q->sk.sk_receive_queue, skb); wake_up_interruptible_poll(sk_sleep(&q->sk), POLLIN | POLLRDNORM | POLLRDBAND); - return 0; + return NET_RX_SUCCESS; + +drop: + kfree_skb(skb); + return NET_RX_DROP; } /* @@ -235,8 +242,15 @@ static void macvtap_dellink(struct net_device *dev, macvlan_dellink(dev, head); } +static void macvtap_setup(struct net_device *dev) +{ + macvlan_common_setup(dev); + dev->tx_queue_len = TUN_READQ_SIZE; +} + static struct rtnl_link_ops macvtap_link_ops __read_mostly = { .kind = "macvtap", + .setup = macvtap_setup, .newlink = macvtap_newlink, .dellink = macvtap_dellink, }; diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 2fcdb1e1b99..2d488abcf62 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -2675,7 +2675,8 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev) * Detect hardware parameters. */ msp->t_clk = (pd != NULL && pd->t_clk != 0) ? pd->t_clk : 133000000; - msp->tx_csum_limit = pd->tx_csum_limit ? pd->tx_csum_limit : 9 * 1024; + msp->tx_csum_limit = (pd != NULL && pd->tx_csum_limit) ? + pd->tx_csum_limit : 9 * 1024; infer_hw_params(msp); platform_set_drvdata(pdev, msp); diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index 54ebb65ada1..6168a130f33 100644 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -5,6 +5,8 @@ * See LICENSE.qla3xxx for copyright and licensing details. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/kernel.h> #include <linux/init.h> #include <linux/types.h> @@ -36,14 +38,16 @@ #include "qla3xxx.h" -#define DRV_NAME "qla3xxx" -#define DRV_STRING "QLogic ISP3XXX Network Driver" +#define DRV_NAME "qla3xxx" +#define DRV_STRING "QLogic ISP3XXX Network Driver" #define DRV_VERSION "v2.03.00-k5" -#define PFX DRV_NAME " " static const char ql3xxx_driver_name[] = DRV_NAME; static const char ql3xxx_driver_version[] = DRV_VERSION; +#define TIMED_OUT_MSG \ +"Timed out waiting for management port to get free before issuing command\n" + MODULE_AUTHOR("QLogic Corporation"); MODULE_DESCRIPTION("QLogic ISP3XXX Network Driver " DRV_VERSION " "); MODULE_LICENSE("GPL"); @@ -73,24 +77,24 @@ MODULE_DEVICE_TABLE(pci, ql3xxx_pci_tbl); /* * These are the known PHY's which are used */ -typedef enum { +enum PHY_DEVICE_TYPE { PHY_TYPE_UNKNOWN = 0, PHY_VITESSE_VSC8211, PHY_AGERE_ET1011C, MAX_PHY_DEV_TYPES -} PHY_DEVICE_et; - -typedef struct { - PHY_DEVICE_et phyDevice; - u32 phyIdOUI; - u16 phyIdModel; - char *name; -} PHY_DEVICE_INFO_t; - -static const PHY_DEVICE_INFO_t PHY_DEVICES[] = - {{PHY_TYPE_UNKNOWN, 0x000000, 0x0, "PHY_TYPE_UNKNOWN"}, - {PHY_VITESSE_VSC8211, 0x0003f1, 0xb, "PHY_VITESSE_VSC8211"}, - {PHY_AGERE_ET1011C, 0x00a0bc, 0x1, "PHY_AGERE_ET1011C"}, +}; + +struct PHY_DEVICE_INFO { + const enum PHY_DEVICE_TYPE phyDevice; + const u32 phyIdOUI; + const u16 phyIdModel; + const char *name; +}; + +static const struct PHY_DEVICE_INFO PHY_DEVICES[] = { + {PHY_TYPE_UNKNOWN, 0x000000, 0x0, "PHY_TYPE_UNKNOWN"}, + {PHY_VITESSE_VSC8211, 0x0003f1, 0xb, "PHY_VITESSE_VSC8211"}, + {PHY_AGERE_ET1011C, 0x00a0bc, 0x1, "PHY_AGERE_ET1011C"}, }; @@ -100,7 +104,8 @@ static const PHY_DEVICE_INFO_t PHY_DEVICES[] = static int ql_sem_spinlock(struct ql3_adapter *qdev, u32 sem_mask, u32 sem_bits) { - struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; + struct ql3xxx_port_registers __iomem *port_regs = + qdev->mem_map_registers; u32 value; unsigned int seconds = 3; @@ -111,20 +116,22 @@ static int ql_sem_spinlock(struct ql3_adapter *qdev, if ((value & (sem_mask >> 16)) == sem_bits) return 0; ssleep(1); - } while(--seconds); + } while (--seconds); return -1; } static void ql_sem_unlock(struct ql3_adapter *qdev, u32 sem_mask) { - struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; + struct ql3xxx_port_registers __iomem *port_regs = + qdev->mem_map_registers; writel(sem_mask, &port_regs->CommonRegs.semaphoreReg); readl(&port_regs->CommonRegs.semaphoreReg); } static int ql_sem_lock(struct ql3_adapter *qdev, u32 sem_mask, u32 sem_bits) { - struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; + struct ql3xxx_port_registers __iomem *port_regs = + qdev->mem_map_registers; u32 value; writel((sem_mask | sem_bits), &port_regs->CommonRegs.semaphoreReg); @@ -139,32 +146,28 @@ static int ql_wait_for_drvr_lock(struct ql3_adapter *qdev) { int i = 0; - while (1) { - if (!ql_sem_lock(qdev, - QL_DRVR_SEM_MASK, - (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) - * 2) << 1)) { - if (i < 10) { - ssleep(1); - i++; - } else { - printk(KERN_ERR PFX "%s: Timed out waiting for " - "driver lock...\n", - qdev->ndev->name); - return 0; - } - } else { - printk(KERN_DEBUG PFX - "%s: driver lock acquired.\n", - qdev->ndev->name); + while (i < 10) { + if (i) + ssleep(1); + + if (ql_sem_lock(qdev, + QL_DRVR_SEM_MASK, + (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) + * 2) << 1)) { + netdev_printk(KERN_DEBUG, qdev->ndev, + "driver lock acquired\n"); return 1; } } + + netdev_err(qdev->ndev, "Timed out waiting for driver lock...\n"); + return 0; } static void ql_set_register_page(struct ql3_adapter *qdev, u32 page) { - struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; + struct ql3xxx_port_registers __iomem *port_regs = + qdev->mem_map_registers; writel(((ISP_CONTROL_NP_MASK << 16) | page), &port_regs->CommonRegs.ispControlStatus); @@ -172,8 +175,7 @@ static void ql_set_register_page(struct ql3_adapter *qdev, u32 page) qdev->current_page = page; } -static u32 ql_read_common_reg_l(struct ql3_adapter *qdev, - u32 __iomem * reg) +static u32 ql_read_common_reg_l(struct ql3_adapter *qdev, u32 __iomem *reg) { u32 value; unsigned long hw_flags; @@ -185,8 +187,7 @@ static u32 ql_read_common_reg_l(struct ql3_adapter *qdev, return value; } -static u32 ql_read_common_reg(struct ql3_adapter *qdev, - u32 __iomem * reg) +static u32 ql_read_common_reg(struct ql3_adapter *qdev, u32 __iomem *reg) { return readl(reg); } @@ -199,7 +200,7 @@ static u32 ql_read_page0_reg_l(struct ql3_adapter *qdev, u32 __iomem *reg) spin_lock_irqsave(&qdev->hw_lock, hw_flags); if (qdev->current_page != 0) - ql_set_register_page(qdev,0); + ql_set_register_page(qdev, 0); value = readl(reg); spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); @@ -209,7 +210,7 @@ static u32 ql_read_page0_reg_l(struct ql3_adapter *qdev, u32 __iomem *reg) static u32 ql_read_page0_reg(struct ql3_adapter *qdev, u32 __iomem *reg) { if (qdev->current_page != 0) - ql_set_register_page(qdev,0); + ql_set_register_page(qdev, 0); return readl(reg); } @@ -243,7 +244,7 @@ static void ql_write_page0_reg(struct ql3_adapter *qdev, u32 __iomem *reg, u32 value) { if (qdev->current_page != 0) - ql_set_register_page(qdev,0); + ql_set_register_page(qdev, 0); writel(value, reg); readl(reg); } @@ -255,7 +256,7 @@ static void ql_write_page1_reg(struct ql3_adapter *qdev, u32 __iomem *reg, u32 value) { if (qdev->current_page != 1) - ql_set_register_page(qdev,1); + ql_set_register_page(qdev, 1); writel(value, reg); readl(reg); } @@ -267,14 +268,15 @@ static void ql_write_page2_reg(struct ql3_adapter *qdev, u32 __iomem *reg, u32 value) { if (qdev->current_page != 2) - ql_set_register_page(qdev,2); + ql_set_register_page(qdev, 2); writel(value, reg); readl(reg); } static void ql_disable_interrupts(struct ql3_adapter *qdev) { - struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; + struct ql3xxx_port_registers __iomem *port_regs = + qdev->mem_map_registers; ql_write_common_reg_l(qdev, &port_regs->CommonRegs.ispInterruptMaskReg, (ISP_IMR_ENABLE_INT << 16)); @@ -283,7 +285,8 @@ static void ql_disable_interrupts(struct ql3_adapter *qdev) static void ql_enable_interrupts(struct ql3_adapter *qdev) { - struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; + struct ql3xxx_port_registers __iomem *port_regs = + qdev->mem_map_registers; ql_write_common_reg_l(qdev, &port_regs->CommonRegs.ispInterruptMaskReg, ((0xff << 16) | ISP_IMR_ENABLE_INT)); @@ -308,8 +311,7 @@ static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev, lrg_buf_cb->skb = netdev_alloc_skb(qdev->ndev, qdev->lrg_buffer_len); if (unlikely(!lrg_buf_cb->skb)) { - printk(KERN_ERR PFX "%s: failed netdev_alloc_skb().\n", - qdev->ndev->name); + netdev_err(qdev->ndev, "failed netdev_alloc_skb()\n"); qdev->lrg_buf_skb_check++; } else { /* @@ -323,9 +325,10 @@ static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev, QL_HEADER_SPACE, PCI_DMA_FROMDEVICE); err = pci_dma_mapping_error(qdev->pdev, map); - if(err) { - printk(KERN_ERR "%s: PCI mapping failed with error: %d\n", - qdev->ndev->name, err); + if (err) { + netdev_err(qdev->ndev, + "PCI mapping failed with error: %d\n", + err); dev_kfree_skb(lrg_buf_cb->skb); lrg_buf_cb->skb = NULL; @@ -350,10 +353,11 @@ static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev, static struct ql_rcv_buf_cb *ql_get_from_lrg_buf_free_list(struct ql3_adapter *qdev) { - struct ql_rcv_buf_cb *lrg_buf_cb; + struct ql_rcv_buf_cb *lrg_buf_cb = qdev->lrg_buf_free_head; - if ((lrg_buf_cb = qdev->lrg_buf_free_head) != NULL) { - if ((qdev->lrg_buf_free_head = lrg_buf_cb->next) == NULL) + if (lrg_buf_cb != NULL) { + qdev->lrg_buf_free_head = lrg_buf_cb->next; + if (qdev->lrg_buf_free_head == NULL) qdev->lrg_buf_free_tail = NULL; qdev->lrg_buf_free_count--; } @@ -374,13 +378,13 @@ static void eeprom_readword(struct ql3_adapter *qdev, u32 eepromAddr, static void fm93c56a_select(struct ql3_adapter *qdev) { struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; + u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg; qdev->eeprom_cmd_data = AUBURN_EEPROM_CS_1; - ql_write_nvram_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg, - ISP_NVRAM_MASK | qdev->eeprom_cmd_data); - ql_write_nvram_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg, - ((ISP_NVRAM_MASK << 16) | qdev->eeprom_cmd_data)); + ql_write_nvram_reg(qdev, spir, ISP_NVRAM_MASK | qdev->eeprom_cmd_data); + ql_write_nvram_reg(qdev, spir, + ((ISP_NVRAM_MASK << 16) | qdev->eeprom_cmd_data)); } /* @@ -393,51 +397,40 @@ static void fm93c56a_cmd(struct ql3_adapter *qdev, u32 cmd, u32 eepromAddr) u32 dataBit; u32 previousBit; struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; + u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg; /* Clock in a zero, then do the start bit */ - ql_write_nvram_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg, - ISP_NVRAM_MASK | qdev->eeprom_cmd_data | - AUBURN_EEPROM_DO_1); - ql_write_nvram_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg, - ISP_NVRAM_MASK | qdev-> - eeprom_cmd_data | AUBURN_EEPROM_DO_1 | - AUBURN_EEPROM_CLK_RISE); - ql_write_nvram_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg, - ISP_NVRAM_MASK | qdev-> - eeprom_cmd_data | AUBURN_EEPROM_DO_1 | - AUBURN_EEPROM_CLK_FALL); + ql_write_nvram_reg(qdev, spir, + (ISP_NVRAM_MASK | qdev->eeprom_cmd_data | + AUBURN_EEPROM_DO_1)); + ql_write_nvram_reg(qdev, spir, + (ISP_NVRAM_MASK | qdev->eeprom_cmd_data | + AUBURN_EEPROM_DO_1 | AUBURN_EEPROM_CLK_RISE)); + ql_write_nvram_reg(qdev, spir, + (ISP_NVRAM_MASK | qdev->eeprom_cmd_data | + AUBURN_EEPROM_DO_1 | AUBURN_EEPROM_CLK_FALL)); mask = 1 << (FM93C56A_CMD_BITS - 1); /* Force the previous data bit to be different */ previousBit = 0xffff; for (i = 0; i < FM93C56A_CMD_BITS; i++) { - dataBit = - (cmd & mask) ? AUBURN_EEPROM_DO_1 : AUBURN_EEPROM_DO_0; + dataBit = (cmd & mask) + ? AUBURN_EEPROM_DO_1 + : AUBURN_EEPROM_DO_0; if (previousBit != dataBit) { - /* - * If the bit changed, then change the DO state to - * match - */ - ql_write_nvram_reg(qdev, - &port_regs->CommonRegs. - serialPortInterfaceReg, - ISP_NVRAM_MASK | qdev-> - eeprom_cmd_data | dataBit); + /* If the bit changed, change the DO state to match */ + ql_write_nvram_reg(qdev, spir, + (ISP_NVRAM_MASK | + qdev->eeprom_cmd_data | dataBit)); previousBit = dataBit; } - ql_write_nvram_reg(qdev, - &port_regs->CommonRegs. - serialPortInterfaceReg, - ISP_NVRAM_MASK | qdev-> - eeprom_cmd_data | dataBit | - AUBURN_EEPROM_CLK_RISE); - ql_write_nvram_reg(qdev, - &port_regs->CommonRegs. - serialPortInterfaceReg, - ISP_NVRAM_MASK | qdev-> - eeprom_cmd_data | dataBit | - AUBURN_EEPROM_CLK_FALL); + ql_write_nvram_reg(qdev, spir, + (ISP_NVRAM_MASK | qdev->eeprom_cmd_data | + dataBit | AUBURN_EEPROM_CLK_RISE)); + ql_write_nvram_reg(qdev, spir, + (ISP_NVRAM_MASK | qdev->eeprom_cmd_data | + dataBit | AUBURN_EEPROM_CLK_FALL)); cmd = cmd << 1; } @@ -445,33 +438,24 @@ static void fm93c56a_cmd(struct ql3_adapter *qdev, u32 cmd, u32 eepromAddr) /* Force the previous data bit to be different */ previousBit = 0xffff; for (i = 0; i < addrBits; i++) { - dataBit = - (eepromAddr & mask) ? AUBURN_EEPROM_DO_1 : - AUBURN_EEPROM_DO_0; + dataBit = (eepromAddr & mask) ? AUBURN_EEPROM_DO_1 + : AUBURN_EEPROM_DO_0; if (previousBit != dataBit) { /* * If the bit changed, then change the DO state to * match */ - ql_write_nvram_reg(qdev, - &port_regs->CommonRegs. - serialPortInterfaceReg, - ISP_NVRAM_MASK | qdev-> - eeprom_cmd_data | dataBit); + ql_write_nvram_reg(qdev, spir, + (ISP_NVRAM_MASK | + qdev->eeprom_cmd_data | dataBit)); previousBit = dataBit; } - ql_write_nvram_reg(qdev, - &port_regs->CommonRegs. - serialPortInterfaceReg, - ISP_NVRAM_MASK | qdev-> - eeprom_cmd_data | dataBit | - AUBURN_EEPROM_CLK_RISE); - ql_write_nvram_reg(qdev, - &port_regs->CommonRegs. - serialPortInterfaceReg, - ISP_NVRAM_MASK | qdev-> - eeprom_cmd_data | dataBit | - AUBURN_EEPROM_CLK_FALL); + ql_write_nvram_reg(qdev, spir, + (ISP_NVRAM_MASK | qdev->eeprom_cmd_data | + dataBit | AUBURN_EEPROM_CLK_RISE)); + ql_write_nvram_reg(qdev, spir, + (ISP_NVRAM_MASK | qdev->eeprom_cmd_data | + dataBit | AUBURN_EEPROM_CLK_FALL)); eepromAddr = eepromAddr << 1; } } @@ -482,10 +466,11 @@ static void fm93c56a_cmd(struct ql3_adapter *qdev, u32 cmd, u32 eepromAddr) static void fm93c56a_deselect(struct ql3_adapter *qdev) { struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; + u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg; + qdev->eeprom_cmd_data = AUBURN_EEPROM_CS_0; - ql_write_nvram_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg, - ISP_NVRAM_MASK | qdev->eeprom_cmd_data); + ql_write_nvram_reg(qdev, spir, ISP_NVRAM_MASK | qdev->eeprom_cmd_data); } /* @@ -497,29 +482,23 @@ static void fm93c56a_datain(struct ql3_adapter *qdev, unsigned short *value) u32 data = 0; u32 dataBit; struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; + u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg; /* Read the data bits */ /* The first bit is a dummy. Clock right over it. */ for (i = 0; i < dataBits; i++) { - ql_write_nvram_reg(qdev, - &port_regs->CommonRegs. - serialPortInterfaceReg, - ISP_NVRAM_MASK | qdev->eeprom_cmd_data | - AUBURN_EEPROM_CLK_RISE); - ql_write_nvram_reg(qdev, - &port_regs->CommonRegs. - serialPortInterfaceReg, - ISP_NVRAM_MASK | qdev->eeprom_cmd_data | - AUBURN_EEPROM_CLK_FALL); - dataBit = - (ql_read_common_reg - (qdev, - &port_regs->CommonRegs. - serialPortInterfaceReg) & AUBURN_EEPROM_DI_1) ? 1 : 0; + ql_write_nvram_reg(qdev, spir, + ISP_NVRAM_MASK | qdev->eeprom_cmd_data | + AUBURN_EEPROM_CLK_RISE); + ql_write_nvram_reg(qdev, spir, + ISP_NVRAM_MASK | qdev->eeprom_cmd_data | + AUBURN_EEPROM_CLK_FALL); + dataBit = (ql_read_common_reg(qdev, spir) & + AUBURN_EEPROM_DI_1) ? 1 : 0; data = (data << 1) | dataBit; } - *value = (u16) data; + *value = (u16)data; } /* @@ -551,13 +530,12 @@ static int ql_get_nvram_params(struct ql3_adapter *qdev) spin_lock_irqsave(&qdev->hw_lock, hw_flags); - pEEPROMData = (u16 *) & qdev->nvram_data; + pEEPROMData = (u16 *)&qdev->nvram_data; qdev->eeprom_cmd_data = 0; - if(ql_sem_spinlock(qdev, QL_NVRAM_SEM_MASK, + if (ql_sem_spinlock(qdev, QL_NVRAM_SEM_MASK, (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) * 2) << 10)) { - printk(KERN_ERR PFX"%s: Failed ql_sem_spinlock().\n", - __func__); + pr_err("%s: Failed ql_sem_spinlock()\n", __func__); spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); return -1; } @@ -570,8 +548,8 @@ static int ql_get_nvram_params(struct ql3_adapter *qdev) ql_sem_unlock(qdev, QL_NVRAM_SEM_MASK); if (checksum != 0) { - printk(KERN_ERR PFX "%s: checksum should be zero, is %x!!\n", - qdev->ndev->name, checksum); + netdev_err(qdev->ndev, "checksum should be zero, is %x!!\n", + checksum); spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); return -1; } @@ -587,7 +565,7 @@ static const u32 PHYAddr[2] = { static int ql_wait_for_mii_ready(struct ql3_adapter *qdev) { struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; u32 temp; int count = 1000; @@ -604,7 +582,7 @@ static int ql_wait_for_mii_ready(struct ql3_adapter *qdev) static void ql_mii_enable_scan_mode(struct ql3_adapter *qdev) { struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; u32 scanControl; if (qdev->numPorts > 1) { @@ -632,7 +610,7 @@ static u8 ql_mii_disable_scan_mode(struct ql3_adapter *qdev) { u8 ret; struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; /* See if scan mode is enabled before we turn it off */ if (ql_read_page0_reg(qdev, &port_regs->macMIIMgmtControlReg) & @@ -662,17 +640,13 @@ static int ql_mii_write_reg_ex(struct ql3_adapter *qdev, u16 regAddr, u16 value, u32 phyAddr) { struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; u8 scanWasEnabled; scanWasEnabled = ql_mii_disable_scan_mode(qdev); if (ql_wait_for_mii_ready(qdev)) { - if (netif_msg_link(qdev)) - printk(KERN_WARNING PFX - "%s Timed out waiting for management port to " - "get free before issuing command.\n", - qdev->ndev->name); + netif_warn(qdev, link, qdev->ndev, TIMED_OUT_MSG); return -1; } @@ -683,11 +657,7 @@ static int ql_mii_write_reg_ex(struct ql3_adapter *qdev, /* Wait for write to complete 9/10/04 SJP */ if (ql_wait_for_mii_ready(qdev)) { - if (netif_msg_link(qdev)) - printk(KERN_WARNING PFX - "%s: Timed out waiting for management port to " - "get free before issuing command.\n", - qdev->ndev->name); + netif_warn(qdev, link, qdev->ndev, TIMED_OUT_MSG); return -1; } @@ -698,21 +668,17 @@ static int ql_mii_write_reg_ex(struct ql3_adapter *qdev, } static int ql_mii_read_reg_ex(struct ql3_adapter *qdev, u16 regAddr, - u16 * value, u32 phyAddr) + u16 *value, u32 phyAddr) { struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; u8 scanWasEnabled; u32 temp; scanWasEnabled = ql_mii_disable_scan_mode(qdev); if (ql_wait_for_mii_ready(qdev)) { - if (netif_msg_link(qdev)) - printk(KERN_WARNING PFX - "%s: Timed out waiting for management port to " - "get free before issuing command.\n", - qdev->ndev->name); + netif_warn(qdev, link, qdev->ndev, TIMED_OUT_MSG); return -1; } @@ -727,11 +693,7 @@ static int ql_mii_read_reg_ex(struct ql3_adapter *qdev, u16 regAddr, /* Wait for the read to complete */ if (ql_wait_for_mii_ready(qdev)) { - if (netif_msg_link(qdev)) - printk(KERN_WARNING PFX - "%s: Timed out waiting for management port to " - "get free after issuing command.\n", - qdev->ndev->name); + netif_warn(qdev, link, qdev->ndev, TIMED_OUT_MSG); return -1; } @@ -747,16 +709,12 @@ static int ql_mii_read_reg_ex(struct ql3_adapter *qdev, u16 regAddr, static int ql_mii_write_reg(struct ql3_adapter *qdev, u16 regAddr, u16 value) { struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; ql_mii_disable_scan_mode(qdev); if (ql_wait_for_mii_ready(qdev)) { - if (netif_msg_link(qdev)) - printk(KERN_WARNING PFX - "%s: Timed out waiting for management port to " - "get free before issuing command.\n", - qdev->ndev->name); + netif_warn(qdev, link, qdev->ndev, TIMED_OUT_MSG); return -1; } @@ -767,11 +725,7 @@ static int ql_mii_write_reg(struct ql3_adapter *qdev, u16 regAddr, u16 value) /* Wait for write to complete. */ if (ql_wait_for_mii_ready(qdev)) { - if (netif_msg_link(qdev)) - printk(KERN_WARNING PFX - "%s: Timed out waiting for management port to " - "get free before issuing command.\n", - qdev->ndev->name); + netif_warn(qdev, link, qdev->ndev, TIMED_OUT_MSG); return -1; } @@ -784,16 +738,12 @@ static int ql_mii_read_reg(struct ql3_adapter *qdev, u16 regAddr, u16 *value) { u32 temp; struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; ql_mii_disable_scan_mode(qdev); if (ql_wait_for_mii_ready(qdev)) { - if (netif_msg_link(qdev)) - printk(KERN_WARNING PFX - "%s: Timed out waiting for management port to " - "get free before issuing command.\n", - qdev->ndev->name); + netif_warn(qdev, link, qdev->ndev, TIMED_OUT_MSG); return -1; } @@ -808,11 +758,7 @@ static int ql_mii_read_reg(struct ql3_adapter *qdev, u16 regAddr, u16 *value) /* Wait for the read to complete */ if (ql_wait_for_mii_ready(qdev)) { - if (netif_msg_link(qdev)) - printk(KERN_WARNING PFX - "%s: Timed out waiting for management port to " - "get free before issuing command.\n", - qdev->ndev->name); + netif_warn(qdev, link, qdev->ndev, TIMED_OUT_MSG); return -1; } @@ -898,7 +844,7 @@ static int ql_is_petbi_neg_pause(struct ql3_adapter *qdev) static void phyAgereSpecificInit(struct ql3_adapter *qdev, u32 miiAddr) { - printk(KERN_INFO "%s: enabling Agere specific PHY\n", qdev->ndev->name); + netdev_info(qdev->ndev, "enabling Agere specific PHY\n"); /* power down device bit 11 = 1 */ ql_mii_write_reg_ex(qdev, 0x00, 0x1940, miiAddr); /* enable diagnostic mode bit 2 = 1 */ @@ -918,7 +864,8 @@ static void phyAgereSpecificInit(struct ql3_adapter *qdev, u32 miiAddr) /* point to hidden reg 0x2806 */ ql_mii_write_reg_ex(qdev, 0x10, 0x2806, miiAddr); /* Write new PHYAD w/bit 5 set */ - ql_mii_write_reg_ex(qdev, 0x11, 0x0020 | (PHYAddr[qdev->mac_index] >> 8), miiAddr); + ql_mii_write_reg_ex(qdev, 0x11, + 0x0020 | (PHYAddr[qdev->mac_index] >> 8), miiAddr); /* * Disable diagnostic mode bit 2 = 0 * Power up device bit 11 = 0 @@ -929,21 +876,19 @@ static void phyAgereSpecificInit(struct ql3_adapter *qdev, u32 miiAddr) ql_mii_write_reg(qdev, 0x1c, 0xfaf0); } -static PHY_DEVICE_et getPhyType (struct ql3_adapter *qdev, - u16 phyIdReg0, u16 phyIdReg1) +static enum PHY_DEVICE_TYPE getPhyType(struct ql3_adapter *qdev, + u16 phyIdReg0, u16 phyIdReg1) { - PHY_DEVICE_et result = PHY_TYPE_UNKNOWN; + enum PHY_DEVICE_TYPE result = PHY_TYPE_UNKNOWN; u32 oui; u16 model; int i; - if (phyIdReg0 == 0xffff) { + if (phyIdReg0 == 0xffff) return result; - } - if (phyIdReg1 == 0xffff) { + if (phyIdReg1 == 0xffff) return result; - } /* oui is split between two registers */ oui = (phyIdReg0 << 6) | ((phyIdReg1 & PHY_OUI_1_MASK) >> 10); @@ -951,15 +896,13 @@ static PHY_DEVICE_et getPhyType (struct ql3_adapter *qdev, model = (phyIdReg1 & PHY_MODEL_MASK) >> 4; /* Scan table for this PHY */ - for(i = 0; i < MAX_PHY_DEV_TYPES; i++) { - if ((oui == PHY_DEVICES[i].phyIdOUI) && (model == PHY_DEVICES[i].phyIdModel)) - { + for (i = 0; i < MAX_PHY_DEV_TYPES; i++) { + if ((oui == PHY_DEVICES[i].phyIdOUI) && + (model == PHY_DEVICES[i].phyIdModel)) { + netdev_info(qdev->ndev, "Phy: %s\n", + PHY_DEVICES[i].name); result = PHY_DEVICES[i].phyDevice; - - printk(KERN_INFO "%s: Phy: %s\n", - qdev->ndev->name, PHY_DEVICES[i].name); - - break; + break; } } @@ -970,9 +913,8 @@ static int ql_phy_get_speed(struct ql3_adapter *qdev) { u16 reg; - switch(qdev->phyType) { - case PHY_AGERE_ET1011C: - { + switch (qdev->phyType) { + case PHY_AGERE_ET1011C: { if (ql_mii_read_reg(qdev, 0x1A, ®) < 0) return 0; @@ -980,20 +922,20 @@ static int ql_phy_get_speed(struct ql3_adapter *qdev) break; } default: - if (ql_mii_read_reg(qdev, AUX_CONTROL_STATUS, ®) < 0) - return 0; + if (ql_mii_read_reg(qdev, AUX_CONTROL_STATUS, ®) < 0) + return 0; - reg = (((reg & 0x18) >> 3) & 3); + reg = (((reg & 0x18) >> 3) & 3); } - switch(reg) { - case 2: + switch (reg) { + case 2: return SPEED_1000; - case 1: + case 1: return SPEED_100; - case 0: + case 0: return SPEED_10; - default: + default: return -1; } } @@ -1002,17 +944,15 @@ static int ql_is_full_dup(struct ql3_adapter *qdev) { u16 reg; - switch(qdev->phyType) { - case PHY_AGERE_ET1011C: - { + switch (qdev->phyType) { + case PHY_AGERE_ET1011C: { if (ql_mii_read_reg(qdev, 0x1A, ®)) return 0; return ((reg & 0x0080) && (reg & 0x1000)) != 0; } case PHY_VITESSE_VSC8211: - default: - { + default: { if (ql_mii_read_reg(qdev, AUX_CONTROL_STATUS, ®) < 0) return 0; return (reg & PHY_AUX_DUPLEX_STAT) != 0; @@ -1040,17 +980,15 @@ static int PHY_Setup(struct ql3_adapter *qdev) /* Determine the PHY we are using by reading the ID's */ err = ql_mii_read_reg(qdev, PHY_ID_0_REG, ®1); - if(err != 0) { - printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG\n", - qdev->ndev->name); - return err; + if (err != 0) { + netdev_err(qdev->ndev, "Could not read from reg PHY_ID_0_REG\n"); + return err; } err = ql_mii_read_reg(qdev, PHY_ID_1_REG, ®2); - if(err != 0) { - printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG\n", - qdev->ndev->name); - return err; + if (err != 0) { + netdev_err(qdev->ndev, "Could not read from reg PHY_ID_1_REG\n"); + return err; } /* Check if we have a Agere PHY */ @@ -1058,24 +996,22 @@ static int PHY_Setup(struct ql3_adapter *qdev) /* Determine which MII address we should be using determined by the index of the card */ - if (qdev->mac_index == 0) { + if (qdev->mac_index == 0) miiAddr = MII_AGERE_ADDR_1; - } else { + else miiAddr = MII_AGERE_ADDR_2; - } - err =ql_mii_read_reg_ex(qdev, PHY_ID_0_REG, ®1, miiAddr); - if(err != 0) { - printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG after Agere detected\n", - qdev->ndev->name); + err = ql_mii_read_reg_ex(qdev, PHY_ID_0_REG, ®1, miiAddr); + if (err != 0) { + netdev_err(qdev->ndev, + "Could not read from reg PHY_ID_0_REG after Agere detected\n"); return err; } err = ql_mii_read_reg_ex(qdev, PHY_ID_1_REG, ®2, miiAddr); - if(err != 0) { - printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG after Agere detected\n", - qdev->ndev->name); - return err; + if (err != 0) { + netdev_err(qdev->ndev, "Could not read from reg PHY_ID_1_REG after Agere detected\n"); + return err; } /* We need to remember to initialize the Agere PHY */ @@ -1090,7 +1026,7 @@ static int PHY_Setup(struct ql3_adapter *qdev) /* need this here so address gets changed */ phyAgereSpecificInit(qdev, miiAddr); } else if (qdev->phyType == PHY_TYPE_UNKNOWN) { - printk(KERN_ERR "%s: PHY is unknown\n", qdev->ndev->name); + netdev_err(qdev->ndev, "PHY is unknown\n"); return -EIO; } @@ -1103,7 +1039,7 @@ static int PHY_Setup(struct ql3_adapter *qdev) static void ql_mac_enable(struct ql3_adapter *qdev, u32 enable) { struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; u32 value; if (enable) @@ -1123,7 +1059,7 @@ static void ql_mac_enable(struct ql3_adapter *qdev, u32 enable) static void ql_mac_cfg_soft_reset(struct ql3_adapter *qdev, u32 enable) { struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; u32 value; if (enable) @@ -1143,7 +1079,7 @@ static void ql_mac_cfg_soft_reset(struct ql3_adapter *qdev, u32 enable) static void ql_mac_cfg_gig(struct ql3_adapter *qdev, u32 enable) { struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; u32 value; if (enable) @@ -1163,7 +1099,7 @@ static void ql_mac_cfg_gig(struct ql3_adapter *qdev, u32 enable) static void ql_mac_cfg_full_dup(struct ql3_adapter *qdev, u32 enable) { struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; u32 value; if (enable) @@ -1183,7 +1119,7 @@ static void ql_mac_cfg_full_dup(struct ql3_adapter *qdev, u32 enable) static void ql_mac_cfg_pause(struct ql3_adapter *qdev, u32 enable) { struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; u32 value; if (enable) @@ -1205,7 +1141,7 @@ static void ql_mac_cfg_pause(struct ql3_adapter *qdev, u32 enable) static int ql_is_fiber(struct ql3_adapter *qdev) { struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; u32 bitToCheck = 0; u32 temp; @@ -1235,7 +1171,7 @@ static int ql_is_auto_cfg(struct ql3_adapter *qdev) static int ql_is_auto_neg_complete(struct ql3_adapter *qdev) { struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; u32 bitToCheck = 0; u32 temp; @@ -1250,18 +1186,11 @@ static int ql_is_auto_neg_complete(struct ql3_adapter *qdev) temp = ql_read_page0_reg(qdev, &port_regs->portStatus); if (temp & bitToCheck) { - if (netif_msg_link(qdev)) - printk(KERN_INFO PFX - "%s: Auto-Negotiate complete.\n", - qdev->ndev->name); + netif_info(qdev, link, qdev->ndev, "Auto-Negotiate complete\n"); return 1; - } else { - if (netif_msg_link(qdev)) - printk(KERN_WARNING PFX - "%s: Auto-Negotiate incomplete.\n", - qdev->ndev->name); - return 0; } + netif_info(qdev, link, qdev->ndev, "Auto-Negotiate incomplete\n"); + return 0; } /* @@ -1278,7 +1207,7 @@ static int ql_is_neg_pause(struct ql3_adapter *qdev) static int ql_auto_neg_error(struct ql3_adapter *qdev) { struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; u32 bitToCheck = 0; u32 temp; @@ -1316,7 +1245,7 @@ static int ql_is_link_full_dup(struct ql3_adapter *qdev) static int ql_link_down_detect(struct ql3_adapter *qdev) { struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; u32 bitToCheck = 0; u32 temp; @@ -1340,7 +1269,7 @@ static int ql_link_down_detect(struct ql3_adapter *qdev) static int ql_link_down_detect_clear(struct ql3_adapter *qdev) { struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; switch (qdev->mac_index) { case 0: @@ -1370,7 +1299,7 @@ static int ql_link_down_detect_clear(struct ql3_adapter *qdev) static int ql_this_adapter_controls_port(struct ql3_adapter *qdev) { struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; u32 bitToCheck = 0; u32 temp; @@ -1387,16 +1316,13 @@ static int ql_this_adapter_controls_port(struct ql3_adapter *qdev) temp = ql_read_page0_reg(qdev, &port_regs->portStatus); if (temp & bitToCheck) { - if (netif_msg_link(qdev)) - printk(KERN_DEBUG PFX - "%s: is not link master.\n", qdev->ndev->name); + netif_printk(qdev, link, KERN_DEBUG, qdev->ndev, + "not link master\n"); return 0; - } else { - if (netif_msg_link(qdev)) - printk(KERN_DEBUG PFX - "%s: is link master.\n", qdev->ndev->name); - return 1; } + + netif_printk(qdev, link, KERN_DEBUG, qdev->ndev, "link master\n"); + return 1; } static void ql_phy_reset_ex(struct ql3_adapter *qdev) @@ -1410,19 +1336,20 @@ static void ql_phy_start_neg_ex(struct ql3_adapter *qdev) u16 reg; u16 portConfiguration; - if(qdev->phyType == PHY_AGERE_ET1011C) { - /* turn off external loopback */ + if (qdev->phyType == PHY_AGERE_ET1011C) ql_mii_write_reg(qdev, 0x13, 0x0000); - } + /* turn off external loopback */ - if(qdev->mac_index == 0) - portConfiguration = qdev->nvram_data.macCfg_port0.portConfiguration; + if (qdev->mac_index == 0) + portConfiguration = + qdev->nvram_data.macCfg_port0.portConfiguration; else - portConfiguration = qdev->nvram_data.macCfg_port1.portConfiguration; + portConfiguration = + qdev->nvram_data.macCfg_port1.portConfiguration; /* Some HBA's in the field are set to 0 and they need to be reinterpreted with a default value */ - if(portConfiguration == 0) + if (portConfiguration == 0) portConfiguration = PORT_CONFIG_DEFAULT; /* Set the 1000 advertisements */ @@ -1430,8 +1357,8 @@ static void ql_phy_start_neg_ex(struct ql3_adapter *qdev) PHYAddr[qdev->mac_index]); reg &= ~PHY_GIG_ALL_PARAMS; - if(portConfiguration & PORT_CONFIG_1000MB_SPEED) { - if(portConfiguration & PORT_CONFIG_FULL_DUPLEX_ENABLED) + if (portConfiguration & PORT_CONFIG_1000MB_SPEED) { + if (portConfiguration & PORT_CONFIG_FULL_DUPLEX_ENABLED) reg |= PHY_GIG_ADV_1000F; else reg |= PHY_GIG_ADV_1000H; @@ -1445,29 +1372,27 @@ static void ql_phy_start_neg_ex(struct ql3_adapter *qdev) PHYAddr[qdev->mac_index]); reg &= ~PHY_NEG_ALL_PARAMS; - if(portConfiguration & PORT_CONFIG_SYM_PAUSE_ENABLED) + if (portConfiguration & PORT_CONFIG_SYM_PAUSE_ENABLED) reg |= PHY_NEG_ASY_PAUSE | PHY_NEG_SYM_PAUSE; - if(portConfiguration & PORT_CONFIG_FULL_DUPLEX_ENABLED) { - if(portConfiguration & PORT_CONFIG_100MB_SPEED) + if (portConfiguration & PORT_CONFIG_FULL_DUPLEX_ENABLED) { + if (portConfiguration & PORT_CONFIG_100MB_SPEED) reg |= PHY_NEG_ADV_100F; - if(portConfiguration & PORT_CONFIG_10MB_SPEED) + if (portConfiguration & PORT_CONFIG_10MB_SPEED) reg |= PHY_NEG_ADV_10F; } - if(portConfiguration & PORT_CONFIG_HALF_DUPLEX_ENABLED) { - if(portConfiguration & PORT_CONFIG_100MB_SPEED) + if (portConfiguration & PORT_CONFIG_HALF_DUPLEX_ENABLED) { + if (portConfiguration & PORT_CONFIG_100MB_SPEED) reg |= PHY_NEG_ADV_100H; - if(portConfiguration & PORT_CONFIG_10MB_SPEED) + if (portConfiguration & PORT_CONFIG_10MB_SPEED) reg |= PHY_NEG_ADV_10H; } - if(portConfiguration & - PORT_CONFIG_1000MB_SPEED) { + if (portConfiguration & PORT_CONFIG_1000MB_SPEED) reg |= 1; - } ql_mii_write_reg_ex(qdev, PHY_NEG_ADVER, reg, PHYAddr[qdev->mac_index]); @@ -1492,7 +1417,7 @@ static void ql_phy_init_ex(struct ql3_adapter *qdev) static u32 ql_get_link_state(struct ql3_adapter *qdev) { struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; u32 bitToCheck = 0; u32 temp, linkState; @@ -1504,22 +1429,22 @@ static u32 ql_get_link_state(struct ql3_adapter *qdev) bitToCheck = PORT_STATUS_UP1; break; } + temp = ql_read_page0_reg(qdev, &port_regs->portStatus); - if (temp & bitToCheck) { + if (temp & bitToCheck) linkState = LS_UP; - } else { + else linkState = LS_DOWN; - } + return linkState; } static int ql_port_start(struct ql3_adapter *qdev) { - if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK, + if (ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK, (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) * 2) << 7)) { - printk(KERN_ERR "%s: Could not get hw lock for GIO\n", - qdev->ndev->name); + netdev_err(qdev->ndev, "Could not get hw lock for GIO\n"); return -1; } @@ -1537,19 +1462,16 @@ static int ql_port_start(struct ql3_adapter *qdev) static int ql_finish_auto_neg(struct ql3_adapter *qdev) { - if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK, + if (ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK, (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) * 2) << 7)) return -1; if (!ql_auto_neg_error(qdev)) { - if (test_bit(QL_LINK_MASTER,&qdev->flags)) { + if (test_bit(QL_LINK_MASTER, &qdev->flags)) { /* configure the MAC */ - if (netif_msg_link(qdev)) - printk(KERN_DEBUG PFX - "%s: Configuring link.\n", - qdev->ndev-> - name); + netif_printk(qdev, link, KERN_DEBUG, qdev->ndev, + "Configuring link\n"); ql_mac_cfg_soft_reset(qdev, 1); ql_mac_cfg_gig(qdev, (ql_get_link_speed @@ -1564,43 +1486,32 @@ static int ql_finish_auto_neg(struct ql3_adapter *qdev) ql_mac_cfg_soft_reset(qdev, 0); /* enable the MAC */ - if (netif_msg_link(qdev)) - printk(KERN_DEBUG PFX - "%s: Enabling mac.\n", - qdev->ndev-> - name); + netif_printk(qdev, link, KERN_DEBUG, qdev->ndev, + "Enabling mac\n"); ql_mac_enable(qdev, 1); } qdev->port_link_state = LS_UP; netif_start_queue(qdev->ndev); netif_carrier_on(qdev->ndev); - if (netif_msg_link(qdev)) - printk(KERN_INFO PFX - "%s: Link is up at %d Mbps, %s duplex.\n", - qdev->ndev->name, - ql_get_link_speed(qdev), - ql_is_link_full_dup(qdev) - ? "full" : "half"); + netif_info(qdev, link, qdev->ndev, + "Link is up at %d Mbps, %s duplex\n", + ql_get_link_speed(qdev), + ql_is_link_full_dup(qdev) ? "full" : "half"); } else { /* Remote error detected */ - if (test_bit(QL_LINK_MASTER,&qdev->flags)) { - if (netif_msg_link(qdev)) - printk(KERN_DEBUG PFX - "%s: Remote error detected. " - "Calling ql_port_start().\n", - qdev->ndev-> - name); + if (test_bit(QL_LINK_MASTER, &qdev->flags)) { + netif_printk(qdev, link, KERN_DEBUG, qdev->ndev, + "Remote error detected. Calling ql_port_start()\n"); /* * ql_port_start() is shared code and needs * to lock the PHY on it's own. */ ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK); - if(ql_port_start(qdev)) {/* Restart port */ + if (ql_port_start(qdev)) /* Restart port */ return -1; - } else - return 0; + return 0; } } ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK); @@ -1619,33 +1530,28 @@ static void ql_link_state_machine_work(struct work_struct *work) curr_link_state = ql_get_link_state(qdev); - if (test_bit(QL_RESET_ACTIVE,&qdev->flags)) { - if (netif_msg_link(qdev)) - printk(KERN_INFO PFX - "%s: Reset in progress, skip processing link " - "state.\n", qdev->ndev->name); + if (test_bit(QL_RESET_ACTIVE, &qdev->flags)) { + netif_info(qdev, link, qdev->ndev, + "Reset in progress, skip processing link state\n"); spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); /* Restart timer on 2 second interval. */ - mod_timer(&qdev->adapter_timer, jiffies + HZ * 1);\ + mod_timer(&qdev->adapter_timer, jiffies + HZ * 1); return; } switch (qdev->port_link_state) { default: - if (test_bit(QL_LINK_MASTER,&qdev->flags)) { + if (test_bit(QL_LINK_MASTER, &qdev->flags)) ql_port_start(qdev); - } qdev->port_link_state = LS_DOWN; /* Fall Through */ case LS_DOWN: if (curr_link_state == LS_UP) { - if (netif_msg_link(qdev)) - printk(KERN_INFO PFX "%s: Link is up.\n", - qdev->ndev->name); + netif_info(qdev, link, qdev->ndev, "Link is up\n"); if (ql_is_auto_neg_complete(qdev)) ql_finish_auto_neg(qdev); @@ -1662,9 +1568,7 @@ static void ql_link_state_machine_work(struct work_struct *work) * back up */ if (curr_link_state == LS_DOWN) { - if (netif_msg_link(qdev)) - printk(KERN_INFO PFX "%s: Link is down.\n", - qdev->ndev->name); + netif_info(qdev, link, qdev->ndev, "Link is down\n"); qdev->port_link_state = LS_DOWN; } if (ql_link_down_detect(qdev)) @@ -1683,9 +1587,9 @@ static void ql_link_state_machine_work(struct work_struct *work) static void ql_get_phy_owner(struct ql3_adapter *qdev) { if (ql_this_adapter_controls_port(qdev)) - set_bit(QL_LINK_MASTER,&qdev->flags); + set_bit(QL_LINK_MASTER, &qdev->flags); else - clear_bit(QL_LINK_MASTER,&qdev->flags); + clear_bit(QL_LINK_MASTER, &qdev->flags); } /* @@ -1695,7 +1599,7 @@ static void ql_init_scan_mode(struct ql3_adapter *qdev) { ql_mii_enable_scan_mode(qdev); - if (test_bit(QL_LINK_OPTICAL,&qdev->flags)) { + if (test_bit(QL_LINK_OPTICAL, &qdev->flags)) { if (ql_this_adapter_controls_port(qdev)) ql_petbi_init_ex(qdev); } else { @@ -1705,18 +1609,18 @@ static void ql_init_scan_mode(struct ql3_adapter *qdev) } /* - * MII_Setup needs to be called before taking the PHY out of reset so that the - * management interface clock speed can be set properly. It would be better if - * we had a way to disable MDC until after the PHY is out of reset, but we - * don't have that capability. + * MII_Setup needs to be called before taking the PHY out of reset + * so that the management interface clock speed can be set properly. + * It would be better if we had a way to disable MDC until after the + * PHY is out of reset, but we don't have that capability. */ static int ql_mii_setup(struct ql3_adapter *qdev) { u32 reg; struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; - if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK, + if (ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK, (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) * 2) << 7)) return -1; @@ -1735,24 +1639,24 @@ static int ql_mii_setup(struct ql3_adapter *qdev) return 0; } +#define SUPPORTED_OPTICAL_MODES (SUPPORTED_1000baseT_Full | \ + SUPPORTED_FIBRE | \ + SUPPORTED_Autoneg) +#define SUPPORTED_TP_MODES (SUPPORTED_10baseT_Half | \ + SUPPORTED_10baseT_Full | \ + SUPPORTED_100baseT_Half | \ + SUPPORTED_100baseT_Full | \ + SUPPORTED_1000baseT_Half | \ + SUPPORTED_1000baseT_Full | \ + SUPPORTED_Autoneg | \ + SUPPORTED_TP); \ + static u32 ql_supported_modes(struct ql3_adapter *qdev) { - u32 supported; + if (test_bit(QL_LINK_OPTICAL, &qdev->flags)) + return SUPPORTED_OPTICAL_MODES; - if (test_bit(QL_LINK_OPTICAL,&qdev->flags)) { - supported = SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE - | SUPPORTED_Autoneg; - } else { - supported = SUPPORTED_10baseT_Half - | SUPPORTED_10baseT_Full - | SUPPORTED_100baseT_Half - | SUPPORTED_100baseT_Full - | SUPPORTED_1000baseT_Half - | SUPPORTED_1000baseT_Full - | SUPPORTED_Autoneg | SUPPORTED_TP; - } - - return supported; + return SUPPORTED_TP_MODES; } static int ql_get_auto_cfg_status(struct ql3_adapter *qdev) @@ -1760,9 +1664,9 @@ static int ql_get_auto_cfg_status(struct ql3_adapter *qdev) int status; unsigned long hw_flags; spin_lock_irqsave(&qdev->hw_lock, hw_flags); - if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK, - (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) * - 2) << 7)) { + if (ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK, + (QL_RESOURCE_BITS_BASE_CODE | + (qdev->mac_index) * 2) << 7)) { spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); return 0; } @@ -1777,9 +1681,9 @@ static u32 ql_get_speed(struct ql3_adapter *qdev) u32 status; unsigned long hw_flags; spin_lock_irqsave(&qdev->hw_lock, hw_flags); - if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK, - (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) * - 2) << 7)) { + if (ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK, + (QL_RESOURCE_BITS_BASE_CODE | + (qdev->mac_index) * 2) << 7)) { spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); return 0; } @@ -1794,9 +1698,9 @@ static int ql_get_full_dup(struct ql3_adapter *qdev) int status; unsigned long hw_flags; spin_lock_irqsave(&qdev->hw_lock, hw_flags); - if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK, - (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) * - 2) << 7)) { + if (ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK, + (QL_RESOURCE_BITS_BASE_CODE | + (qdev->mac_index) * 2) << 7)) { spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); return 0; } @@ -1806,7 +1710,6 @@ static int ql_get_full_dup(struct ql3_adapter *qdev) return status; } - static int ql_get_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) { struct ql3_adapter *qdev = netdev_priv(ndev); @@ -1814,7 +1717,7 @@ static int ql_get_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) ecmd->transceiver = XCVR_INTERNAL; ecmd->supported = ql_supported_modes(qdev); - if (test_bit(QL_LINK_OPTICAL,&qdev->flags)) { + if (test_bit(QL_LINK_OPTICAL, &qdev->flags)) { ecmd->port = PORT_FIBRE; } else { ecmd->port = PORT_TP; @@ -1855,10 +1758,11 @@ static void ql_get_pauseparam(struct net_device *ndev, struct ethtool_pauseparam *pause) { struct ql3_adapter *qdev = netdev_priv(ndev); - struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; + struct ql3xxx_port_registers __iomem *port_regs = + qdev->mem_map_registers; u32 reg; - if(qdev->mac_index == 0) + if (qdev->mac_index == 0) reg = ql_read_page0_reg(qdev, &port_regs->mac0ConfigReg); else reg = ql_read_page0_reg(qdev, &port_regs->mac1ConfigReg); @@ -1885,12 +1789,12 @@ static int ql_populate_free_queue(struct ql3_adapter *qdev) while (lrg_buf_cb) { if (!lrg_buf_cb->skb) { - lrg_buf_cb->skb = netdev_alloc_skb(qdev->ndev, - qdev->lrg_buffer_len); + lrg_buf_cb->skb = + netdev_alloc_skb(qdev->ndev, + qdev->lrg_buffer_len); if (unlikely(!lrg_buf_cb->skb)) { - printk(KERN_DEBUG PFX - "%s: Failed netdev_alloc_skb().\n", - qdev->ndev->name); + netdev_printk(KERN_DEBUG, qdev->ndev, + "Failed netdev_alloc_skb()\n"); break; } else { /* @@ -1905,9 +1809,10 @@ static int ql_populate_free_queue(struct ql3_adapter *qdev) PCI_DMA_FROMDEVICE); err = pci_dma_mapping_error(qdev->pdev, map); - if(err) { - printk(KERN_ERR "%s: PCI mapping failed with error: %d\n", - qdev->ndev->name, err); + if (err) { + netdev_err(qdev->ndev, + "PCI mapping failed with error: %d\n", + err); dev_kfree_skb(lrg_buf_cb->skb); lrg_buf_cb->skb = NULL; break; @@ -1915,9 +1820,9 @@ static int ql_populate_free_queue(struct ql3_adapter *qdev) lrg_buf_cb->buf_phy_addr_low = - cpu_to_le32(LS_64BITS(map)); + cpu_to_le32(LS_64BITS(map)); lrg_buf_cb->buf_phy_addr_high = - cpu_to_le32(MS_64BITS(map)); + cpu_to_le32(MS_64BITS(map)); dma_unmap_addr_set(lrg_buf_cb, mapaddr, map); dma_unmap_len_set(lrg_buf_cb, maplen, qdev->lrg_buffer_len - @@ -1937,7 +1842,9 @@ static int ql_populate_free_queue(struct ql3_adapter *qdev) */ static void ql_update_small_bufq_prod_index(struct ql3_adapter *qdev) { - struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; + struct ql3xxx_port_registers __iomem *port_regs = + qdev->mem_map_registers; + if (qdev->small_buf_release_cnt >= 16) { while (qdev->small_buf_release_cnt >= 16) { qdev->small_buf_q_producer_index++; @@ -1961,7 +1868,8 @@ static void ql_update_lrg_bufq_prod_index(struct ql3_adapter *qdev) struct bufq_addr_element *lrg_buf_q_ele; int i; struct ql_rcv_buf_cb *lrg_buf_cb; - struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; + struct ql3xxx_port_registers __iomem *port_regs = + qdev->mem_map_registers; if ((qdev->lrg_buf_free_count >= 8) && (qdev->lrg_buf_release_cnt >= 16)) { @@ -1989,7 +1897,8 @@ static void ql_update_lrg_bufq_prod_index(struct ql3_adapter *qdev) qdev->lrg_buf_q_producer_index++; - if (qdev->lrg_buf_q_producer_index == qdev->num_lbufq_entries) + if (qdev->lrg_buf_q_producer_index == + qdev->num_lbufq_entries) qdev->lrg_buf_q_producer_index = 0; if (qdev->lrg_buf_q_producer_index == @@ -2011,23 +1920,26 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev, int i; int retval = 0; - if(mac_rsp->flags & OB_MAC_IOCB_RSP_S) { - printk(KERN_WARNING "Frame short but, frame was padded and sent.\n"); + if (mac_rsp->flags & OB_MAC_IOCB_RSP_S) { + netdev_warn(qdev->ndev, + "Frame too short but it was padded and sent\n"); } tx_cb = &qdev->tx_buf[mac_rsp->transaction_id]; /* Check the transmit response flags for any errors */ - if(mac_rsp->flags & OB_MAC_IOCB_RSP_S) { - printk(KERN_ERR "Frame too short to be legal, frame not sent.\n"); + if (mac_rsp->flags & OB_MAC_IOCB_RSP_S) { + netdev_err(qdev->ndev, + "Frame too short to be legal, frame not sent\n"); qdev->ndev->stats.tx_errors++; retval = -EIO; goto frame_not_sent; } - if(tx_cb->seg_count == 0) { - printk(KERN_ERR "tx_cb->seg_count == 0: %d\n", mac_rsp->transaction_id); + if (tx_cb->seg_count == 0) { + netdev_err(qdev->ndev, "tx_cb->seg_count == 0: %d\n", + mac_rsp->transaction_id); qdev->ndev->stats.tx_errors++; retval = -EIO; @@ -2073,7 +1985,7 @@ static struct ql_rcv_buf_cb *ql_get_lbuf(struct ql3_adapter *qdev) qdev->lrg_buf_release_cnt++; if (++qdev->lrg_buf_index == qdev->num_large_buffers) qdev->lrg_buf_index = 0; - return(lrg_buf_cb); + return lrg_buf_cb; } /* @@ -2177,12 +2089,11 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev, if (checksum & (IB_IP_IOCB_RSP_3032_ICE | IB_IP_IOCB_RSP_3032_CE)) { - printk(KERN_ERR - "%s: Bad checksum for this %s packet, checksum = %x.\n", - __func__, - ((checksum & - IB_IP_IOCB_RSP_3032_TCP) ? "TCP" : - "UDP"),checksum); + netdev_err(ndev, + "%s: Bad checksum for this %s packet, checksum = %x\n", + __func__, + ((checksum & IB_IP_IOCB_RSP_3032_TCP) ? + "TCP" : "UDP"), checksum); } else if ((checksum & IB_IP_IOCB_RSP_3032_TCP) || (checksum & IB_IP_IOCB_RSP_3032_UDP && !(checksum & IB_IP_IOCB_RSP_3032_NUC))) { @@ -2215,8 +2126,8 @@ static int ql_tx_rx_clean(struct ql3_adapter *qdev, net_rsp = qdev->rsp_current; rmb(); /* - * Fix 4032 chipe undocumented "feature" where bit-8 is set if the - * inbound completion is for a VLAN. + * Fix 4032 chip's undocumented "feature" where bit-8 is set + * if the inbound completion is for a VLAN. */ if (qdev->device_id == QL3032_DEVICE_ID) net_rsp->opcode &= 0x7f; @@ -2242,22 +2153,18 @@ static int ql_tx_rx_clean(struct ql3_adapter *qdev, net_rsp); (*rx_cleaned)++; break; - default: - { - u32 *tmp = (u32 *) net_rsp; - printk(KERN_ERR PFX - "%s: Hit default case, not " - "handled!\n" - " dropping the packet, opcode = " - "%x.\n", - ndev->name, net_rsp->opcode); - printk(KERN_ERR PFX - "0x%08lx 0x%08lx 0x%08lx 0x%08lx\n", - (unsigned long int)tmp[0], - (unsigned long int)tmp[1], - (unsigned long int)tmp[2], - (unsigned long int)tmp[3]); - } + default: { + u32 *tmp = (u32 *)net_rsp; + netdev_err(ndev, + "Hit default case, not handled!\n" + " dropping the packet, opcode = %x\n" + "0x%08lx 0x%08lx 0x%08lx 0x%08lx\n", + net_rsp->opcode, + (unsigned long int)tmp[0], + (unsigned long int)tmp[1], + (unsigned long int)tmp[2], + (unsigned long int)tmp[3]); + } } qdev->rsp_consumer_index++; @@ -2280,7 +2187,8 @@ static int ql_poll(struct napi_struct *napi, int budget) struct ql3_adapter *qdev = container_of(napi, struct ql3_adapter, napi); int rx_cleaned = 0, tx_cleaned = 0; unsigned long hw_flags; - struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; + struct ql3xxx_port_registers __iomem *port_regs = + qdev->mem_map_registers; ql_tx_rx_clean(qdev, &tx_cleaned, &rx_cleaned, budget); @@ -2303,15 +2211,14 @@ static irqreturn_t ql3xxx_isr(int irq, void *dev_id) struct net_device *ndev = dev_id; struct ql3_adapter *qdev = netdev_priv(ndev); - struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; + struct ql3xxx_port_registers __iomem *port_regs = + qdev->mem_map_registers; u32 value; int handled = 1; u32 var; - port_regs = qdev->mem_map_registers; - - value = - ql_read_common_reg_l(qdev, &port_regs->CommonRegs.ispControlStatus); + value = ql_read_common_reg_l(qdev, + &port_regs->CommonRegs.ispControlStatus); if (value & (ISP_CONTROL_FE | ISP_CONTROL_RI)) { spin_lock(&qdev->adapter_lock); @@ -2319,7 +2226,7 @@ static irqreturn_t ql3xxx_isr(int irq, void *dev_id) netif_carrier_off(qdev->ndev); ql_disable_interrupts(qdev); qdev->port_link_state = LS_DOWN; - set_bit(QL_RESET_ACTIVE,&qdev->flags) ; + set_bit(QL_RESET_ACTIVE, &qdev->flags) ; if (value & ISP_CONTROL_FE) { /* @@ -2328,69 +2235,53 @@ static irqreturn_t ql3xxx_isr(int irq, void *dev_id) var = ql_read_page0_reg_l(qdev, &port_regs->PortFatalErrStatus); - printk(KERN_WARNING PFX - "%s: Resetting chip. PortFatalErrStatus " - "register = 0x%x\n", ndev->name, var); - set_bit(QL_RESET_START,&qdev->flags) ; + netdev_warn(ndev, + "Resetting chip. PortFatalErrStatus register = 0x%x\n", + var); + set_bit(QL_RESET_START, &qdev->flags) ; } else { /* * Soft Reset Requested. */ - set_bit(QL_RESET_PER_SCSI,&qdev->flags) ; - printk(KERN_ERR PFX - "%s: Another function issued a reset to the " - "chip. ISR value = %x.\n", ndev->name, value); + set_bit(QL_RESET_PER_SCSI, &qdev->flags) ; + netdev_err(ndev, + "Another function issued a reset to the chip. ISR value = %x\n", + value); } queue_delayed_work(qdev->workqueue, &qdev->reset_work, 0); spin_unlock(&qdev->adapter_lock); } else if (value & ISP_IMR_DISABLE_CMPL_INT) { ql_disable_interrupts(qdev); - if (likely(napi_schedule_prep(&qdev->napi))) { + if (likely(napi_schedule_prep(&qdev->napi))) __napi_schedule(&qdev->napi); - } - } else { + } else return IRQ_NONE; - } return IRQ_RETVAL(handled); } /* - * Get the total number of segments needed for the - * given number of fragments. This is necessary because - * outbound address lists (OAL) will be used when more than - * two frags are given. Each address list has 5 addr/len - * pairs. The 5th pair in each AOL is used to point to - * the next AOL if more frags are coming. - * That is why the frags:segment count ratio is not linear. + * Get the total number of segments needed for the given number of fragments. + * This is necessary because outbound address lists (OAL) will be used when + * more than two frags are given. Each address list has 5 addr/len pairs. + * The 5th pair in each OAL is used to point to the next OAL if more frags + * are coming. That is why the frags:segment count ratio is not linear. */ -static int ql_get_seg_count(struct ql3_adapter *qdev, - unsigned short frags) +static int ql_get_seg_count(struct ql3_adapter *qdev, unsigned short frags) { if (qdev->device_id == QL3022_DEVICE_ID) return 1; - switch(frags) { - case 0: return 1; /* just the skb->data seg */ - case 1: return 2; /* skb->data + 1 frag */ - case 2: return 3; /* skb->data + 2 frags */ - case 3: return 5; /* skb->data + 1 frag + 1 AOL containting 2 frags */ - case 4: return 6; - case 5: return 7; - case 6: return 8; - case 7: return 10; - case 8: return 11; - case 9: return 12; - case 10: return 13; - case 11: return 15; - case 12: return 16; - case 13: return 17; - case 14: return 18; - case 15: return 20; - case 16: return 21; - case 17: return 22; - case 18: return 23; - } + if (frags <= 2) + return frags + 1; + else if (frags <= 6) + return frags + 2; + else if (frags <= 10) + return frags + 3; + else if (frags <= 14) + return frags + 4; + else if (frags <= 18) + return frags + 5; return -1; } @@ -2413,8 +2304,8 @@ static void ql_hw_csum_setup(const struct sk_buff *skb, } /* - * Map the buffers for this transmit. This will return - * NETDEV_TX_BUSY or NETDEV_TX_OK based on success. + * Map the buffers for this transmit. + * This will return NETDEV_TX_BUSY or NETDEV_TX_OK based on success. */ static int ql_send_map(struct ql3_adapter *qdev, struct ob_mac_iocb_req *mac_iocb_ptr, @@ -2437,9 +2328,9 @@ static int ql_send_map(struct ql3_adapter *qdev, map = pci_map_single(qdev->pdev, skb->data, len, PCI_DMA_TODEVICE); err = pci_dma_mapping_error(qdev->pdev, map); - if(err) { - printk(KERN_ERR "%s: PCI mapping failed with error: %d\n", - qdev->ndev->name, err); + if (err) { + netdev_err(qdev->ndev, "PCI mapping failed with error: %d\n", + err); return NETDEV_TX_BUSY; } @@ -2455,65 +2346,67 @@ static int ql_send_map(struct ql3_adapter *qdev, if (seg_cnt == 1) { /* Terminate the last segment. */ oal_entry->len |= cpu_to_le32(OAL_LAST_ENTRY); - } else { - oal = tx_cb->oal; - for (completed_segs=0; completed_segs<frag_cnt; completed_segs++,seg++) { - skb_frag_t *frag = &skb_shinfo(skb)->frags[completed_segs]; - oal_entry++; - if ((seg == 2 && seg_cnt > 3) || /* Check for continuation */ - (seg == 7 && seg_cnt > 8) || /* requirements. It's strange */ - (seg == 12 && seg_cnt > 13) || /* but necessary. */ - (seg == 17 && seg_cnt > 18)) { - /* Continuation entry points to outbound address list. */ - map = pci_map_single(qdev->pdev, oal, - sizeof(struct oal), - PCI_DMA_TODEVICE); - - err = pci_dma_mapping_error(qdev->pdev, map); - if(err) { - - printk(KERN_ERR "%s: PCI mapping outbound address list with error: %d\n", - qdev->ndev->name, err); - goto map_error; - } - - oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map)); - oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map)); - oal_entry->len = - cpu_to_le32(sizeof(struct oal) | - OAL_CONT_ENTRY); - dma_unmap_addr_set(&tx_cb->map[seg], mapaddr, - map); - dma_unmap_len_set(&tx_cb->map[seg], maplen, - sizeof(struct oal)); - oal_entry = (struct oal_entry *)oal; - oal++; - seg++; - } - - map = - pci_map_page(qdev->pdev, frag->page, - frag->page_offset, frag->size, - PCI_DMA_TODEVICE); + return NETDEV_TX_OK; + } + oal = tx_cb->oal; + for (completed_segs = 0; + completed_segs < frag_cnt; + completed_segs++, seg++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[completed_segs]; + oal_entry++; + /* + * Check for continuation requirements. + * It's strange but necessary. + * Continuation entry points to outbound address list. + */ + if ((seg == 2 && seg_cnt > 3) || + (seg == 7 && seg_cnt > 8) || + (seg == 12 && seg_cnt > 13) || + (seg == 17 && seg_cnt > 18)) { + map = pci_map_single(qdev->pdev, oal, + sizeof(struct oal), + PCI_DMA_TODEVICE); err = pci_dma_mapping_error(qdev->pdev, map); - if(err) { - printk(KERN_ERR "%s: PCI mapping frags failed with error: %d\n", - qdev->ndev->name, err); + if (err) { + netdev_err(qdev->ndev, + "PCI mapping outbound address list with error: %d\n", + err); goto map_error; } oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map)); oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map)); - oal_entry->len = cpu_to_le32(frag->size); + oal_entry->len = cpu_to_le32(sizeof(struct oal) | + OAL_CONT_ENTRY); dma_unmap_addr_set(&tx_cb->map[seg], mapaddr, map); dma_unmap_len_set(&tx_cb->map[seg], maplen, - frag->size); + sizeof(struct oal)); + oal_entry = (struct oal_entry *)oal; + oal++; + seg++; + } + + map = pci_map_page(qdev->pdev, frag->page, + frag->page_offset, frag->size, + PCI_DMA_TODEVICE); + + err = pci_dma_mapping_error(qdev->pdev, map); + if (err) { + netdev_err(qdev->ndev, + "PCI mapping frags failed with error: %d\n", + err); + goto map_error; } - /* Terminate the last segment. */ - oal_entry->len |= cpu_to_le32(OAL_LAST_ENTRY); - } + oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map)); + oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map)); + oal_entry->len = cpu_to_le32(frag->size); + dma_unmap_addr_set(&tx_cb->map[seg], mapaddr, map); + dma_unmap_len_set(&tx_cb->map[seg], maplen, frag->size); + } + /* Terminate the last segment. */ + oal_entry->len |= cpu_to_le32(OAL_LAST_ENTRY); return NETDEV_TX_OK; map_error: @@ -2525,13 +2418,18 @@ map_error: seg = 1; oal_entry = (struct oal_entry *)&mac_iocb_ptr->buf_addr0_low; oal = tx_cb->oal; - for (i=0; i<completed_segs; i++,seg++) { + for (i = 0; i < completed_segs; i++, seg++) { oal_entry++; - if((seg == 2 && seg_cnt > 3) || /* Check for continuation */ - (seg == 7 && seg_cnt > 8) || /* requirements. It's strange */ - (seg == 12 && seg_cnt > 13) || /* but necessary. */ - (seg == 17 && seg_cnt > 18)) { + /* + * Check for continuation requirements. + * It's strange but necessary. + */ + + if ((seg == 2 && seg_cnt > 3) || + (seg == 7 && seg_cnt > 8) || + (seg == 12 && seg_cnt > 13) || + (seg == 17 && seg_cnt > 18)) { pci_unmap_single(qdev->pdev, dma_unmap_addr(&tx_cb->map[seg], mapaddr), dma_unmap_len(&tx_cb->map[seg], maplen), @@ -2570,19 +2468,20 @@ static netdev_tx_t ql3xxx_send(struct sk_buff *skb, struct net_device *ndev) { struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev); - struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; + struct ql3xxx_port_registers __iomem *port_regs = + qdev->mem_map_registers; struct ql_tx_buf_cb *tx_cb; u32 tot_len = skb->len; struct ob_mac_iocb_req *mac_iocb_ptr; - if (unlikely(atomic_read(&qdev->tx_count) < 2)) { + if (unlikely(atomic_read(&qdev->tx_count) < 2)) return NETDEV_TX_BUSY; - } - tx_cb = &qdev->tx_buf[qdev->req_producer_index] ; - if((tx_cb->seg_count = ql_get_seg_count(qdev, - (skb_shinfo(skb)->nr_frags))) == -1) { - printk(KERN_ERR PFX"%s: invalid segment count!\n",__func__); + tx_cb = &qdev->tx_buf[qdev->req_producer_index]; + tx_cb->seg_count = ql_get_seg_count(qdev, + skb_shinfo(skb)->nr_frags); + if (tx_cb->seg_count == -1) { + netdev_err(ndev, "%s: invalid segment count!\n", __func__); return NETDEV_TX_OK; } @@ -2598,8 +2497,8 @@ static netdev_tx_t ql3xxx_send(struct sk_buff *skb, skb->ip_summed == CHECKSUM_PARTIAL) ql_hw_csum_setup(skb, mac_iocb_ptr); - if(ql_send_map(qdev,mac_iocb_ptr,tx_cb,skb) != NETDEV_TX_OK) { - printk(KERN_ERR PFX"%s: Could not map the segments!\n",__func__); + if (ql_send_map(qdev, mac_iocb_ptr, tx_cb, skb) != NETDEV_TX_OK) { + netdev_err(ndev, "%s: Could not map the segments!\n", __func__); return NETDEV_TX_BUSY; } @@ -2612,9 +2511,9 @@ static netdev_tx_t ql3xxx_send(struct sk_buff *skb, &port_regs->CommonRegs.reqQProducerIndex, qdev->req_producer_index); - if (netif_msg_tx_queued(qdev)) - printk(KERN_DEBUG PFX "%s: tx queued, slot %d, len %d\n", - ndev->name, qdev->req_producer_index, skb->len); + netif_printk(qdev, tx_queued, KERN_DEBUG, ndev, + "tx queued, slot %d, len %d\n", + qdev->req_producer_index, skb->len); atomic_dec(&qdev->tx_count); return NETDEV_TX_OK; @@ -2632,8 +2531,7 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev) if ((qdev->req_q_virt_addr == NULL) || LS_64BITS(qdev->req_q_phy_addr) & (qdev->req_q_size - 1)) { - printk(KERN_ERR PFX "%s: reqQ failed.\n", - qdev->ndev->name); + netdev_err(qdev->ndev, "reqQ failed\n"); return -ENOMEM; } @@ -2646,25 +2544,22 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev) if ((qdev->rsp_q_virt_addr == NULL) || LS_64BITS(qdev->rsp_q_phy_addr) & (qdev->rsp_q_size - 1)) { - printk(KERN_ERR PFX - "%s: rspQ allocation failed\n", - qdev->ndev->name); + netdev_err(qdev->ndev, "rspQ allocation failed\n"); pci_free_consistent(qdev->pdev, (size_t) qdev->req_q_size, qdev->req_q_virt_addr, qdev->req_q_phy_addr); return -ENOMEM; } - set_bit(QL_ALLOC_REQ_RSP_Q_DONE,&qdev->flags); + set_bit(QL_ALLOC_REQ_RSP_Q_DONE, &qdev->flags); return 0; } static void ql_free_net_req_rsp_queues(struct ql3_adapter *qdev) { - if (!test_bit(QL_ALLOC_REQ_RSP_Q_DONE,&qdev->flags)) { - printk(KERN_INFO PFX - "%s: Already done.\n", qdev->ndev->name); + if (!test_bit(QL_ALLOC_REQ_RSP_Q_DONE, &qdev->flags)) { + netdev_info(qdev->ndev, "Already done\n"); return; } @@ -2680,34 +2575,34 @@ static void ql_free_net_req_rsp_queues(struct ql3_adapter *qdev) qdev->rsp_q_virt_addr = NULL; - clear_bit(QL_ALLOC_REQ_RSP_Q_DONE,&qdev->flags); + clear_bit(QL_ALLOC_REQ_RSP_Q_DONE, &qdev->flags); } static int ql_alloc_buffer_queues(struct ql3_adapter *qdev) { /* Create Large Buffer Queue */ qdev->lrg_buf_q_size = - qdev->num_lbufq_entries * sizeof(struct lrg_buf_q_entry); + qdev->num_lbufq_entries * sizeof(struct lrg_buf_q_entry); if (qdev->lrg_buf_q_size < PAGE_SIZE) qdev->lrg_buf_q_alloc_size = PAGE_SIZE; else qdev->lrg_buf_q_alloc_size = qdev->lrg_buf_q_size * 2; - qdev->lrg_buf = kmalloc(qdev->num_large_buffers * sizeof(struct ql_rcv_buf_cb),GFP_KERNEL); + qdev->lrg_buf = + kmalloc(qdev->num_large_buffers * sizeof(struct ql_rcv_buf_cb), + GFP_KERNEL); if (qdev->lrg_buf == NULL) { - printk(KERN_ERR PFX - "%s: qdev->lrg_buf alloc failed.\n", qdev->ndev->name); + netdev_err(qdev->ndev, "qdev->lrg_buf alloc failed\n"); return -ENOMEM; } qdev->lrg_buf_q_alloc_virt_addr = - pci_alloc_consistent(qdev->pdev, - qdev->lrg_buf_q_alloc_size, - &qdev->lrg_buf_q_alloc_phy_addr); + pci_alloc_consistent(qdev->pdev, + qdev->lrg_buf_q_alloc_size, + &qdev->lrg_buf_q_alloc_phy_addr); if (qdev->lrg_buf_q_alloc_virt_addr == NULL) { - printk(KERN_ERR PFX - "%s: lBufQ failed\n", qdev->ndev->name); + netdev_err(qdev->ndev, "lBufQ failed\n"); return -ENOMEM; } qdev->lrg_buf_q_virt_addr = qdev->lrg_buf_q_alloc_virt_addr; @@ -2715,21 +2610,19 @@ static int ql_alloc_buffer_queues(struct ql3_adapter *qdev) /* Create Small Buffer Queue */ qdev->small_buf_q_size = - NUM_SBUFQ_ENTRIES * sizeof(struct lrg_buf_q_entry); + NUM_SBUFQ_ENTRIES * sizeof(struct lrg_buf_q_entry); if (qdev->small_buf_q_size < PAGE_SIZE) qdev->small_buf_q_alloc_size = PAGE_SIZE; else qdev->small_buf_q_alloc_size = qdev->small_buf_q_size * 2; qdev->small_buf_q_alloc_virt_addr = - pci_alloc_consistent(qdev->pdev, - qdev->small_buf_q_alloc_size, - &qdev->small_buf_q_alloc_phy_addr); + pci_alloc_consistent(qdev->pdev, + qdev->small_buf_q_alloc_size, + &qdev->small_buf_q_alloc_phy_addr); if (qdev->small_buf_q_alloc_virt_addr == NULL) { - printk(KERN_ERR PFX - "%s: Small Buffer Queue allocation failed.\n", - qdev->ndev->name); + netdev_err(qdev->ndev, "Small Buffer Queue allocation failed\n"); pci_free_consistent(qdev->pdev, qdev->lrg_buf_q_alloc_size, qdev->lrg_buf_q_alloc_virt_addr, qdev->lrg_buf_q_alloc_phy_addr); @@ -2738,18 +2631,17 @@ static int ql_alloc_buffer_queues(struct ql3_adapter *qdev) qdev->small_buf_q_virt_addr = qdev->small_buf_q_alloc_virt_addr; qdev->small_buf_q_phy_addr = qdev->small_buf_q_alloc_phy_addr; - set_bit(QL_ALLOC_BUFQS_DONE,&qdev->flags); + set_bit(QL_ALLOC_BUFQS_DONE, &qdev->flags); return 0; } static void ql_free_buffer_queues(struct ql3_adapter *qdev) { - if (!test_bit(QL_ALLOC_BUFQS_DONE,&qdev->flags)) { - printk(KERN_INFO PFX - "%s: Already done.\n", qdev->ndev->name); + if (!test_bit(QL_ALLOC_BUFQS_DONE, &qdev->flags)) { + netdev_info(qdev->ndev, "Already done\n"); return; } - if(qdev->lrg_buf) kfree(qdev->lrg_buf); + kfree(qdev->lrg_buf); pci_free_consistent(qdev->pdev, qdev->lrg_buf_q_alloc_size, qdev->lrg_buf_q_alloc_virt_addr, @@ -2764,7 +2656,7 @@ static void ql_free_buffer_queues(struct ql3_adapter *qdev) qdev->small_buf_q_virt_addr = NULL; - clear_bit(QL_ALLOC_BUFQS_DONE,&qdev->flags); + clear_bit(QL_ALLOC_BUFQS_DONE, &qdev->flags); } static int ql_alloc_small_buffers(struct ql3_adapter *qdev) @@ -2774,18 +2666,16 @@ static int ql_alloc_small_buffers(struct ql3_adapter *qdev) /* Currently we allocate on one of memory and use it for smallbuffers */ qdev->small_buf_total_size = - (QL_ADDR_ELE_PER_BUFQ_ENTRY * NUM_SBUFQ_ENTRIES * - QL_SMALL_BUFFER_SIZE); + (QL_ADDR_ELE_PER_BUFQ_ENTRY * NUM_SBUFQ_ENTRIES * + QL_SMALL_BUFFER_SIZE); qdev->small_buf_virt_addr = - pci_alloc_consistent(qdev->pdev, - qdev->small_buf_total_size, - &qdev->small_buf_phy_addr); + pci_alloc_consistent(qdev->pdev, + qdev->small_buf_total_size, + &qdev->small_buf_phy_addr); if (qdev->small_buf_virt_addr == NULL) { - printk(KERN_ERR PFX - "%s: Failed to get small buffer memory.\n", - qdev->ndev->name); + netdev_err(qdev->ndev, "Failed to get small buffer memory\n"); return -ENOMEM; } @@ -2804,15 +2694,14 @@ static int ql_alloc_small_buffers(struct ql3_adapter *qdev) small_buf_q_entry++; } qdev->small_buf_index = 0; - set_bit(QL_ALLOC_SMALL_BUF_DONE,&qdev->flags); + set_bit(QL_ALLOC_SMALL_BUF_DONE, &qdev->flags); return 0; } static void ql_free_small_buffers(struct ql3_adapter *qdev) { - if (!test_bit(QL_ALLOC_SMALL_BUF_DONE,&qdev->flags)) { - printk(KERN_INFO PFX - "%s: Already done.\n", qdev->ndev->name); + if (!test_bit(QL_ALLOC_SMALL_BUF_DONE, &qdev->flags)) { + netdev_info(qdev->ndev, "Already done\n"); return; } if (qdev->small_buf_virt_addr != NULL) { @@ -2874,11 +2763,9 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev) qdev->lrg_buffer_len); if (unlikely(!skb)) { /* Better luck next round */ - printk(KERN_ERR PFX - "%s: large buff alloc failed, " - "for %d bytes at index %d.\n", - qdev->ndev->name, - qdev->lrg_buffer_len * 2, i); + netdev_err(qdev->ndev, + "large buff alloc failed for %d bytes at index %d\n", + qdev->lrg_buffer_len * 2, i); ql_free_large_buffers(qdev); return -ENOMEM; } else { @@ -2899,9 +2786,10 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev) PCI_DMA_FROMDEVICE); err = pci_dma_mapping_error(qdev->pdev, map); - if(err) { - printk(KERN_ERR "%s: PCI mapping failed with error: %d\n", - qdev->ndev->name, err); + if (err) { + netdev_err(qdev->ndev, + "PCI mapping failed with error: %d\n", + err); ql_free_large_buffers(qdev); return -ENOMEM; } @@ -2926,10 +2814,8 @@ static void ql_free_send_free_list(struct ql3_adapter *qdev) tx_cb = &qdev->tx_buf[0]; for (i = 0; i < NUM_REQ_Q_ENTRIES; i++) { - if (tx_cb->oal) { - kfree(tx_cb->oal); - tx_cb->oal = NULL; - } + kfree(tx_cb->oal); + tx_cb->oal = NULL; tx_cb++; } } @@ -2938,8 +2824,7 @@ static int ql_create_send_free_list(struct ql3_adapter *qdev) { struct ql_tx_buf_cb *tx_cb; int i; - struct ob_mac_iocb_req *req_q_curr = - qdev->req_q_virt_addr; + struct ob_mac_iocb_req *req_q_curr = qdev->req_q_virt_addr; /* Create free list of transmit buffers */ for (i = 0; i < NUM_REQ_Q_ENTRIES; i++) { @@ -2960,23 +2845,22 @@ static int ql_alloc_mem_resources(struct ql3_adapter *qdev) if (qdev->ndev->mtu == NORMAL_MTU_SIZE) { qdev->num_lbufq_entries = NUM_LBUFQ_ENTRIES; qdev->lrg_buffer_len = NORMAL_MTU_SIZE; - } - else if (qdev->ndev->mtu == JUMBO_MTU_SIZE) { + } else if (qdev->ndev->mtu == JUMBO_MTU_SIZE) { /* * Bigger buffers, so less of them. */ qdev->num_lbufq_entries = JUMBO_NUM_LBUFQ_ENTRIES; qdev->lrg_buffer_len = JUMBO_MTU_SIZE; } else { - printk(KERN_ERR PFX - "%s: Invalid mtu size. Only 1500 and 9000 are accepted.\n", - qdev->ndev->name); + netdev_err(qdev->ndev, "Invalid mtu size: %d. Only %d and %d are accepted.\n", + qdev->ndev->mtu, NORMAL_MTU_SIZE, JUMBO_MTU_SIZE); return -ENOMEM; } - qdev->num_large_buffers = qdev->num_lbufq_entries * QL_ADDR_ELE_PER_BUFQ_ENTRY; + qdev->num_large_buffers = + qdev->num_lbufq_entries * QL_ADDR_ELE_PER_BUFQ_ENTRY; qdev->lrg_buffer_len += VLAN_ETH_HLEN + VLAN_ID_LEN + QL_HEADER_SPACE; qdev->max_frame_size = - (qdev->lrg_buffer_len - QL_HEADER_SPACE) + ETHERNET_CRC_SIZE; + (qdev->lrg_buffer_len - QL_HEADER_SPACE) + ETHERNET_CRC_SIZE; /* * First allocate a page of shared memory and use it for shadow @@ -2984,51 +2868,44 @@ static int ql_alloc_mem_resources(struct ql3_adapter *qdev) * Network Completion Queue Producer Index Register */ qdev->shadow_reg_virt_addr = - pci_alloc_consistent(qdev->pdev, - PAGE_SIZE, &qdev->shadow_reg_phy_addr); + pci_alloc_consistent(qdev->pdev, + PAGE_SIZE, &qdev->shadow_reg_phy_addr); if (qdev->shadow_reg_virt_addr != NULL) { qdev->preq_consumer_index = (u16 *) qdev->shadow_reg_virt_addr; qdev->req_consumer_index_phy_addr_high = - MS_64BITS(qdev->shadow_reg_phy_addr); + MS_64BITS(qdev->shadow_reg_phy_addr); qdev->req_consumer_index_phy_addr_low = - LS_64BITS(qdev->shadow_reg_phy_addr); + LS_64BITS(qdev->shadow_reg_phy_addr); qdev->prsp_producer_index = - (__le32 *) (((u8 *) qdev->preq_consumer_index) + 8); + (__le32 *) (((u8 *) qdev->preq_consumer_index) + 8); qdev->rsp_producer_index_phy_addr_high = - qdev->req_consumer_index_phy_addr_high; + qdev->req_consumer_index_phy_addr_high; qdev->rsp_producer_index_phy_addr_low = - qdev->req_consumer_index_phy_addr_low + 8; + qdev->req_consumer_index_phy_addr_low + 8; } else { - printk(KERN_ERR PFX - "%s: shadowReg Alloc failed.\n", qdev->ndev->name); + netdev_err(qdev->ndev, "shadowReg Alloc failed\n"); return -ENOMEM; } if (ql_alloc_net_req_rsp_queues(qdev) != 0) { - printk(KERN_ERR PFX - "%s: ql_alloc_net_req_rsp_queues failed.\n", - qdev->ndev->name); + netdev_err(qdev->ndev, "ql_alloc_net_req_rsp_queues failed\n"); goto err_req_rsp; } if (ql_alloc_buffer_queues(qdev) != 0) { - printk(KERN_ERR PFX - "%s: ql_alloc_buffer_queues failed.\n", - qdev->ndev->name); + netdev_err(qdev->ndev, "ql_alloc_buffer_queues failed\n"); goto err_buffer_queues; } if (ql_alloc_small_buffers(qdev) != 0) { - printk(KERN_ERR PFX - "%s: ql_alloc_small_buffers failed\n", qdev->ndev->name); + netdev_err(qdev->ndev, "ql_alloc_small_buffers failed\n"); goto err_small_buffers; } if (ql_alloc_large_buffers(qdev) != 0) { - printk(KERN_ERR PFX - "%s: ql_alloc_large_buffers failed\n", qdev->ndev->name); + netdev_err(qdev->ndev, "ql_alloc_large_buffers failed\n"); goto err_small_buffers; } @@ -3076,7 +2953,7 @@ static int ql_init_misc_registers(struct ql3_adapter *qdev) struct ql3xxx_local_ram_registers __iomem *local_ram = (void __iomem *)qdev->mem_map_registers; - if(ql_sem_spinlock(qdev, QL_DDR_RAM_SEM_MASK, + if (ql_sem_spinlock(qdev, QL_DDR_RAM_SEM_MASK, (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) * 2) << 4)) return -1; @@ -3132,18 +3009,20 @@ static int ql_init_misc_registers(struct ql3_adapter *qdev) static int ql_adapter_initialize(struct ql3_adapter *qdev) { u32 value; - struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; + struct ql3xxx_port_registers __iomem *port_regs = + qdev->mem_map_registers; + u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg; struct ql3xxx_host_memory_registers __iomem *hmem_regs = - (void __iomem *)port_regs; + (void __iomem *)port_regs; u32 delay = 10; int status = 0; unsigned long hw_flags = 0; - if(ql_mii_setup(qdev)) + if (ql_mii_setup(qdev)) return -1; /* Bring out PHY out of reset */ - ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg, + ql_write_common_reg(qdev, spir, (ISP_SERIAL_PORT_IF_WE | (ISP_SERIAL_PORT_IF_WE << 16))); /* Give the PHY time to come out of reset. */ @@ -3152,13 +3031,13 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev) netif_carrier_off(qdev->ndev); /* V2 chip fix for ARS-39168. */ - ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg, + ql_write_common_reg(qdev, spir, (ISP_SERIAL_PORT_IF_SDE | (ISP_SERIAL_PORT_IF_SDE << 16))); /* Request Queue Registers */ - *((u32 *) (qdev->preq_consumer_index)) = 0; - atomic_set(&qdev->tx_count,NUM_REQ_Q_ENTRIES); + *((u32 *)(qdev->preq_consumer_index)) = 0; + atomic_set(&qdev->tx_count, NUM_REQ_Q_ENTRIES); qdev->req_producer_index = 0; ql_write_page1_reg(qdev, @@ -3208,7 +3087,9 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev) &hmem_regs->rxLargeQBaseAddrLow, LS_64BITS(qdev->lrg_buf_q_phy_addr)); - ql_write_page1_reg(qdev, &hmem_regs->rxLargeQLength, qdev->num_lbufq_entries); + ql_write_page1_reg(qdev, + &hmem_regs->rxLargeQLength, + qdev->num_lbufq_entries); ql_write_page1_reg(qdev, &hmem_regs->rxLargeBufferLength, @@ -3258,7 +3139,7 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev) if ((value & PORT_STATUS_IC) == 0) { /* Chip has not been configured yet, so let it rip. */ - if(ql_init_misc_registers(qdev)) { + if (ql_init_misc_registers(qdev)) { status = -1; goto out; } @@ -3268,7 +3149,7 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev) value = (0xFFFF << 16) | qdev->nvram_data.extHwConfig; - if(ql_sem_spinlock(qdev, QL_FLASH_SEM_MASK, + if (ql_sem_spinlock(qdev, QL_FLASH_SEM_MASK, (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) * 2) << 13)) { status = -1; @@ -3291,7 +3172,7 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev) &port_regs->mac0MaxFrameLengthReg, qdev->max_frame_size); - if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK, + if (ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK, (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) * 2) << 7)) { status = -1; @@ -3353,8 +3234,7 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev) } while (--delay); if (delay == 0) { - printk(KERN_ERR PFX - "%s: Hw Initialization timeout.\n", qdev->ndev->name); + netdev_err(qdev->ndev, "Hw Initialization timeout\n"); status = -1; goto out; } @@ -3385,7 +3265,8 @@ out: */ static int ql_adapter_reset(struct ql3_adapter *qdev) { - struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; + struct ql3xxx_port_registers __iomem *port_regs = + qdev->mem_map_registers; int status = 0; u16 value; int max_wait_time; @@ -3396,17 +3277,14 @@ static int ql_adapter_reset(struct ql3_adapter *qdev) /* * Issue soft reset to chip. */ - printk(KERN_DEBUG PFX - "%s: Issue soft reset to chip.\n", - qdev->ndev->name); + netdev_printk(KERN_DEBUG, qdev->ndev, "Issue soft reset to chip\n"); ql_write_common_reg(qdev, &port_regs->CommonRegs.ispControlStatus, ((ISP_CONTROL_SR << 16) | ISP_CONTROL_SR)); /* Wait 3 seconds for reset to complete. */ - printk(KERN_DEBUG PFX - "%s: Wait 10 milliseconds for reset to complete.\n", - qdev->ndev->name); + netdev_printk(KERN_DEBUG, qdev->ndev, + "Wait 10 milliseconds for reset to complete\n"); /* Wait until the firmware tells us the Soft Reset is done */ max_wait_time = 5; @@ -3427,8 +3305,8 @@ static int ql_adapter_reset(struct ql3_adapter *qdev) value = ql_read_common_reg(qdev, &port_regs->CommonRegs.ispControlStatus); if (value & ISP_CONTROL_RI) { - printk(KERN_DEBUG PFX - "ql_adapter_reset: clearing RI after reset.\n"); + netdev_printk(KERN_DEBUG, qdev->ndev, + "clearing RI after reset\n"); ql_write_common_reg(qdev, &port_regs->CommonRegs. ispControlStatus, @@ -3448,13 +3326,11 @@ static int ql_adapter_reset(struct ql3_adapter *qdev) */ max_wait_time = 5; do { - value = - ql_read_common_reg(qdev, - &port_regs->CommonRegs. - ispControlStatus); - if ((value & ISP_CONTROL_FSR) == 0) { + value = ql_read_common_reg(qdev, + &port_regs->CommonRegs. + ispControlStatus); + if ((value & ISP_CONTROL_FSR) == 0) break; - } ssleep(1); } while ((--max_wait_time)); } @@ -3468,7 +3344,8 @@ static int ql_adapter_reset(struct ql3_adapter *qdev) static void ql_set_mac_info(struct ql3_adapter *qdev) { - struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; + struct ql3xxx_port_registers __iomem *port_regs = + qdev->mem_map_registers; u32 value, port_status; u8 func_number; @@ -3484,9 +3361,9 @@ static void ql_set_mac_info(struct ql3_adapter *qdev) qdev->mb_bit_mask = FN0_MA_BITS_MASK; qdev->PHYAddr = PORT0_PHY_ADDRESS; if (port_status & PORT_STATUS_SM0) - set_bit(QL_LINK_OPTICAL,&qdev->flags); + set_bit(QL_LINK_OPTICAL, &qdev->flags); else - clear_bit(QL_LINK_OPTICAL,&qdev->flags); + clear_bit(QL_LINK_OPTICAL, &qdev->flags); break; case ISP_CONTROL_FN1_NET: @@ -3495,17 +3372,17 @@ static void ql_set_mac_info(struct ql3_adapter *qdev) qdev->mb_bit_mask = FN1_MA_BITS_MASK; qdev->PHYAddr = PORT1_PHY_ADDRESS; if (port_status & PORT_STATUS_SM1) - set_bit(QL_LINK_OPTICAL,&qdev->flags); + set_bit(QL_LINK_OPTICAL, &qdev->flags); else - clear_bit(QL_LINK_OPTICAL,&qdev->flags); + clear_bit(QL_LINK_OPTICAL, &qdev->flags); break; case ISP_CONTROL_FN0_SCSI: case ISP_CONTROL_FN1_SCSI: default: - printk(KERN_DEBUG PFX - "%s: Invalid function number, ispControlStatus = 0x%x\n", - qdev->ndev->name,value); + netdev_printk(KERN_DEBUG, qdev->ndev, + "Invalid function number, ispControlStatus = 0x%x\n", + value); break; } qdev->numPorts = qdev->nvram_data.version_and_numPorts >> 8; @@ -3516,32 +3393,26 @@ static void ql_display_dev_info(struct net_device *ndev) struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev); struct pci_dev *pdev = qdev->pdev; - printk(KERN_INFO PFX - "\n%s Adapter %d RevisionID %d found %s on PCI slot %d.\n", - DRV_NAME, qdev->index, qdev->chip_rev_id, - (qdev->device_id == QL3032_DEVICE_ID) ? "QLA3032" : "QLA3022", - qdev->pci_slot); - printk(KERN_INFO PFX - "%s Interface.\n", - test_bit(QL_LINK_OPTICAL,&qdev->flags) ? "OPTICAL" : "COPPER"); + netdev_info(ndev, + "%s Adapter %d RevisionID %d found %s on PCI slot %d\n", + DRV_NAME, qdev->index, qdev->chip_rev_id, + qdev->device_id == QL3032_DEVICE_ID ? "QLA3032" : "QLA3022", + qdev->pci_slot); + netdev_info(ndev, "%s Interface\n", + test_bit(QL_LINK_OPTICAL, &qdev->flags) ? "OPTICAL" : "COPPER"); /* * Print PCI bus width/type. */ - printk(KERN_INFO PFX - "Bus interface is %s %s.\n", - ((qdev->pci_width == 64) ? "64-bit" : "32-bit"), - ((qdev->pci_x) ? "PCI-X" : "PCI")); + netdev_info(ndev, "Bus interface is %s %s\n", + ((qdev->pci_width == 64) ? "64-bit" : "32-bit"), + ((qdev->pci_x) ? "PCI-X" : "PCI")); - printk(KERN_INFO PFX - "mem IO base address adjusted = 0x%p\n", - qdev->mem_map_registers); - printk(KERN_INFO PFX "Interrupt number = %d\n", pdev->irq); + netdev_info(ndev, "mem IO base address adjusted = 0x%p\n", + qdev->mem_map_registers); + netdev_info(ndev, "Interrupt number = %d\n", pdev->irq); - if (netif_msg_probe(qdev)) - printk(KERN_INFO PFX - "%s: MAC address %pM\n", - ndev->name, ndev->dev_addr); + netif_info(qdev, probe, ndev, "MAC address %pM\n", ndev->dev_addr); } static int ql_adapter_down(struct ql3_adapter *qdev, int do_reset) @@ -3552,17 +3423,16 @@ static int ql_adapter_down(struct ql3_adapter *qdev, int do_reset) netif_stop_queue(ndev); netif_carrier_off(ndev); - clear_bit(QL_ADAPTER_UP,&qdev->flags); - clear_bit(QL_LINK_MASTER,&qdev->flags); + clear_bit(QL_ADAPTER_UP, &qdev->flags); + clear_bit(QL_LINK_MASTER, &qdev->flags); ql_disable_interrupts(qdev); free_irq(qdev->pdev->irq, ndev); - if (qdev->msi && test_bit(QL_MSI_ENABLED,&qdev->flags)) { - printk(KERN_INFO PFX - "%s: calling pci_disable_msi().\n", qdev->ndev->name); - clear_bit(QL_MSI_ENABLED,&qdev->flags); + if (qdev->msi && test_bit(QL_MSI_ENABLED, &qdev->flags)) { + netdev_info(qdev->ndev, "calling pci_disable_msi()\n"); + clear_bit(QL_MSI_ENABLED, &qdev->flags); pci_disable_msi(qdev->pdev); } @@ -3576,17 +3446,16 @@ static int ql_adapter_down(struct ql3_adapter *qdev, int do_reset) spin_lock_irqsave(&qdev->hw_lock, hw_flags); if (ql_wait_for_drvr_lock(qdev)) { - if ((soft_reset = ql_adapter_reset(qdev))) { - printk(KERN_ERR PFX - "%s: ql_adapter_reset(%d) FAILED!\n", - ndev->name, qdev->index); + soft_reset = ql_adapter_reset(qdev); + if (soft_reset) { + netdev_err(ndev, "ql_adapter_reset(%d) FAILED!\n", + qdev->index); } - printk(KERN_ERR PFX - "%s: Releaseing driver lock via chip reset.\n",ndev->name); + netdev_err(ndev, + "Releasing driver lock via chip reset\n"); } else { - printk(KERN_ERR PFX - "%s: Could not acquire driver lock to do " - "reset!\n", ndev->name); + netdev_err(ndev, + "Could not acquire driver lock to do reset!\n"); retval = -1; } spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); @@ -3603,56 +3472,50 @@ static int ql_adapter_up(struct ql3_adapter *qdev) unsigned long hw_flags; if (ql_alloc_mem_resources(qdev)) { - printk(KERN_ERR PFX - "%s Unable to allocate buffers.\n", ndev->name); + netdev_err(ndev, "Unable to allocate buffers\n"); return -ENOMEM; } if (qdev->msi) { if (pci_enable_msi(qdev->pdev)) { - printk(KERN_ERR PFX - "%s: User requested MSI, but MSI failed to " - "initialize. Continuing without MSI.\n", - qdev->ndev->name); + netdev_err(ndev, + "User requested MSI, but MSI failed to initialize. Continuing without MSI.\n"); qdev->msi = 0; } else { - printk(KERN_INFO PFX "%s: MSI Enabled...\n", qdev->ndev->name); - set_bit(QL_MSI_ENABLED,&qdev->flags); + netdev_info(ndev, "MSI Enabled...\n"); + set_bit(QL_MSI_ENABLED, &qdev->flags); irq_flags &= ~IRQF_SHARED; } } - if ((err = request_irq(qdev->pdev->irq, - ql3xxx_isr, - irq_flags, ndev->name, ndev))) { - printk(KERN_ERR PFX - "%s: Failed to reserve interrupt %d already in use.\n", - ndev->name, qdev->pdev->irq); + err = request_irq(qdev->pdev->irq, ql3xxx_isr, + irq_flags, ndev->name, ndev); + if (err) { + netdev_err(ndev, + "Failed to reserve interrupt %d - already in use\n", + qdev->pdev->irq); goto err_irq; } spin_lock_irqsave(&qdev->hw_lock, hw_flags); - if ((err = ql_wait_for_drvr_lock(qdev))) { - if ((err = ql_adapter_initialize(qdev))) { - printk(KERN_ERR PFX - "%s: Unable to initialize adapter.\n", - ndev->name); + err = ql_wait_for_drvr_lock(qdev); + if (err) { + err = ql_adapter_initialize(qdev); + if (err) { + netdev_err(ndev, "Unable to initialize adapter\n"); goto err_init; } - printk(KERN_ERR PFX - "%s: Releaseing driver lock.\n",ndev->name); + netdev_err(ndev, "Releasing driver lock\n"); ql_sem_unlock(qdev, QL_DRVR_SEM_MASK); } else { - printk(KERN_ERR PFX - "%s: Could not acquire driver lock.\n", - ndev->name); + netdev_err(ndev, "Could not acquire driver lock\n"); goto err_lock; } spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); - set_bit(QL_ADAPTER_UP,&qdev->flags); + set_bit(QL_ADAPTER_UP, &qdev->flags); mod_timer(&qdev->adapter_timer, jiffies + HZ * 1); @@ -3666,11 +3529,9 @@ err_lock: spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); free_irq(qdev->pdev->irq, ndev); err_irq: - if (qdev->msi && test_bit(QL_MSI_ENABLED,&qdev->flags)) { - printk(KERN_INFO PFX - "%s: calling pci_disable_msi().\n", - qdev->ndev->name); - clear_bit(QL_MSI_ENABLED,&qdev->flags); + if (qdev->msi && test_bit(QL_MSI_ENABLED, &qdev->flags)) { + netdev_info(ndev, "calling pci_disable_msi()\n"); + clear_bit(QL_MSI_ENABLED, &qdev->flags); pci_disable_msi(qdev->pdev); } return err; @@ -3678,10 +3539,9 @@ err_irq: static int ql_cycle_adapter(struct ql3_adapter *qdev, int reset) { - if( ql_adapter_down(qdev,reset) || ql_adapter_up(qdev)) { - printk(KERN_ERR PFX - "%s: Driver up/down cycle failed, " - "closing device\n",qdev->ndev->name); + if (ql_adapter_down(qdev, reset) || ql_adapter_up(qdev)) { + netdev_err(qdev->ndev, + "Driver up/down cycle failed, closing device\n"); rtnl_lock(); dev_close(qdev->ndev); rtnl_unlock(); @@ -3698,24 +3558,24 @@ static int ql3xxx_close(struct net_device *ndev) * Wait for device to recover from a reset. * (Rarely happens, but possible.) */ - while (!test_bit(QL_ADAPTER_UP,&qdev->flags)) + while (!test_bit(QL_ADAPTER_UP, &qdev->flags)) msleep(50); - ql_adapter_down(qdev,QL_DO_RESET); + ql_adapter_down(qdev, QL_DO_RESET); return 0; } static int ql3xxx_open(struct net_device *ndev) { struct ql3_adapter *qdev = netdev_priv(ndev); - return (ql_adapter_up(qdev)); + return ql_adapter_up(qdev); } static int ql3xxx_set_mac_address(struct net_device *ndev, void *p) { struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev); struct ql3xxx_port_registers __iomem *port_regs = - qdev->mem_map_registers; + qdev->mem_map_registers; struct sockaddr *addr = p; unsigned long hw_flags; @@ -3750,7 +3610,7 @@ static void ql3xxx_tx_timeout(struct net_device *ndev) { struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev); - printk(KERN_ERR PFX "%s: Resetting...\n", ndev->name); + netdev_err(ndev, "Resetting...\n"); /* * Stop the queues, we've got a problem. */ @@ -3770,11 +3630,12 @@ static void ql_reset_work(struct work_struct *work) u32 value; struct ql_tx_buf_cb *tx_cb; int max_wait_time, i; - struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; + struct ql3xxx_port_registers __iomem *port_regs = + qdev->mem_map_registers; unsigned long hw_flags; - if (test_bit((QL_RESET_PER_SCSI | QL_RESET_START),&qdev->flags)) { - clear_bit(QL_LINK_MASTER,&qdev->flags); + if (test_bit((QL_RESET_PER_SCSI | QL_RESET_START), &qdev->flags)) { + clear_bit(QL_LINK_MASTER, &qdev->flags); /* * Loop through the active list and return the skb. @@ -3783,17 +3644,19 @@ static void ql_reset_work(struct work_struct *work) int j; tx_cb = &qdev->tx_buf[i]; if (tx_cb->skb) { - printk(KERN_DEBUG PFX - "%s: Freeing lost SKB.\n", - qdev->ndev->name); + netdev_printk(KERN_DEBUG, ndev, + "Freeing lost SKB\n"); pci_unmap_single(qdev->pdev, - dma_unmap_addr(&tx_cb->map[0], mapaddr), + dma_unmap_addr(&tx_cb->map[0], + mapaddr), dma_unmap_len(&tx_cb->map[0], maplen), PCI_DMA_TODEVICE); - for(j=1;j<tx_cb->seg_count;j++) { + for (j = 1; j < tx_cb->seg_count; j++) { pci_unmap_page(qdev->pdev, - dma_unmap_addr(&tx_cb->map[j],mapaddr), - dma_unmap_len(&tx_cb->map[j],maplen), + dma_unmap_addr(&tx_cb->map[j], + mapaddr), + dma_unmap_len(&tx_cb->map[j], + maplen), PCI_DMA_TODEVICE); } dev_kfree_skb(tx_cb->skb); @@ -3801,8 +3664,7 @@ static void ql_reset_work(struct work_struct *work) } } - printk(KERN_ERR PFX - "%s: Clearing NRI after reset.\n", qdev->ndev->name); + netdev_err(ndev, "Clearing NRI after reset\n"); spin_lock_irqsave(&qdev->hw_lock, hw_flags); ql_write_common_reg(qdev, &port_regs->CommonRegs. @@ -3818,16 +3680,14 @@ static void ql_reset_work(struct work_struct *work) ispControlStatus); if ((value & ISP_CONTROL_SR) == 0) { - printk(KERN_DEBUG PFX - "%s: reset completed.\n", - qdev->ndev->name); + netdev_printk(KERN_DEBUG, ndev, + "reset completed\n"); break; } if (value & ISP_CONTROL_RI) { - printk(KERN_DEBUG PFX - "%s: clearing NRI after reset.\n", - qdev->ndev->name); + netdev_printk(KERN_DEBUG, ndev, + "clearing NRI after reset\n"); ql_write_common_reg(qdev, &port_regs-> CommonRegs. @@ -3848,21 +3708,19 @@ static void ql_reset_work(struct work_struct *work) * Set the reset flags and clear the board again. * Nothing else to do... */ - printk(KERN_ERR PFX - "%s: Timed out waiting for reset to " - "complete.\n", ndev->name); - printk(KERN_ERR PFX - "%s: Do a reset.\n", ndev->name); - clear_bit(QL_RESET_PER_SCSI,&qdev->flags); - clear_bit(QL_RESET_START,&qdev->flags); - ql_cycle_adapter(qdev,QL_DO_RESET); + netdev_err(ndev, + "Timed out waiting for reset to complete\n"); + netdev_err(ndev, "Do a reset\n"); + clear_bit(QL_RESET_PER_SCSI, &qdev->flags); + clear_bit(QL_RESET_START, &qdev->flags); + ql_cycle_adapter(qdev, QL_DO_RESET); return; } - clear_bit(QL_RESET_ACTIVE,&qdev->flags); - clear_bit(QL_RESET_PER_SCSI,&qdev->flags); - clear_bit(QL_RESET_START,&qdev->flags); - ql_cycle_adapter(qdev,QL_NO_RESET); + clear_bit(QL_RESET_ACTIVE, &qdev->flags); + clear_bit(QL_RESET_PER_SCSI, &qdev->flags); + clear_bit(QL_RESET_START, &qdev->flags); + ql_cycle_adapter(qdev, QL_NO_RESET); } } @@ -3876,7 +3734,8 @@ static void ql_tx_timeout_work(struct work_struct *work) static void ql_get_board_info(struct ql3_adapter *qdev) { - struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; + struct ql3xxx_port_registers __iomem *port_regs = + qdev->mem_map_registers; u32 value; value = ql_read_page0_reg_l(qdev, &port_regs->portStatus); @@ -3915,20 +3774,18 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev, { struct net_device *ndev = NULL; struct ql3_adapter *qdev = NULL; - static int cards_found = 0; + static int cards_found; int uninitialized_var(pci_using_dac), err; err = pci_enable_device(pdev); if (err) { - printk(KERN_ERR PFX "%s cannot enable PCI device\n", - pci_name(pdev)); + pr_err("%s cannot enable PCI device\n", pci_name(pdev)); goto err_out; } err = pci_request_regions(pdev, DRV_NAME); if (err) { - printk(KERN_ERR PFX "%s cannot obtain PCI resources\n", - pci_name(pdev)); + pr_err("%s cannot obtain PCI resources\n", pci_name(pdev)); goto err_out_disable_pdev; } @@ -3943,15 +3800,13 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev, } if (err) { - printk(KERN_ERR PFX "%s no usable DMA configuration\n", - pci_name(pdev)); + pr_err("%s no usable DMA configuration\n", pci_name(pdev)); goto err_out_free_regions; } ndev = alloc_etherdev(sizeof(struct ql3_adapter)); if (!ndev) { - printk(KERN_ERR PFX "%s could not alloc etherdev\n", - pci_name(pdev)); + pr_err("%s could not alloc etherdev\n", pci_name(pdev)); err = -ENOMEM; goto err_out_free_regions; } @@ -3978,8 +3833,7 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev, qdev->mem_map_registers = pci_ioremap_bar(pdev, 1); if (!qdev->mem_map_registers) { - printk(KERN_ERR PFX "%s: cannot map device registers\n", - pci_name(pdev)); + pr_err("%s: cannot map device registers\n", pci_name(pdev)); err = -EIO; goto err_out_free_ndev; } @@ -3998,9 +3852,8 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev, /* make sure the EEPROM is good */ if (ql_get_nvram_params(qdev)) { - printk(KERN_ALERT PFX - "ql3xxx_probe: Adapter #%d, Invalid NVRAM parameters.\n", - qdev->index); + pr_alert("%s: Adapter #%d, Invalid NVRAM parameters\n", + __func__, qdev->index); err = -EIO; goto err_out_iounmap; } @@ -4026,14 +3879,12 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev, * Set the Maximum Memory Read Byte Count value. We do this to handle * jumbo frames. */ - if (qdev->pci_x) { + if (qdev->pci_x) pci_write_config_word(pdev, (int)0x4e, (u16) 0x0036); - } err = register_netdev(ndev); if (err) { - printk(KERN_ERR PFX "%s: cannot register net device\n", - pci_name(pdev)); + pr_err("%s: cannot register net device\n", pci_name(pdev)); goto err_out_iounmap; } @@ -4052,10 +3903,10 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev, qdev->adapter_timer.expires = jiffies + HZ * 2; /* two second delay */ qdev->adapter_timer.data = (unsigned long)qdev; - if(!cards_found) { - printk(KERN_ALERT PFX "%s\n", DRV_STRING); - printk(KERN_ALERT PFX "Driver name: %s, Version: %s.\n", - DRV_NAME, DRV_VERSION); + if (!cards_found) { + pr_alert("%s\n", DRV_STRING); + pr_alert("Driver name: %s, Version: %s\n", + DRV_NAME, DRV_VERSION); } ql_display_dev_info(ndev); diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index e1894775e5a..970389331bb 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -1074,8 +1074,8 @@ struct qlcnic_eswitch { /* Return codes for Error handling */ #define QL_STATUS_INVALID_PARAM -1 -#define MAX_BW 10000 -#define MIN_BW 100 +#define MAX_BW 100 +#define MIN_BW 1 #define MAX_VLAN_ID 4095 #define MIN_VLAN_ID 2 #define MAX_TX_QUEUES 1 @@ -1083,8 +1083,7 @@ struct qlcnic_eswitch { #define DEFAULT_MAC_LEARN 1 #define IS_VALID_VLAN(vlan) (vlan >= MIN_VLAN_ID && vlan <= MAX_VLAN_ID) -#define IS_VALID_BW(bw) (bw >= MIN_BW && bw <= MAX_BW \ - && (bw % 100) == 0) +#define IS_VALID_BW(bw) (bw >= MIN_BW && bw <= MAX_BW) #define IS_VALID_TX_QUEUES(que) (que > 0 && que <= MAX_TX_QUEUES) #define IS_VALID_RX_QUEUES(que) (que > 0 && que <= MAX_RX_QUEUES) #define IS_VALID_MODE(mode) (mode == 0 || mode == 1) @@ -1302,8 +1301,6 @@ struct qlcnic_nic_template { int (*get_mac_addr) (struct qlcnic_adapter *, u8*); int (*config_bridged_mode) (struct qlcnic_adapter *, u32); int (*config_led) (struct qlcnic_adapter *, u32, u32); - int (*set_ilb_mode) (struct qlcnic_adapter *); - void (*clear_ilb_mode) (struct qlcnic_adapter *); int (*start_firmware) (struct qlcnic_adapter *); }; diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 7d6558e33dc..9328d59e21e 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -678,6 +678,12 @@ static int qlcnic_loopback_test(struct net_device *netdev) int max_sds_rings = adapter->max_sds_rings; int ret; + if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) { + dev_warn(&adapter->pdev->dev, "Loopback test not supported" + "for non privilege function\n"); + return 0; + } + if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) return -EIO; @@ -685,13 +691,13 @@ static int qlcnic_loopback_test(struct net_device *netdev) if (ret) goto clear_it; - ret = adapter->nic_ops->set_ilb_mode(adapter); + ret = qlcnic_set_ilb_mode(adapter); if (ret) goto done; ret = qlcnic_do_ilb_test(adapter); - adapter->nic_ops->clear_ilb_mode(adapter); + qlcnic_clear_ilb_mode(adapter); done: qlcnic_diag_free_res(netdev, max_sds_rings); diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index f1f7acfbf41..b9615bd745e 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -107,8 +107,6 @@ static void qlcnic_config_indev_addr(struct net_device *dev, unsigned long); static int qlcnic_start_firmware(struct qlcnic_adapter *); static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *); -static void qlcnicvf_clear_ilb_mode(struct qlcnic_adapter *); -static int qlcnicvf_set_ilb_mode(struct qlcnic_adapter *); static int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32); static int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32); static int qlcnicvf_start_firmware(struct qlcnic_adapter *); @@ -381,8 +379,6 @@ static struct qlcnic_nic_template qlcnic_ops = { .get_mac_addr = qlcnic_get_mac_address, .config_bridged_mode = qlcnic_config_bridged_mode, .config_led = qlcnic_config_led, - .set_ilb_mode = qlcnic_set_ilb_mode, - .clear_ilb_mode = qlcnic_clear_ilb_mode, .start_firmware = qlcnic_start_firmware }; @@ -390,8 +386,6 @@ static struct qlcnic_nic_template qlcnic_vf_ops = { .get_mac_addr = qlcnic_get_mac_address, .config_bridged_mode = qlcnicvf_config_bridged_mode, .config_led = qlcnicvf_config_led, - .set_ilb_mode = qlcnicvf_set_ilb_mode, - .clear_ilb_mode = qlcnicvf_clear_ilb_mode, .start_firmware = qlcnicvf_start_firmware }; @@ -1182,6 +1176,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test) ret = qlcnic_fw_create_ctx(adapter); if (ret) { qlcnic_detach(adapter); + netif_device_attach(netdev); return ret; } @@ -2841,18 +2836,6 @@ qlcnicvf_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate) return -EOPNOTSUPP; } -static int -qlcnicvf_set_ilb_mode(struct qlcnic_adapter *adapter) -{ - return -EOPNOTSUPP; -} - -static void -qlcnicvf_clear_ilb_mode(struct qlcnic_adapter *adapter) -{ - return; -} - static ssize_t qlcnic_store_bridged_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index b8b85843c61..18bc5b718bb 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -5796,7 +5796,7 @@ static void s2io_vpd_read(struct s2io_nic *nic) { u8 *vpd_data; u8 data; - int i = 0, cnt, fail = 0; + int i = 0, cnt, len, fail = 0; int vpd_addr = 0x80; struct swStat *swstats = &nic->mac_control.stats_info->sw_stat; @@ -5837,20 +5837,28 @@ static void s2io_vpd_read(struct s2io_nic *nic) if (!fail) { /* read serial number of adapter */ - for (cnt = 0; cnt < 256; cnt++) { + for (cnt = 0; cnt < 252; cnt++) { if ((vpd_data[cnt] == 'S') && - (vpd_data[cnt+1] == 'N') && - (vpd_data[cnt+2] < VPD_STRING_LEN)) { - memset(nic->serial_num, 0, VPD_STRING_LEN); - memcpy(nic->serial_num, &vpd_data[cnt + 3], - vpd_data[cnt+2]); - break; + (vpd_data[cnt+1] == 'N')) { + len = vpd_data[cnt+2]; + if (len < min(VPD_STRING_LEN, 256-cnt-2)) { + memcpy(nic->serial_num, + &vpd_data[cnt + 3], + len); + memset(nic->serial_num+len, + 0, + VPD_STRING_LEN-len); + break; + } } } } - if ((!fail) && (vpd_data[1] < VPD_STRING_LEN)) - memcpy(nic->product_name, &vpd_data[3], vpd_data[1]); + if ((!fail) && (vpd_data[1] < VPD_STRING_LEN)) { + len = vpd_data[1]; + memcpy(nic->product_name, &vpd_data[3], len); + nic->product_name[len] = 0; + } kfree(vpd_data); swstats->mem_freed += 256; } diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 3645fb3673d..0af03353390 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -65,7 +65,7 @@ static int debug_level = ERR_DBG; /* DEBUG message print. */ #define DBG_PRINT(dbg_level, fmt, args...) do { \ - if (dbg_level >= debug_level) \ + if (dbg_level <= debug_level) \ pr_info(fmt, ##args); \ } while (0) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index c762c6ac055..194e5cf8c76 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -79,7 +79,7 @@ #define SKY2_EEPROM_MAGIC 0x9955aabb -#define RING_NEXT(x,s) (((x)+1) & ((s)-1)) +#define RING_NEXT(x, s) (((x)+1) & ((s)-1)) static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK @@ -172,7 +172,7 @@ static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val) udelay(10); } - dev_warn(&hw->pdev->dev,"%s: phy write timeout\n", hw->dev[port]->name); + dev_warn(&hw->pdev->dev, "%s: phy write timeout\n", hw->dev[port]->name); return -ETIMEDOUT; io_error: @@ -1067,7 +1067,7 @@ static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2) return le; } -static unsigned sky2_get_rx_threshold(struct sky2_port* sky2) +static unsigned sky2_get_rx_threshold(struct sky2_port *sky2) { unsigned size; @@ -1078,7 +1078,7 @@ static unsigned sky2_get_rx_threshold(struct sky2_port* sky2) return (size - 8) / sizeof(u32); } -static unsigned sky2_get_rx_data_size(struct sky2_port* sky2) +static unsigned sky2_get_rx_data_size(struct sky2_port *sky2) { struct rx_ring_info *re; unsigned size; @@ -1102,7 +1102,7 @@ static unsigned sky2_get_rx_data_size(struct sky2_port* sky2) } /* Build description to hardware for one receive segment */ -static void sky2_rx_add(struct sky2_port *sky2, u8 op, +static void sky2_rx_add(struct sky2_port *sky2, u8 op, dma_addr_t map, unsigned len) { struct sky2_rx_le *le; @@ -3014,7 +3014,7 @@ static int __devinit sky2_init(struct sky2_hw *hw) hw->chip_id = sky2_read8(hw, B2_CHIP_ID); hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; - switch(hw->chip_id) { + switch (hw->chip_id) { case CHIP_ID_YUKON_XL: hw->flags = SKY2_HW_GIGABIT | SKY2_HW_NEWER_PHY; if (hw->chip_rev < CHIP_REV_YU_XL_A2) @@ -3685,7 +3685,7 @@ static int sky2_set_mac_address(struct net_device *dev, void *p) return 0; } -static void inline sky2_add_filter(u8 filter[8], const u8 *addr) +static inline void sky2_add_filter(u8 filter[8], const u8 *addr) { u32 bit; @@ -3911,7 +3911,7 @@ static int sky2_set_coalesce(struct net_device *dev, return -EINVAL; if (ecmd->rx_max_coalesced_frames > RX_MAX_PENDING) return -EINVAL; - if (ecmd->rx_max_coalesced_frames_irq >RX_MAX_PENDING) + if (ecmd->rx_max_coalesced_frames_irq > RX_MAX_PENDING) return -EINVAL; if (ecmd->tx_coalesce_usecs == 0) @@ -4372,7 +4372,7 @@ static int sky2_debug_show(struct seq_file *seq, void *v) seq_printf(seq, "%u:", idx); sop = 0; - switch(le->opcode & ~HW_OWNER) { + switch (le->opcode & ~HW_OWNER) { case OP_ADDR64: seq_printf(seq, " %#x:", a); break; @@ -4441,7 +4441,7 @@ static int sky2_device_event(struct notifier_block *unused, if (dev->netdev_ops->ndo_open != sky2_up || !sky2_debug) return NOTIFY_DONE; - switch(event) { + switch (event) { case NETDEV_CHANGENAME: if (sky2->debugfs) { sky2->debugfs = debugfs_rename(sky2_debug, sky2->debugfs, @@ -4636,7 +4636,7 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw) struct pci_dev *pdev = hw->pdev; int err; - init_waitqueue_head (&hw->msi_wait); + init_waitqueue_head(&hw->msi_wait); sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW); @@ -4753,7 +4753,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev, * this driver uses software swapping. */ reg &= ~PCI_REV_DESC; - err = pci_write_config_dword(pdev,PCI_DEV_REG2, reg); + err = pci_write_config_dword(pdev, PCI_DEV_REG2, reg); if (err) { dev_err(&pdev->dev, "PCI write config failed\n"); goto err_out_free_regions; diff --git a/drivers/net/stmmac/common.h b/drivers/net/stmmac/common.h index 144f76fd3e3..66b9da0260f 100644 --- a/drivers/net/stmmac/common.h +++ b/drivers/net/stmmac/common.h @@ -108,6 +108,7 @@ enum rx_frame_status { /* IPC status */ good_frame = 0, discard_frame = 1, csum_none = 2, + llc_snap = 4, }; enum tx_dma_irq_status { diff --git a/drivers/net/stmmac/dwmac1000.h b/drivers/net/stmmac/dwmac1000.h index d8d0f355377..8b20b19971c 100644 --- a/drivers/net/stmmac/dwmac1000.h +++ b/drivers/net/stmmac/dwmac1000.h @@ -93,7 +93,7 @@ enum inter_frame_gap { #define GMAC_CONTROL_IPC 0x00000400 /* Checksum Offload */ #define GMAC_CONTROL_DR 0x00000200 /* Disable Retry */ #define GMAC_CONTROL_LUD 0x00000100 /* Link up/down */ -#define GMAC_CONTROL_ACS 0x00000080 /* Automatic Pad Stripping */ +#define GMAC_CONTROL_ACS 0x00000080 /* Automatic Pad/FCS Stripping */ #define GMAC_CONTROL_DC 0x00000010 /* Deferral Check */ #define GMAC_CONTROL_TE 0x00000008 /* Transmitter Enable */ #define GMAC_CONTROL_RE 0x00000004 /* Receiver Enable */ diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c index 917b4e16923..2b2f5c8caf1 100644 --- a/drivers/net/stmmac/dwmac1000_core.c +++ b/drivers/net/stmmac/dwmac1000_core.c @@ -220,6 +220,8 @@ struct mac_device_info *dwmac1000_setup(unsigned long ioaddr) ((uid & 0x0000ff00) >> 8), (uid & 0x000000ff)); mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL); + if (!mac) + return NULL; mac->mac = &dwmac1000_ops; mac->dma = &dwmac1000_dma_ops; diff --git a/drivers/net/stmmac/dwmac100_core.c b/drivers/net/stmmac/dwmac100_core.c index 6f270a0e151..2fb165fa2ba 100644 --- a/drivers/net/stmmac/dwmac100_core.c +++ b/drivers/net/stmmac/dwmac100_core.c @@ -179,6 +179,8 @@ struct mac_device_info *dwmac100_setup(unsigned long ioaddr) struct mac_device_info *mac; mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL); + if (!mac) + return NULL; pr_info("\tDWMAC100\n"); diff --git a/drivers/net/stmmac/enh_desc.c b/drivers/net/stmmac/enh_desc.c index 3c18ebece04..f612f986a7e 100644 --- a/drivers/net/stmmac/enh_desc.c +++ b/drivers/net/stmmac/enh_desc.c @@ -123,7 +123,7 @@ static int enh_desc_coe_rdes0(int ipc_err, int type, int payload_err) */ if (status == 0x0) { CHIP_DBG(KERN_INFO "RX Des0 status: IEEE 802.3 Type frame.\n"); - ret = good_frame; + ret = llc_snap; } else if (status == 0x4) { CHIP_DBG(KERN_INFO "RX Des0 status: IPv4/6 No CSUM errorS.\n"); ret = good_frame; diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index acf06168694..bbb7951b9c4 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -829,7 +829,6 @@ static int stmmac_open(struct net_device *dev) * In case of failure continue without timer. */ if (unlikely((stmmac_open_ext_timer(dev, priv->tm)) < 0)) { pr_warning("stmmaceth: cannot attach the external timer.\n"); - tmrate = 0; priv->tm->freq = 0; priv->tm->timer_start = stmmac_no_timer_started; priv->tm->timer_stop = stmmac_no_timer_stopped; @@ -1217,9 +1216,13 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit) priv->dev->stats.rx_errors++; else { struct sk_buff *skb; - /* Length should omit the CRC */ - int frame_len = priv->hw->desc->get_rx_frame_len(p) - 4; + int frame_len; + frame_len = priv->hw->desc->get_rx_frame_len(p); + /* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3 + * Type frames (LLC/LLC-SNAP) */ + if (unlikely(status != llc_snap)) + frame_len -= ETH_FCS_LEN; #ifdef STMMAC_RX_DEBUG if (frame_len > ETH_FRAME_LEN) pr_debug("\tRX frame size %d, COE status: %d\n", @@ -1558,15 +1561,15 @@ static int stmmac_mac_device_setup(struct net_device *dev) else device = dwmac100_setup(ioaddr); + if (!device) + return -ENOMEM; + if (priv->enh_desc) { device->desc = &enh_desc_ops; pr_info("\tEnhanced descriptor structure\n"); } else device->desc = &ndesc_ops; - if (!device) - return -ENOMEM; - priv->hw = device; priv->wolenabled = priv->hw->pmt; /* PMT supported */ diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index b26a5778293..bc3af78a869 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -69,10 +69,10 @@ #define DRV_MODULE_NAME "tg3" #define TG3_MAJ_NUM 3 -#define TG3_MIN_NUM 112 +#define TG3_MIN_NUM 113 #define DRV_MODULE_VERSION \ __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM) -#define DRV_MODULE_RELDATE "July 11, 2010" +#define DRV_MODULE_RELDATE "August 2, 2010" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -221,12 +221,9 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S_2)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5720)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5722)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750M)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751M)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752)}, @@ -882,7 +879,7 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val) unsigned int loops; int ret; - if ((tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET) && + if ((tp->phy_flags & TG3_PHYFLG_IS_FET) && (reg == MII_TG3_CTRL || reg == MII_TG3_AUX_CTRL)) return 0; @@ -1178,7 +1175,7 @@ static int tg3_mdio_init(struct tg3 *tp) case PHY_ID_BCMAC131: phydev->interface = PHY_INTERFACE_MODE_MII; phydev->dev_flags |= PHY_BRCM_AUTO_PWRDWN_ENABLE; - tp->tg3_flags3 |= TG3_FLG3_PHY_IS_FET; + tp->phy_flags |= TG3_PHYFLG_IS_FET; break; } @@ -1271,7 +1268,7 @@ static void tg3_ump_link_report(struct tg3 *tp) tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 4, val); val = 0; - if (!(tp->tg3_flags2 & TG3_FLG2_MII_SERDES)) { + if (!(tp->phy_flags & TG3_PHYFLG_MII_SERDES)) { if (!tg3_readphy(tp, MII_CTRL1000, ®)) val = reg << 16; if (!tg3_readphy(tp, MII_STAT1000, ®)) @@ -1379,7 +1376,7 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 lcladv, u32 rmtadv) if (autoneg == AUTONEG_ENABLE && (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG)) { - if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) + if (tp->phy_flags & TG3_PHYFLG_ANY_SERDES) flowctrl = tg3_resolve_flowctrl_1000X(lcladv, rmtadv); else flowctrl = mii_resolve_flowctrl_fdx(lcladv, rmtadv); @@ -1493,7 +1490,7 @@ static int tg3_phy_init(struct tg3 *tp) { struct phy_device *phydev; - if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) + if (tp->phy_flags & TG3_PHYFLG_IS_CONNECTED) return 0; /* Bring the PHY back to a known state. */ @@ -1513,7 +1510,7 @@ static int tg3_phy_init(struct tg3 *tp) switch (phydev->interface) { case PHY_INTERFACE_MODE_GMII: case PHY_INTERFACE_MODE_RGMII: - if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) { + if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) { phydev->supported &= (PHY_GBIT_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause); @@ -1530,7 +1527,7 @@ static int tg3_phy_init(struct tg3 *tp) return -EINVAL; } - tp->tg3_flags3 |= TG3_FLG3_PHY_CONNECTED; + tp->phy_flags |= TG3_PHYFLG_IS_CONNECTED; phydev->advertising = phydev->supported; @@ -1541,13 +1538,13 @@ static void tg3_phy_start(struct tg3 *tp) { struct phy_device *phydev; - if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)) + if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED)) return; phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; - if (tp->link_config.phy_is_low_power) { - tp->link_config.phy_is_low_power = 0; + if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) { + tp->phy_flags &= ~TG3_PHYFLG_IS_LOW_POWER; phydev->speed = tp->link_config.orig_speed; phydev->duplex = tp->link_config.orig_duplex; phydev->autoneg = tp->link_config.orig_autoneg; @@ -1561,7 +1558,7 @@ static void tg3_phy_start(struct tg3 *tp) static void tg3_phy_stop(struct tg3 *tp) { - if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)) + if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED)) return; phy_stop(tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]); @@ -1569,16 +1566,21 @@ static void tg3_phy_stop(struct tg3 *tp) static void tg3_phy_fini(struct tg3 *tp) { - if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) { + if (tp->phy_flags & TG3_PHYFLG_IS_CONNECTED) { phy_disconnect(tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]); - tp->tg3_flags3 &= ~TG3_FLG3_PHY_CONNECTED; + tp->phy_flags &= ~TG3_PHYFLG_IS_CONNECTED; } } -static void tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val) +static int tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val) { - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg); - tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val); + int err; + + err = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg); + if (!err) + err = tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val); + + return err; } static void tg3_phy_fet_toggle_apd(struct tg3 *tp, bool enable) @@ -1608,10 +1610,10 @@ static void tg3_phy_toggle_apd(struct tg3 *tp, bool enable) if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) && - (tp->tg3_flags2 & TG3_FLG2_MII_SERDES))) + (tp->phy_flags & TG3_PHYFLG_MII_SERDES))) return; - if (tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET) { + if (tp->phy_flags & TG3_PHYFLG_IS_FET) { tg3_phy_fet_toggle_apd(tp, enable); return; } @@ -1642,10 +1644,10 @@ static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable) u32 phy; if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || - (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) + (tp->phy_flags & TG3_PHYFLG_ANY_SERDES)) return; - if (tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET) { + if (tp->phy_flags & TG3_PHYFLG_IS_FET) { u32 ephy; if (!tg3_readphy(tp, MII_TG3_FET_TEST, &ephy)) { @@ -1681,7 +1683,7 @@ static void tg3_phy_set_wirespeed(struct tg3 *tp) { u32 val; - if (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) + if (tp->phy_flags & TG3_PHYFLG_NO_ETH_WIRE_SPEED) return; if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007) && @@ -1740,7 +1742,7 @@ static int tg3_wait_macro_done(struct tg3 *tp) while (limit--) { u32 tmp32; - if (!tg3_readphy(tp, 0x16, &tmp32)) { + if (!tg3_readphy(tp, MII_TG3_DSP_CONTROL, &tmp32)) { if ((tmp32 & 0x1000) == 0) break; } @@ -1766,13 +1768,13 @@ static int tg3_phy_write_and_check_testpat(struct tg3 *tp, int *resetp) tg3_writephy(tp, MII_TG3_DSP_ADDRESS, (chan * 0x2000) | 0x0200); - tg3_writephy(tp, 0x16, 0x0002); + tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0002); for (i = 0; i < 6; i++) tg3_writephy(tp, MII_TG3_DSP_RW_PORT, test_pat[chan][i]); - tg3_writephy(tp, 0x16, 0x0202); + tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0202); if (tg3_wait_macro_done(tp)) { *resetp = 1; return -EBUSY; @@ -1780,13 +1782,13 @@ static int tg3_phy_write_and_check_testpat(struct tg3 *tp, int *resetp) tg3_writephy(tp, MII_TG3_DSP_ADDRESS, (chan * 0x2000) | 0x0200); - tg3_writephy(tp, 0x16, 0x0082); + tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0082); if (tg3_wait_macro_done(tp)) { *resetp = 1; return -EBUSY; } - tg3_writephy(tp, 0x16, 0x0802); + tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0802); if (tg3_wait_macro_done(tp)) { *resetp = 1; return -EBUSY; @@ -1826,10 +1828,10 @@ static int tg3_phy_reset_chanpat(struct tg3 *tp) tg3_writephy(tp, MII_TG3_DSP_ADDRESS, (chan * 0x2000) | 0x0200); - tg3_writephy(tp, 0x16, 0x0002); + tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0002); for (i = 0; i < 6; i++) tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x000); - tg3_writephy(tp, 0x16, 0x0202); + tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0202); if (tg3_wait_macro_done(tp)) return -EBUSY; } @@ -1875,8 +1877,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); /* Block the PHY control access. */ - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005); - tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0800); + tg3_phydsp_write(tp, 0x8005, 0x0800); err = tg3_phy_write_and_check_testpat(tp, &do_phy_reset); if (!err) @@ -1887,11 +1888,10 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) if (err) return err; - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005); - tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0000); + tg3_phydsp_write(tp, 0x8005, 0x0000); tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200); - tg3_writephy(tp, 0x16, 0x0000); + tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0000); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { @@ -1984,42 +1984,37 @@ static int tg3_phy_reset(struct tg3 *tp) if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) && - (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)) + (tp->phy_flags & TG3_PHYFLG_MII_SERDES)) return 0; tg3_phy_apply_otp(tp); - if (tp->tg3_flags3 & TG3_FLG3_PHY_ENABLE_APD) + if (tp->phy_flags & TG3_PHYFLG_ENABLE_APD) tg3_phy_toggle_apd(tp, true); else tg3_phy_toggle_apd(tp, false); out: - if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) { + if (tp->phy_flags & TG3_PHYFLG_ADC_BUG) { tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f); - tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x2aaa); - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a); - tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0323); + tg3_phydsp_write(tp, 0x201f, 0x2aaa); + tg3_phydsp_write(tp, 0x000a, 0x0323); tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400); } - if (tp->tg3_flags2 & TG3_FLG2_PHY_5704_A0_BUG) { - tg3_writephy(tp, 0x1c, 0x8d68); - tg3_writephy(tp, 0x1c, 0x8d68); + if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) { + tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68); + tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68); } - if (tp->tg3_flags2 & TG3_FLG2_PHY_BER_BUG) { + if (tp->phy_flags & TG3_PHYFLG_BER_BUG) { tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a); - tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x310b); - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f); - tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x9506); - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x401f); - tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x14e2); + tg3_phydsp_write(tp, 0x000a, 0x310b); + tg3_phydsp_write(tp, 0x201f, 0x9506); + tg3_phydsp_write(tp, 0x401f, 0x14e2); tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400); - } else if (tp->tg3_flags2 & TG3_FLG2_PHY_JITTER_BUG) { + } else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) { tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a); - if (tp->tg3_flags2 & TG3_FLG2_PHY_ADJUST_TRIM) { + if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) { tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b); tg3_writephy(tp, MII_TG3_TEST1, MII_TG3_TEST1_TRIM_EN | 0x4); @@ -2204,7 +2199,7 @@ static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power) { u32 val; - if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { + if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { u32 sg_dig_ctrl = tr32(SG_DIG_CTRL); u32 serdes_cfg = tr32(MAC_SERDES_CFG); @@ -2223,7 +2218,7 @@ static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power) tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ); udelay(40); return; - } else if (tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET) { + } else if (tp->phy_flags & TG3_PHYFLG_IS_FET) { u32 phytest; if (!tg3_readphy(tp, MII_TG3_FET_TEST, &phytest)) { u32 phy; @@ -2260,7 +2255,7 @@ static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 && - (tp->tg3_flags2 & TG3_FLG2_MII_SERDES))) + (tp->phy_flags & TG3_PHYFLG_MII_SERDES))) return; if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX || @@ -2563,14 +2558,14 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { do_low_power = false; - if ((tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) && - !tp->link_config.phy_is_low_power) { + if ((tp->phy_flags & TG3_PHYFLG_IS_CONNECTED) && + !(tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) { struct phy_device *phydev; u32 phyid, advertising; phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; - tp->link_config.phy_is_low_power = 1; + tp->phy_flags |= TG3_PHYFLG_IS_LOW_POWER; tp->link_config.orig_speed = phydev->speed; tp->link_config.orig_duplex = phydev->duplex; @@ -2609,14 +2604,14 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) } else { do_low_power = true; - if (tp->link_config.phy_is_low_power == 0) { - tp->link_config.phy_is_low_power = 1; + if (!(tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) { + tp->phy_flags |= TG3_PHYFLG_IS_LOW_POWER; tp->link_config.orig_speed = tp->link_config.speed; tp->link_config.orig_duplex = tp->link_config.duplex; tp->link_config.orig_autoneg = tp->link_config.autoneg; } - if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) { + if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES)) { tp->link_config.speed = SPEED_10; tp->link_config.duplex = DUPLEX_HALF; tp->link_config.autoneg = AUTONEG_ENABLE; @@ -2649,13 +2644,13 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) if (device_should_wake) { u32 mac_mode; - if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { + if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES)) { if (do_low_power) { tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a); udelay(40); } - if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) + if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) mac_mode = MAC_MODE_PORT_MODE_GMII; else mac_mode = MAC_MODE_PORT_MODE_MII; @@ -2823,7 +2818,7 @@ static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 break; default: - if (tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET) { + if (tp->phy_flags & TG3_PHYFLG_IS_FET) { *speed = (val & MII_TG3_AUX_STAT_100) ? SPEED_100 : SPEED_10; *duplex = (val & MII_TG3_AUX_STAT_FULL) ? DUPLEX_FULL : @@ -2841,7 +2836,7 @@ static void tg3_phy_copper_begin(struct tg3 *tp) u32 new_adv; int i; - if (tp->link_config.phy_is_low_power) { + if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) { /* Entering low power mode. Disable gigabit and * 100baseT advertisements. */ @@ -2854,7 +2849,7 @@ static void tg3_phy_copper_begin(struct tg3 *tp) tg3_writephy(tp, MII_ADVERTISE, new_adv); } else if (tp->link_config.speed == SPEED_INVALID) { - if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) + if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY) tp->link_config.advertising &= ~(ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full); @@ -2880,7 +2875,7 @@ static void tg3_phy_copper_begin(struct tg3 *tp) new_adv |= MII_TG3_CTRL_ADV_1000_HALF; if (tp->link_config.advertising & ADVERTISED_1000baseT_Full) new_adv |= MII_TG3_CTRL_ADV_1000_FULL; - if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY) && + if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY) && (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 || tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)) new_adv |= (MII_TG3_CTRL_AS_MASTER | @@ -2982,20 +2977,11 @@ static int tg3_init_5401phy_dsp(struct tg3 *tp) /* Set Extended packet length bit */ err = tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4c20); - err |= tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x0012); - err |= tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x1804); - - err |= tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x0013); - err |= tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x1204); - - err |= tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8006); - err |= tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0132); - - err |= tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8006); - err |= tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0232); - - err |= tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f); - err |= tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0a20); + err |= tg3_phydsp_write(tp, 0x0012, 0x1804); + err |= tg3_phydsp_write(tp, 0x0013, 0x1204); + err |= tg3_phydsp_write(tp, 0x8006, 0x0132); + err |= tg3_phydsp_write(tp, 0x8006, 0x0232); + err |= tg3_phydsp_write(tp, 0x201f, 0x0a20); udelay(40); @@ -3020,7 +3006,7 @@ static int tg3_copper_is_advertising_all(struct tg3 *tp, u32 mask) if ((adv_reg & all_mask) != all_mask) return 0; - if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) { + if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) { u32 tg3_ctrl; all_mask = 0; @@ -3148,18 +3134,18 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) { /* 5701 {A0,B0} CRC bug workaround */ tg3_writephy(tp, 0x15, 0x0a75); - tg3_writephy(tp, 0x1c, 0x8c68); - tg3_writephy(tp, 0x1c, 0x8d68); - tg3_writephy(tp, 0x1c, 0x8c68); + tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8c68); + tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68); + tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8c68); } /* Clear pending interrupts... */ tg3_readphy(tp, MII_TG3_ISTAT, &dummy); tg3_readphy(tp, MII_TG3_ISTAT, &dummy); - if (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) + if (tp->phy_flags & TG3_PHYFLG_USE_MI_INTERRUPT) tg3_writephy(tp, MII_TG3_IMASK, ~MII_TG3_INT_LINKCHG); - else if (!(tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET)) + else if (!(tp->phy_flags & TG3_PHYFLG_IS_FET)) tg3_writephy(tp, MII_TG3_IMASK, ~0); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || @@ -3175,7 +3161,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) current_speed = SPEED_INVALID; current_duplex = DUPLEX_INVALID; - if (tp->tg3_flags2 & TG3_FLG2_CAPACITIVE_COUPLING) { + if (tp->phy_flags & TG3_PHYFLG_CAPACITIVE_COUPLING) { u32 val; tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4007); @@ -3251,7 +3237,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) } relink: - if (current_link_up == 0 || tp->link_config.phy_is_low_power) { + if (current_link_up == 0 || (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) { u32 tmp; tg3_phy_copper_begin(tp); @@ -3269,7 +3255,7 @@ relink: tp->mac_mode |= MAC_MODE_PORT_MODE_MII; else tp->mac_mode |= MAC_MODE_PORT_MODE_GMII; - } else if (tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET) + } else if (tp->phy_flags & TG3_PHYFLG_IS_FET) tp->mac_mode |= MAC_MODE_PORT_MODE_MII; else tp->mac_mode |= MAC_MODE_PORT_MODE_GMII; @@ -3820,7 +3806,7 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) expected_sg_dig_ctrl |= SG_DIG_ASYM_PAUSE; if (sg_dig_ctrl != expected_sg_dig_ctrl) { - if ((tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT) && + if ((tp->phy_flags & TG3_PHYFLG_PARALLEL_DETECT) && tp->serdes_counter && ((mac_status & (MAC_STATUS_PCS_SYNCED | MAC_STATUS_RCVD_CFG)) == @@ -3837,7 +3823,7 @@ restart_autoneg: tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl); tp->serdes_counter = SERDES_AN_TIMEOUT_5704S; - tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; + tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT; } else if (mac_status & (MAC_STATUS_PCS_SYNCED | MAC_STATUS_SIGNAL_DET)) { sg_dig_status = tr32(SG_DIG_STATUS); @@ -3860,7 +3846,7 @@ restart_autoneg: tg3_setup_flow_control(tp, local_adv, remote_adv); current_link_up = 1; tp->serdes_counter = 0; - tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; + tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT; } else if (!(sg_dig_status & SG_DIG_AUTONEG_COMPLETE)) { if (tp->serdes_counter) tp->serdes_counter--; @@ -3887,8 +3873,8 @@ restart_autoneg: !(mac_status & MAC_STATUS_RCVD_CFG)) { tg3_setup_flow_control(tp, 0, 0); current_link_up = 1; - tp->tg3_flags2 |= - TG3_FLG2_PARALLEL_DETECT; + tp->phy_flags |= + TG3_PHYFLG_PARALLEL_DETECT; tp->serdes_counter = SERDES_PARALLEL_DET_TIMEOUT; } else @@ -3897,7 +3883,7 @@ restart_autoneg: } } else { tp->serdes_counter = SERDES_AN_TIMEOUT_5704S; - tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; + tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT; } out: @@ -4114,7 +4100,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) err |= tg3_readphy(tp, MII_BMCR, &bmcr); if ((tp->link_config.autoneg == AUTONEG_ENABLE) && !force_reset && - (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT)) { + (tp->phy_flags & TG3_PHYFLG_PARALLEL_DETECT)) { /* do nothing, just check for link up at the end */ } else if (tp->link_config.autoneg == AUTONEG_ENABLE) { u32 adv, new_adv; @@ -4139,7 +4125,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED); tp->serdes_counter = SERDES_AN_TIMEOUT_5714S; - tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; + tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT; return err; } @@ -4184,7 +4170,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) else bmsr &= ~BMSR_LSTATUS; } - tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; + tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT; } } @@ -4239,7 +4225,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) netif_carrier_on(tp->dev); else { netif_carrier_off(tp->dev); - tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; + tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT; } tg3_link_report(tp); } @@ -4263,13 +4249,14 @@ static void tg3_serdes_parallel_detect(struct tg3 *tp) u32 phy1, phy2; /* Select shadow register 0x1f */ - tg3_writephy(tp, 0x1c, 0x7c00); - tg3_readphy(tp, 0x1c, &phy1); + tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x7c00); + tg3_readphy(tp, MII_TG3_MISC_SHDW, &phy1); /* Select expansion interrupt status register */ - tg3_writephy(tp, 0x17, 0x0f01); - tg3_readphy(tp, 0x15, &phy2); - tg3_readphy(tp, 0x15, &phy2); + tg3_writephy(tp, MII_TG3_DSP_ADDRESS, + MII_TG3_DSP_EXP1_INT_STAT); + tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &phy2); + tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &phy2); if ((phy1 & 0x10) && !(phy2 & 0x20)) { /* We have signal detect and not receiving @@ -4280,17 +4267,18 @@ static void tg3_serdes_parallel_detect(struct tg3 *tp) bmcr &= ~BMCR_ANENABLE; bmcr |= BMCR_SPEED1000 | BMCR_FULLDPLX; tg3_writephy(tp, MII_BMCR, bmcr); - tp->tg3_flags2 |= TG3_FLG2_PARALLEL_DETECT; + tp->phy_flags |= TG3_PHYFLG_PARALLEL_DETECT; } } } else if (netif_carrier_ok(tp->dev) && (tp->link_config.autoneg == AUTONEG_ENABLE) && - (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT)) { + (tp->phy_flags & TG3_PHYFLG_PARALLEL_DETECT)) { u32 phy2; /* Select expansion interrupt status register */ - tg3_writephy(tp, 0x17, 0x0f01); - tg3_readphy(tp, 0x15, &phy2); + tg3_writephy(tp, MII_TG3_DSP_ADDRESS, + MII_TG3_DSP_EXP1_INT_STAT); + tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &phy2); if (phy2 & 0x20) { u32 bmcr; @@ -4298,7 +4286,7 @@ static void tg3_serdes_parallel_detect(struct tg3 *tp) tg3_readphy(tp, MII_BMCR, &bmcr); tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANENABLE); - tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; + tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT; } } @@ -4308,9 +4296,9 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) { int err; - if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) + if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) err = tg3_setup_fiber_phy(tp, force_reset); - else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) + else if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) err = tg3_setup_fiber_mii_phy(tp, force_reset); else err = tg3_setup_copper_phy(tp, force_reset); @@ -4389,7 +4377,8 @@ static void tg3_tx_recover(struct tg3 *tp) static inline u32 tg3_tx_avail(struct tg3_napi *tnapi) { - smp_mb(); + /* Tell compiler to fetch tx indices from memory. */ + barrier(); return tnapi->tx_pending - ((tnapi->tx_prod - tnapi->tx_cons) & (TG3_TX_RING_SIZE - 1)); } @@ -5673,6 +5662,13 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, tnapi->tx_prod = entry; if (unlikely(tg3_tx_avail(tnapi) <= (MAX_SKB_FRAGS + 1))) { netif_tx_stop_queue(txq); + + /* netif_tx_stop_queue() must be done before checking + * checking tx index in tg3_tx_avail() below, because in + * tg3_tx(), we update tx index before checking for + * netif_tx_queue_stopped(). + */ + smp_mb(); if (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi)) netif_tx_wake_queue(txq); } @@ -5718,6 +5714,13 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb) /* Estimate the number of fragments in the worst case */ if (unlikely(tg3_tx_avail(&tp->napi[0]) <= frag_cnt_est)) { netif_stop_queue(tp->dev); + + /* netif_tx_stop_queue() must be done before checking + * checking tx index in tg3_tx_avail() below, because in + * tg3_tx(), we update tx index before checking for + * netif_tx_queue_stopped(). + */ + smp_mb(); if (tg3_tx_avail(&tp->napi[0]) <= frag_cnt_est) return NETDEV_TX_BUSY; @@ -5953,6 +5956,13 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb, tnapi->tx_prod = entry; if (unlikely(tg3_tx_avail(tnapi) <= (MAX_SKB_FRAGS + 1))) { netif_tx_stop_queue(txq); + + /* netif_tx_stop_queue() must be done before checking + * checking tx index in tg3_tx_avail() below, because in + * tg3_tx(), we update tx index before checking for + * netif_tx_queue_stopped(). + */ + smp_mb(); if (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi)) netif_tx_wake_queue(txq); } @@ -6929,9 +6939,13 @@ static int tg3_chip_reset(struct tg3 *tp) val = GRC_MISC_CFG_CORECLK_RESET; if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { - if (tr32(0x7e2c) == 0x60) { - tw32(0x7e2c, 0x20); - } + /* Force PCIe 1.0a mode */ + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 && + !(tp->tg3_flags3 & TG3_FLG3_5717_PLUS) && + tr32(TG3_PCIE_PHY_TSTCTL) == + (TG3_PCIE_PHY_TSTCTL_PCIE10 | TG3_PCIE_PHY_TSTCTL_PSCRAM)) + tw32(TG3_PCIE_PHY_TSTCTL, TG3_PCIE_PHY_TSTCTL_PSCRAM); + if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) { tw32(GRC_MISC_CFG, (1 << 29)); val |= (1 << 29); @@ -6944,8 +6958,11 @@ static int tg3_chip_reset(struct tg3 *tp) tr32(GRC_VCPU_EXT_CTRL) & ~GRC_VCPU_EXT_CTRL_HALT_CPU); } - if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) + /* Manage gphy power for all CPMU absent PCIe devices. */ + if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && + !(tp->tg3_flags & TG3_FLAG_CPMU_PRESENT)) val |= GRC_MISC_CFG_KEEP_GPHY_POWER; + tw32(GRC_MISC_CFG, val); /* restore 5701 hardware bug workaround write method */ @@ -7002,8 +7019,7 @@ static int tg3_chip_reset(struct tg3 *tp) * Older PCIe devices only support the 128 byte * MPS setting. Enforce the restriction. */ - if (!(tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784)) + if (!(tp->tg3_flags & TG3_FLAG_CPMU_PRESENT)) val16 &= ~PCI_EXP_DEVCTL_PAYLOAD; pci_write_config_word(tp->pdev, tp->pcie_cap + PCI_EXP_DEVCTL, @@ -7050,10 +7066,10 @@ static int tg3_chip_reset(struct tg3 *tp) tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); } - if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { + if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) { tp->mac_mode = MAC_MODE_PORT_MODE_TBI; tw32_f(MAC_MODE, tp->mac_mode); - } else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { + } else if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) { tp->mac_mode = MAC_MODE_PORT_MODE_GMII; tw32_f(MAC_MODE, tp->mac_mode); } else if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { @@ -7076,9 +7092,7 @@ static int tg3_chip_reset(struct tg3 *tp) if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && tp->pci_chip_rev_id != CHIPREV_ID_5750_A0 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5719 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765) { + !(tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) { val = tr32(0x7c00); tw32(0x7c00, val | (1 << 25)); @@ -7751,9 +7765,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (err) return err; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) { + if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) { val = tr32(TG3PCI_DMA_RW_CTRL) & ~DMA_RWCTRL_DIS_CACHE_ALIGNMENT; if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) @@ -7916,9 +7928,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) BDINFO_FLAGS_DISABLED); } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) + if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) val = (RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT) | (TG3_RX_STD_DMA_SZ << 2); else @@ -7935,9 +7945,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tp->rx_jumbo_pending : 0; tw32_rx_mbox(TG3_RX_JMB_PROD_IDX_REG, tpr->rx_jmb_prod_idx); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) { + if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) { tw32(STD_REPLENISH_LWM, 32); tw32(JMB_REPLENISH_LWM, 16); } @@ -8065,8 +8073,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) tw32(RCVLSC_MODE, RCVLSC_MODE_ENABLE | RCVLSC_MODE_ATTN_ENABLE); - if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { - tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; + if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) { + tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT; /* reset to prevent losing 1st rx packet intermittently */ tw32_f(MAC_RX_MODE, RX_MODE_RESET); udelay(10); @@ -8079,7 +8087,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tp->mac_mode |= MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE | MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE; if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && - !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && + !(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) tp->mac_mode |= MAC_MODE_LINK_POLARITY; tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR); @@ -8264,16 +8272,16 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(MAC_LED_CTRL, tp->led_ctrl); tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB); - if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { + if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) { tw32_f(MAC_RX_MODE, RX_MODE_RESET); udelay(10); } tw32_f(MAC_RX_MODE, tp->rx_mode); udelay(10); - if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { + if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) { if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) && - !(tp->tg3_flags2 & TG3_FLG2_SERDES_PREEMPHASIS)) { + !(tp->phy_flags & TG3_PHYFLG_SERDES_PREEMPHASIS)) { /* Set drive transmission level to 1.2V */ /* only if the signal pre-emphasis bit is not set */ val = tr32(MAC_SERDES_CFG); @@ -8295,12 +8303,12 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, val); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && - (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { + (tp->phy_flags & TG3_PHYFLG_PHY_SERDES)) { /* Use hardware link auto-negotiation */ tp->tg3_flags2 |= TG3_FLG2_HW_AUTONEG; } - if ((tp->tg3_flags2 & TG3_FLG2_MII_SERDES) && + if ((tp->phy_flags & TG3_PHYFLG_MII_SERDES) && (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)) { u32 tmp; @@ -8312,8 +8320,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) } if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) { - if (tp->link_config.phy_is_low_power) { - tp->link_config.phy_is_low_power = 0; + if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) { + tp->phy_flags &= ~TG3_PHYFLG_IS_LOW_POWER; tp->link_config.speed = tp->link_config.orig_speed; tp->link_config.duplex = tp->link_config.orig_duplex; tp->link_config.autoneg = tp->link_config.orig_autoneg; @@ -8323,15 +8331,15 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (err) return err; - if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && - !(tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET)) { + if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) && + !(tp->phy_flags & TG3_PHYFLG_IS_FET)) { u32 tmp; /* Clear CRC stats. */ if (!tg3_readphy(tp, MII_TG3_TEST1, &tmp)) { tg3_writephy(tp, MII_TG3_TEST1, tmp | MII_TG3_TEST1_CRC_EN); - tg3_readphy(tp, 0x14, &tmp); + tg3_readphy(tp, MII_TG3_RXR_COUNTERS, &tmp); } } } @@ -8499,7 +8507,7 @@ static void tg3_timer(unsigned long __opaque) mac_stat = tr32(MAC_STATUS); phy_event = 0; - if (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) { + if (tp->phy_flags & TG3_PHYFLG_USE_MI_INTERRUPT) { if (mac_stat & MAC_STATUS_MI_INTERRUPT) phy_event = 1; } else if (mac_stat & MAC_STATUS_LNKSTATE_CHANGED) @@ -8531,7 +8539,7 @@ static void tg3_timer(unsigned long __opaque) } tg3_setup_phy(tp, 0); } - } else if ((tp->tg3_flags2 & TG3_FLG2_MII_SERDES) && + } else if ((tp->phy_flags & TG3_PHYFLG_MII_SERDES) && (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) { tg3_serdes_parallel_detect(tp); } @@ -8627,9 +8635,7 @@ static int tg3_test_interrupt(struct tg3 *tp) * Turn off MSI one shot mode. Otherwise this test has no * observable way to know whether the interrupt was delivered. */ - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) && + if ((tp->tg3_flags3 & TG3_FLG3_5717_PLUS) && (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) { val = tr32(MSGINT_MODE) | MSGINT_MODE_ONE_SHOT_DISABLE; tw32(MSGINT_MODE, val); @@ -8672,9 +8678,7 @@ static int tg3_test_interrupt(struct tg3 *tp) if (intr_ok) { /* Reenable MSI one shot mode. */ - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) && + if ((tp->tg3_flags3 & TG3_FLG3_5717_PLUS) && (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) { val = tr32(MSGINT_MODE) & ~MSGINT_MODE_ONE_SHOT_DISABLE; tw32(MSGINT_MODE, val); @@ -8865,7 +8869,7 @@ static void tg3_ints_fini(struct tg3 *tp) else if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) pci_disable_msi(tp->pdev); tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI_OR_MSIX; - tp->tg3_flags3 &= ~TG3_FLG3_ENABLE_RSS; + tp->tg3_flags3 &= ~(TG3_FLG3_ENABLE_RSS | TG3_FLG3_ENABLE_TSS); } static int tg3_open(struct net_device *dev) @@ -8969,11 +8973,8 @@ static int tg3_open(struct net_device *dev) goto err_out2; } - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5719 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765 && - (tp->tg3_flags2 & TG3_FLG2_USING_MSI) && - (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI)) { + if (!(tp->tg3_flags3 & TG3_FLG3_5717_PLUS) && + (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) { u32 val = tr32(PCIE_TRANSACTION_CFG); tw32(PCIE_TRANSACTION_CFG, @@ -9068,7 +9069,7 @@ static u64 calc_crc_errors(struct tg3 *tp) { struct tg3_hw_stats *hw_stats = tp->hw_stats; - if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && + if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) && (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) { u32 val; @@ -9077,7 +9078,7 @@ static u64 calc_crc_errors(struct tg3 *tp) if (!tg3_readphy(tp, MII_TG3_TEST1, &val)) { tg3_writephy(tp, MII_TG3_TEST1, val | MII_TG3_TEST1_CRC_EN); - tg3_readphy(tp, 0x14, &val); + tg3_readphy(tp, MII_TG3_RXR_COUNTERS, &val); } else val = 0; spin_unlock_bh(&tp->lock); @@ -9367,7 +9368,7 @@ static void tg3_get_regs(struct net_device *dev, memset(p, 0, TG3_REGDUMP_LEN); - if (tp->link_config.phy_is_low_power) + if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) return; tg3_full_lock(tp, 0); @@ -9446,7 +9447,7 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, if (tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) return -EINVAL; - if (tp->link_config.phy_is_low_power) + if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) return -EAGAIN; offset = eeprom->offset; @@ -9508,7 +9509,7 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *buf; __be32 start, end; - if (tp->link_config.phy_is_low_power) + if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) return -EAGAIN; if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) || @@ -9565,7 +9566,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { struct phy_device *phydev; - if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)) + if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED)) return -EAGAIN; phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; return phy_ethtool_gset(phydev, cmd); @@ -9573,11 +9574,11 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->supported = (SUPPORTED_Autoneg); - if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) + if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) cmd->supported |= (SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full); - if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) { + if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES)) { cmd->supported |= (SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_10baseT_Half | @@ -9608,7 +9609,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { struct phy_device *phydev; - if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)) + if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED)) return -EAGAIN; phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; return phy_ethtool_sset(phydev, cmd); @@ -9628,11 +9629,11 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) ADVERTISED_Pause | ADVERTISED_Asym_Pause; - if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) + if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) mask |= ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full; - if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) + if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES)) mask |= ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | ADVERTISED_10baseT_Half | @@ -9653,7 +9654,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->advertising &= mask; } else { - if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) { + if (tp->phy_flags & TG3_PHYFLG_ANY_SERDES) { if (cmd->speed != SPEED_1000) return -EINVAL; @@ -9789,11 +9790,11 @@ static int tg3_nway_reset(struct net_device *dev) if (!netif_running(dev)) return -EAGAIN; - if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) + if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) return -EINVAL; if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { - if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)) + if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED)) return -EAGAIN; r = phy_start_aneg(tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]); } else { @@ -9804,7 +9805,7 @@ static int tg3_nway_reset(struct net_device *dev) tg3_readphy(tp, MII_BMCR, &bmcr); if (!tg3_readphy(tp, MII_BMCR, &bmcr) && ((bmcr & BMCR_ANENABLE) || - (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT))) { + (tp->phy_flags & TG3_PHYFLG_PARALLEL_DETECT))) { tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART | BMCR_ANENABLE); r = 0; @@ -9939,7 +9940,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam else tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG; - if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) { + if (tp->phy_flags & TG3_PHYFLG_IS_CONNECTED) { u32 oldadv = phydev->advertising & (ADVERTISED_Pause | ADVERTISED_Asym_Pause); if (oldadv != newadv) { @@ -10268,7 +10269,7 @@ static int tg3_test_link(struct tg3 *tp) if (!netif_running(tp->dev)) return -ENODEV; - if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) + if (tp->phy_flags & TG3_PHYFLG_ANY_SERDES) max = TG3_SERDES_TIMEOUT_SEC; else max = TG3_COPPER_TIMEOUT_SEC; @@ -10630,7 +10631,7 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) MAC_MODE_PORT_INT_LPBACK; if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) mac_mode |= MAC_MODE_LINK_POLARITY; - if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) + if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY) mac_mode |= MAC_MODE_PORT_MODE_MII; else mac_mode |= MAC_MODE_PORT_MODE_GMII; @@ -10638,7 +10639,7 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) } else if (loopback_mode == TG3_PHY_LOOPBACK) { u32 val; - if (tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET) { + if (tp->phy_flags & TG3_PHYFLG_IS_FET) { tg3_phy_fet_toggle_apd(tp, false); val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED100; } else @@ -10650,7 +10651,7 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) udelay(40); mac_mode = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK; - if (tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET) { + if (tp->phy_flags & TG3_PHYFLG_IS_FET) { tg3_writephy(tp, MII_TG3_FET_PTEST, MII_TG3_FET_PTEST_FRC_TX_LINK | MII_TG3_FET_PTEST_FRC_TX_LOCK); @@ -10662,7 +10663,7 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) mac_mode |= MAC_MODE_PORT_MODE_GMII; /* reset to prevent losing 1st rx packet intermittently */ - if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { + if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) { tw32_f(MAC_RX_MODE, RX_MODE_RESET); udelay(10); tw32_f(MAC_RX_MODE, tp->rx_mode); @@ -10793,7 +10794,7 @@ static int tg3_test_loopback(struct tg3 *tp) return TG3_LOOPBACK_FAILED; /* Turn off gphy autopowerdown. */ - if (tp->tg3_flags3 & TG3_FLG3_PHY_ENABLE_APD) + if (tp->phy_flags & TG3_PHYFLG_ENABLE_APD) tg3_phy_toggle_apd(tp, false); if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) { @@ -10830,14 +10831,14 @@ static int tg3_test_loopback(struct tg3 *tp) tw32(TG3_CPMU_MUTEX_GNT, CPMU_MUTEX_GNT_DRIVER); } - if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && + if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) && !(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) { if (tg3_run_loopback(tp, TG3_PHY_LOOPBACK)) err |= TG3_PHY_LOOPBACK_FAILED; } /* Re-enable gphy autopowerdown. */ - if (tp->tg3_flags3 & TG3_FLG3_PHY_ENABLE_APD) + if (tp->phy_flags & TG3_PHYFLG_ENABLE_APD) tg3_phy_toggle_apd(tp, true); return err; @@ -10848,7 +10849,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, { struct tg3 *tp = netdev_priv(dev); - if (tp->link_config.phy_is_low_power) + if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) tg3_set_power_state(tp, PCI_D0); memset(data, 0, sizeof(u64) * TG3_NUM_TEST); @@ -10880,7 +10881,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, if (!err) tg3_nvram_unlock(tp); - if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) + if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) tg3_phy_reset(tp); if (tg3_test_registers(tp) != 0) { @@ -10916,7 +10917,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, if (irq_sync && !err2) tg3_phy_start(tp); } - if (tp->link_config.phy_is_low_power) + if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) tg3_set_power_state(tp, PCI_D3hot); } @@ -10929,7 +10930,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { struct phy_device *phydev; - if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)) + if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED)) return -EAGAIN; phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; return phy_mii_ioctl(phydev, ifr, cmd); @@ -10943,10 +10944,10 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCGMIIREG: { u32 mii_regval; - if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) + if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) break; /* We have no PHY */ - if (tp->link_config.phy_is_low_power) + if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) return -EAGAIN; spin_lock_bh(&tp->lock); @@ -10959,10 +10960,10 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) } case SIOCSMIIREG: - if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) + if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) break; /* We have no PHY */ - if (tp->link_config.phy_is_low_power) + if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) return -EAGAIN; spin_lock_bh(&tp->lock); @@ -12090,9 +12091,9 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->phy_id = eeprom_phy_id; if (eeprom_phy_serdes) { if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) - tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; + tp->phy_flags |= TG3_PHYFLG_PHY_SERDES; else - tp->tg3_flags2 |= TG3_FLG2_MII_SERDES; + tp->phy_flags |= TG3_PHYFLG_MII_SERDES; } if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) @@ -12176,7 +12177,7 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)) tp->tg3_flags3 |= TG3_FLG3_ENABLE_APE; - if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES && + if (tp->phy_flags & TG3_PHYFLG_ANY_SERDES && !(nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)) tp->tg3_flags &= ~TG3_FLAG_WOL_CAP; @@ -12185,19 +12186,21 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->tg3_flags |= TG3_FLAG_WOL_ENABLE; if (cfg2 & (1 << 17)) - tp->tg3_flags2 |= TG3_FLG2_CAPACITIVE_COUPLING; + tp->phy_flags |= TG3_PHYFLG_CAPACITIVE_COUPLING; /* serdes signal pre-emphasis in register 0x590 set by */ /* bootcode if bit 18 is set */ if (cfg2 & (1 << 18)) - tp->tg3_flags2 |= TG3_FLG2_SERDES_PREEMPHASIS; + tp->phy_flags |= TG3_PHYFLG_SERDES_PREEMPHASIS; if (((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 && GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX)) && (cfg2 & NIC_SRAM_DATA_CFG_2_APD_EN)) - tp->tg3_flags3 |= TG3_FLG3_PHY_ENABLE_APD; + tp->phy_flags |= TG3_PHYFLG_ENABLE_APD; - if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { + if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 && + !(tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) { u32 cfg3; tg3_read_mem(tp, NIC_SRAM_DATA_CFG_3, &cfg3); @@ -12302,9 +12305,9 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) if (!err && TG3_KNOWN_PHY_ID(hw_phy_id_masked)) { tp->phy_id = hw_phy_id; if (hw_phy_id_masked == TG3_PHY_ID_BCM8002) - tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; + tp->phy_flags |= TG3_PHYFLG_PHY_SERDES; else - tp->tg3_flags2 &= ~TG3_FLG2_PHY_SERDES; + tp->phy_flags &= ~TG3_PHYFLG_PHY_SERDES; } else { if (tp->phy_id != TG3_PHY_ID_INVALID) { /* Do nothing, phy ID already set up in @@ -12323,11 +12326,11 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) tp->phy_id = p->phy_id; if (!tp->phy_id || tp->phy_id == TG3_PHY_ID_BCM8002) - tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; + tp->phy_flags |= TG3_PHYFLG_PHY_SERDES; } } - if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) && + if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) && !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) && !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { u32 bmsr, adv_reg, tg3_ctrl, mask; @@ -12345,7 +12348,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) ADVERTISE_100HALF | ADVERTISE_100FULL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); tg3_ctrl = 0; - if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) { + if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) { tg3_ctrl = (MII_TG3_CTRL_ADV_1000_HALF | MII_TG3_CTRL_ADV_1000_FULL); if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 || @@ -12360,7 +12363,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) if (!tg3_copper_is_advertising_all(tp, mask)) { tg3_writephy(tp, MII_ADVERTISE, adv_reg); - if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) + if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) tg3_writephy(tp, MII_TG3_CTRL, tg3_ctrl); tg3_writephy(tp, MII_BMCR, @@ -12369,7 +12372,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) tg3_phy_set_wirespeed(tp); tg3_writephy(tp, MII_ADVERTISE, adv_reg); - if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) + if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) tg3_writephy(tp, MII_TG3_CTRL, tg3_ctrl); } @@ -12382,13 +12385,13 @@ skip_phy_reset: err = tg3_init_5401phy_dsp(tp); } - if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) + if (tp->phy_flags & TG3_PHYFLG_ANY_SERDES) tp->link_config.advertising = (ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg | ADVERTISED_FIBRE); - if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) + if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY) tp->link_config.advertising &= ~(ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full); @@ -12717,6 +12720,7 @@ static void __devinit tg3_read_dash_ver(struct tg3 *tp) { int vlen; u32 apedata; + char *fwtype; if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) || !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) @@ -12732,9 +12736,15 @@ static void __devinit tg3_read_dash_ver(struct tg3 *tp) apedata = tg3_ape_read32(tp, TG3_APE_FW_VERSION); + if (tg3_ape_read32(tp, TG3_APE_FW_FEATURES) & TG3_APE_FW_FEATURE_NCSI) + fwtype = "NCSI"; + else + fwtype = "DASH"; + vlen = strlen(tp->fw_ver); - snprintf(&tp->fw_ver[vlen], TG3_VER_SIZE - vlen, " DASH v%d.%d.%d.%d", + snprintf(&tp->fw_ver[vlen], TG3_VER_SIZE - vlen, " %s v%d.%d.%d.%d", + fwtype, (apedata & APE_FW_VERSION_MAJMSK) >> APE_FW_VERSION_MAJSFT, (apedata & APE_FW_VERSION_MINMSK) >> APE_FW_VERSION_MINSFT, (apedata & APE_FW_VERSION_REVMSK) >> APE_FW_VERSION_REVSFT, @@ -12988,6 +12998,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) tp->pdev_peer = tg3_find_peer(tp); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) + tp->tg3_flags3 |= TG3_FLG3_5717_PLUS; + /* Intentionally exclude ASIC_REV_5906 */ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || @@ -12995,9 +13010,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) + (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) tp->tg3_flags3 |= TG3_FLG3_5755_PLUS; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || @@ -13027,9 +13040,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } /* Determine TSO capabilities */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) + if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) tp->tg3_flags2 |= TG3_FLG2_HW_TSO_3; else if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) @@ -13065,9 +13076,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI; } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) { + if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) { tp->tg3_flags |= TG3_FLAG_SUPPORT_MSIX; tp->irq_max = TG3_IRQ_MAX_VECS; } @@ -13082,9 +13091,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags3 |= TG3_FLG3_40BIT_DMA_LIMIT_BUG; } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) + if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) tp->tg3_flags3 |= TG3_FLG3_USE_JUMBO_BDFLAG; if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || @@ -13285,9 +13292,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) + (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT; /* Set up tp->grc_local_ctrl before calling tg3_set_power_state(). @@ -13345,41 +13350,39 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) - tp->tg3_flags3 |= TG3_FLG3_PHY_IS_FET; + tp->phy_flags |= TG3_PHYFLG_IS_FET; /* A few boards don't want Ethernet@WireSpeed phy feature */ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) || ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) && (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) && (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1)) || - (tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET) || - (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) - tp->tg3_flags2 |= TG3_FLG2_NO_ETH_WIRE_SPEED; + (tp->phy_flags & TG3_PHYFLG_IS_FET) || + (tp->phy_flags & TG3_PHYFLG_ANY_SERDES)) + tp->phy_flags |= TG3_PHYFLG_NO_ETH_WIRE_SPEED; if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5703_AX || GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5704_AX) - tp->tg3_flags2 |= TG3_FLG2_PHY_ADC_BUG; + tp->phy_flags |= TG3_PHYFLG_ADC_BUG; if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0) - tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG; + tp->phy_flags |= TG3_PHYFLG_5704_A0_BUG; if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && - !(tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET) && + !(tp->phy_flags & TG3_PHYFLG_IS_FET) && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57780 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5719 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765) { + !(tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) { if (tp->pdev->device != PCI_DEVICE_ID_TIGON3_5756 && tp->pdev->device != PCI_DEVICE_ID_TIGON3_5722) - tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG; + tp->phy_flags |= TG3_PHYFLG_JITTER_BUG; if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5755M) - tp->tg3_flags2 |= TG3_FLG2_PHY_ADJUST_TRIM; + tp->phy_flags |= TG3_PHYFLG_ADJUST_TRIM; } else - tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG; + tp->phy_flags |= TG3_PHYFLG_BER_BUG; } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 && @@ -13492,8 +13495,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790 || tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791 || tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795 || - (tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET)) - tp->tg3_flags |= TG3_FLAG_10_100_ONLY; + (tp->phy_flags & TG3_PHYFLG_IS_FET)) + tp->phy_flags |= TG3_PHYFLG_10_100_ONLY; err = tg3_phy_probe(tp); if (err) { @@ -13505,13 +13508,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tg3_read_vpd(tp); tg3_read_fw_ver(tp); - if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { - tp->tg3_flags &= ~TG3_FLAG_USE_MI_INTERRUPT; + if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) { + tp->phy_flags &= ~TG3_PHYFLG_USE_MI_INTERRUPT; } else { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) - tp->tg3_flags |= TG3_FLAG_USE_MI_INTERRUPT; + tp->phy_flags |= TG3_PHYFLG_USE_MI_INTERRUPT; else - tp->tg3_flags &= ~TG3_FLAG_USE_MI_INTERRUPT; + tp->phy_flags &= ~TG3_PHYFLG_USE_MI_INTERRUPT; } /* 5700 {AX,BX} chips have a broken status block link @@ -13529,13 +13532,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) */ if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL && GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 && - !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { - tp->tg3_flags |= (TG3_FLAG_USE_MI_INTERRUPT | - TG3_FLAG_USE_LINKCHG_REG); + !(tp->phy_flags & TG3_PHYFLG_PHY_SERDES)) { + tp->phy_flags |= TG3_PHYFLG_USE_MI_INTERRUPT; + tp->tg3_flags |= TG3_FLAG_USE_LINKCHG_REG; } /* For all SERDES we poll the MAC status register. */ - if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) + if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) tp->tg3_flags |= TG3_FLAG_POLL_SERDES; else tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES; @@ -13705,9 +13708,7 @@ static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val) #endif #endif - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) { + if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) { val = goal ? 0 : DMA_RWCTRL_DIS_CACHE_ALIGNMENT; goto out; } @@ -13918,9 +13919,7 @@ static int __devinit tg3_test_dma(struct tg3 *tp) tp->dma_rwctrl = tg3_calc_dma_bndry(tp, tp->dma_rwctrl); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) + if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) goto out; if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { @@ -14110,7 +14109,6 @@ static void __devinit tg3_init_link_config(struct tg3 *tp) tp->link_config.autoneg = AUTONEG_ENABLE; tp->link_config.active_speed = SPEED_INVALID; tp->link_config.active_duplex = DUPLEX_INVALID; - tp->link_config.phy_is_low_power = 0; tp->link_config.orig_speed = SPEED_INVALID; tp->link_config.orig_duplex = DUPLEX_INVALID; tp->link_config.orig_autoneg = AUTONEG_INVALID; @@ -14118,9 +14116,7 @@ static void __devinit tg3_init_link_config(struct tg3 *tp) static void __devinit tg3_init_bufmgr_config(struct tg3 *tp) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) { + if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) { tp->bufmgr_config.mbuf_read_dma_low_water = DEFAULT_MB_RDMA_LOW_WATER_5705; tp->bufmgr_config.mbuf_mac_rx_low_water = @@ -14645,24 +14641,31 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tg3_bus_string(tp, str), dev->dev_addr); - if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) { + if (tp->phy_flags & TG3_PHYFLG_IS_CONNECTED) { struct phy_device *phydev; phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; netdev_info(dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s)\n", phydev->drv->name, dev_name(&phydev->dev)); - } else + } else { + char *ethtype; + + if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY) + ethtype = "10/100Base-TX"; + else if (tp->phy_flags & TG3_PHYFLG_ANY_SERDES) + ethtype = "1000Base-SX"; + else + ethtype = "10/100/1000Base-T"; + netdev_info(dev, "attached PHY is %s (%s Ethernet) " - "(WireSpeed[%d])\n", tg3_phy_string(tp), - ((tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100Base-TX" : - ((tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) ? "1000Base-SX" : - "10/100/1000Base-T")), - (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0); + "(WireSpeed[%d])\n", tg3_phy_string(tp), ethtype, + (tp->phy_flags & TG3_PHYFLG_NO_ETH_WIRE_SPEED) == 0); + } netdev_info(dev, "RXcsums[%d] LinkChgREG[%d] MIirq[%d] ASF[%d] TSOcap[%d]\n", (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0, (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0, - (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0, + (tp->phy_flags & TG3_PHYFLG_USE_MI_INTERRUPT) != 0, (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0, (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0); netdev_info(dev, "dma_rwctrl[%08x] dma_mask[%d-bit]\n", diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 0432399ca74..4937bd19096 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1844,6 +1844,10 @@ #define TG3_PCIE_LNKCTL_L1_PLL_PD_DIS 0x00000080 /* 0x7d58 --> 0x7e70 unused */ +#define TG3_PCIE_PHY_TSTCTL 0x00007e2c +#define TG3_PCIE_PHY_TSTCTL_PCIE10 0x00000040 +#define TG3_PCIE_PHY_TSTCTL_PSCRAM 0x00000020 + #define TG3_PCIE_EIDLE_DELAY 0x00007e70 #define TG3_PCIE_EIDLE_DELAY_MASK 0x0000001f #define TG3_PCIE_EIDLE_DELAY_13_CLKS 0x0000000c @@ -2053,8 +2057,9 @@ #define MII_TG3_EXT_STAT 0x11 /* Extended status register */ #define MII_TG3_EXT_STAT_LPASS 0x0100 +#define MII_TG3_RXR_COUNTERS 0x14 /* Local/Remote Receiver Counts */ #define MII_TG3_DSP_RW_PORT 0x15 /* DSP coefficient read/write port */ - +#define MII_TG3_DSP_CONTROL 0x16 /* DSP control register */ #define MII_TG3_DSP_ADDRESS 0x17 /* DSP address register */ #define MII_TG3_DSP_TAP1 0x0001 @@ -2062,6 +2067,7 @@ #define MII_TG3_DSP_AADJ1CH0 0x001f #define MII_TG3_DSP_AADJ1CH3 0x601f #define MII_TG3_DSP_AADJ1CH3_ADCCKADJ 0x0002 +#define MII_TG3_DSP_EXP1_INT_STAT 0x0f01 #define MII_TG3_DSP_EXP8 0x0f08 #define MII_TG3_DSP_EXP8_REJ2MHz 0x0001 #define MII_TG3_DSP_EXP8_AEDW 0x0200 @@ -2157,6 +2163,8 @@ /* APE shared memory. Accessible through BAR1 */ #define TG3_APE_FW_STATUS 0x400c #define APE_FW_STATUS_READY 0x00000100 +#define TG3_APE_FW_FEATURES 0x4010 +#define TG3_APE_FW_FEATURE_NCSI 0x00000002 #define TG3_APE_FW_VERSION 0x4018 #define APE_FW_VERSION_MAJMSK 0xff000000 #define APE_FW_VERSION_MAJSFT 24 @@ -2526,7 +2534,6 @@ struct tg3_link_config { /* When we go in and out of low power mode we need * to swap with this state. */ - int phy_is_low_power; u16 orig_speed; u8 orig_duplex; u8 orig_autoneg; @@ -2767,7 +2774,6 @@ struct tg3 { #define TG3_FLAG_TXD_MBOX_HWBUG 0x00000002 #define TG3_FLAG_RX_CHECKSUMS 0x00000004 #define TG3_FLAG_USE_LINKCHG_REG 0x00000008 -#define TG3_FLAG_USE_MI_INTERRUPT 0x00000010 #define TG3_FLAG_ENABLE_ASF 0x00000020 #define TG3_FLAG_ASPM_WORKAROUND 0x00000040 #define TG3_FLAG_POLL_SERDES 0x00000080 @@ -2789,7 +2795,6 @@ struct tg3 { #define TG3_FLAG_TX_RECOVERY_PENDING 0x00200000 #define TG3_FLAG_WOL_CAP 0x00400000 #define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000 -#define TG3_FLAG_10_100_ONLY 0x01000000 #define TG3_FLAG_PAUSE_AUTONEG 0x02000000 #define TG3_FLAG_CPMU_PRESENT 0x04000000 #define TG3_FLAG_40BIT_DMA_BUG 0x08000000 @@ -2800,22 +2805,15 @@ struct tg3 { u32 tg3_flags2; #define TG3_FLG2_RESTART_TIMER 0x00000001 #define TG3_FLG2_TSO_BUG 0x00000002 -#define TG3_FLG2_NO_ETH_WIRE_SPEED 0x00000004 #define TG3_FLG2_IS_5788 0x00000008 #define TG3_FLG2_MAX_RXPEND_64 0x00000010 #define TG3_FLG2_TSO_CAPABLE 0x00000020 -#define TG3_FLG2_PHY_ADC_BUG 0x00000040 -#define TG3_FLG2_PHY_5704_A0_BUG 0x00000080 -#define TG3_FLG2_PHY_BER_BUG 0x00000100 #define TG3_FLG2_PCI_EXPRESS 0x00000200 #define TG3_FLG2_ASF_NEW_HANDSHAKE 0x00000400 #define TG3_FLG2_HW_AUTONEG 0x00000800 #define TG3_FLG2_IS_NIC 0x00001000 -#define TG3_FLG2_PHY_SERDES 0x00002000 -#define TG3_FLG2_CAPACITIVE_COUPLING 0x00004000 #define TG3_FLG2_FLASH 0x00008000 #define TG3_FLG2_HW_TSO_1 0x00010000 -#define TG3_FLG2_SERDES_PREEMPHASIS 0x00020000 #define TG3_FLG2_5705_PLUS 0x00040000 #define TG3_FLG2_5750_PLUS 0x00080000 #define TG3_FLG2_HW_TSO_3 0x00100000 @@ -2823,10 +2821,6 @@ struct tg3 { #define TG3_FLG2_USING_MSIX 0x00400000 #define TG3_FLG2_USING_MSI_OR_MSIX (TG3_FLG2_USING_MSI | \ TG3_FLG2_USING_MSIX) -#define TG3_FLG2_MII_SERDES 0x00800000 -#define TG3_FLG2_ANY_SERDES (TG3_FLG2_PHY_SERDES | \ - TG3_FLG2_MII_SERDES) -#define TG3_FLG2_PARALLEL_DETECT 0x01000000 #define TG3_FLG2_ICH_WORKAROUND 0x02000000 #define TG3_FLG2_5780_CLASS 0x04000000 #define TG3_FLG2_HW_TSO_2 0x08000000 @@ -2834,9 +2828,7 @@ struct tg3 { TG3_FLG2_HW_TSO_2 | \ TG3_FLG2_HW_TSO_3) #define TG3_FLG2_1SHOT_MSI 0x10000000 -#define TG3_FLG2_PHY_JITTER_BUG 0x20000000 #define TG3_FLG2_NO_FWARE_REPORTED 0x40000000 -#define TG3_FLG2_PHY_ADJUST_TRIM 0x80000000 u32 tg3_flags3; #define TG3_FLG3_NO_NVRAM_ADDR_TRANS 0x00000001 #define TG3_FLG3_ENABLE_APE 0x00000002 @@ -2844,15 +2836,12 @@ struct tg3 { #define TG3_FLG3_5701_DMA_BUG 0x00000008 #define TG3_FLG3_USE_PHYLIB 0x00000010 #define TG3_FLG3_MDIOBUS_INITED 0x00000020 -#define TG3_FLG3_PHY_CONNECTED 0x00000080 #define TG3_FLG3_RGMII_INBAND_DISABLE 0x00000100 #define TG3_FLG3_RGMII_EXT_IBND_RX_EN 0x00000200 #define TG3_FLG3_RGMII_EXT_IBND_TX_EN 0x00000400 #define TG3_FLG3_CLKREQ_BUG 0x00000800 -#define TG3_FLG3_PHY_ENABLE_APD 0x00001000 #define TG3_FLG3_5755_PLUS 0x00002000 #define TG3_FLG3_NO_NVRAM 0x00004000 -#define TG3_FLG3_PHY_IS_FET 0x00010000 #define TG3_FLG3_ENABLE_RSS 0x00020000 #define TG3_FLG3_ENABLE_TSS 0x00040000 #define TG3_FLG3_4G_DMA_BNDRY_BUG 0x00080000 @@ -2860,6 +2849,7 @@ struct tg3 { #define TG3_FLG3_SHORT_DMA_BUG 0x00200000 #define TG3_FLG3_USE_JUMBO_BDFLAG 0x00400000 #define TG3_FLG3_L1PLLPD_EN 0x00800000 +#define TG3_FLG3_5717_PLUS 0x01000000 struct timer_list timer; u16 timer_counter; @@ -2956,6 +2946,27 @@ struct tg3 { (X) == TG3_PHY_ID_BCM57765 || (X) == TG3_PHY_ID_BCM5719C || \ (X) == TG3_PHY_ID_BCM8002) + u32 phy_flags; +#define TG3_PHYFLG_IS_LOW_POWER 0x00000001 +#define TG3_PHYFLG_IS_CONNECTED 0x00000002 +#define TG3_PHYFLG_USE_MI_INTERRUPT 0x00000004 +#define TG3_PHYFLG_PHY_SERDES 0x00000010 +#define TG3_PHYFLG_MII_SERDES 0x00000020 +#define TG3_PHYFLG_ANY_SERDES (TG3_PHYFLG_PHY_SERDES | \ + TG3_PHYFLG_MII_SERDES) +#define TG3_PHYFLG_IS_FET 0x00000040 +#define TG3_PHYFLG_10_100_ONLY 0x00000080 +#define TG3_PHYFLG_ENABLE_APD 0x00000100 +#define TG3_PHYFLG_CAPACITIVE_COUPLING 0x00000200 +#define TG3_PHYFLG_NO_ETH_WIRE_SPEED 0x00000400 +#define TG3_PHYFLG_JITTER_BUG 0x00000800 +#define TG3_PHYFLG_ADJUST_TRIM 0x00001000 +#define TG3_PHYFLG_ADC_BUG 0x00002000 +#define TG3_PHYFLG_5704_A0_BUG 0x00004000 +#define TG3_PHYFLG_BER_BUG 0x00008000 +#define TG3_PHYFLG_SERDES_PREEMPHASIS 0x00010000 +#define TG3_PHYFLG_PARALLEL_DETECT 0x00020000 + u32 led_ctrl; u32 phy_otp; diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 6ad6fe70631..55f3a3e667a 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -149,6 +149,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file) tfile->tun = tun; tun->tfile = tfile; tun->socket.file = file; + netif_carrier_on(tun->dev); dev_hold(tun->dev); sock_hold(tun->socket.sk); atomic_inc(&tfile->count); @@ -162,6 +163,7 @@ static void __tun_detach(struct tun_struct *tun) { /* Detach from net device */ netif_tx_lock_bh(tun->dev); + netif_carrier_off(tun->dev); tun->tfile = NULL; tun->socket.file = NULL; netif_tx_unlock_bh(tun->dev); @@ -736,8 +738,18 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun, gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; else if (sinfo->gso_type & SKB_GSO_UDP) gso.gso_type = VIRTIO_NET_HDR_GSO_UDP; - else - BUG(); + else { + printk(KERN_ERR "tun: unexpected GSO type: " + "0x%x, gso_size %d, hdr_len %d\n", + sinfo->gso_type, gso.gso_size, + gso.hdr_len); + print_hex_dump(KERN_ERR, "tun: ", + DUMP_PREFIX_NONE, + 16, 1, skb->head, + min((int)gso.hdr_len, 64), true); + WARN_ON_ONCE(1); + return -EINVAL; + } if (sinfo->gso_type & SKB_GSO_TCP_ECN) gso.gso_type |= VIRTIO_NET_HDR_GSO_ECN; } else @@ -1564,12 +1576,6 @@ static void tun_set_msglevel(struct net_device *dev, u32 value) #endif } -static u32 tun_get_link(struct net_device *dev) -{ - struct tun_struct *tun = netdev_priv(dev); - return !!tun->tfile; -} - static u32 tun_get_rx_csum(struct net_device *dev) { struct tun_struct *tun = netdev_priv(dev); @@ -1591,7 +1597,7 @@ static const struct ethtool_ops tun_ethtool_ops = { .get_drvinfo = tun_get_drvinfo, .get_msglevel = tun_get_msglevel, .set_msglevel = tun_set_msglevel, - .get_link = tun_get_link, + .get_link = ethtool_op_get_link, .get_rx_csum = tun_get_rx_csum, .set_rx_csum = tun_set_rx_csum }; diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index e17dd743091..8d532f9b50d 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -594,7 +594,7 @@ static void dump_regs(struct ucc_geth_private *ugeth) { int i; - ugeth_info("UCC%d Geth registers:", ugeth->ug_info->uf_info.ucc_num); + ugeth_info("UCC%d Geth registers:", ugeth->ug_info->uf_info.ucc_num + 1); ugeth_info("Base address: 0x%08x", (u32) ugeth->ug_regs); ugeth_info("maccfg1 : addr - 0x%08x, val - 0x%08x", diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 7eab4071ea2..3b03794ac3f 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -44,6 +44,7 @@ #include <linux/usb.h> #include <linux/usb/usbnet.h> #include <linux/slab.h> +#include <linux/kernel.h> #define DRIVER_VERSION "22-Aug-2005" @@ -158,16 +159,6 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf) } EXPORT_SYMBOL_GPL(usbnet_get_endpoints); -static u8 nibble(unsigned char c) -{ - if (likely(isdigit(c))) - return c - '0'; - c = toupper(c); - if (likely(isxdigit(c))) - return 10 + c - 'A'; - return 0; -} - int usbnet_get_ethernet_addr(struct usbnet *dev, int iMACAddress) { int tmp, i; @@ -183,7 +174,7 @@ int usbnet_get_ethernet_addr(struct usbnet *dev, int iMACAddress) } for (i = tmp = 0; i < 6; i++, tmp += 2) dev->net->dev_addr [i] = - (nibble(buf [tmp]) << 4) + nibble(buf [tmp + 1]); + (hex_to_bin(buf[tmp]) << 4) + hex_to_bin(buf[tmp + 1]); return 0; } EXPORT_SYMBOL_GPL(usbnet_get_ethernet_addr); @@ -624,7 +615,7 @@ static void usbnet_terminate_urbs(struct usbnet *dev) while (!skb_queue_empty(&dev->rxq) && !skb_queue_empty(&dev->txq) && !skb_queue_empty(&dev->done)) { - schedule_timeout(UNLINK_TIMEOUT_MS); + schedule_timeout(msecs_to_jiffies(UNLINK_TIMEOUT_MS)); set_current_state(TASK_UNINTERRUPTIBLE); netif_dbg(dev, ifdown, dev->net, "waited for %d urb completions\n", temp); diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 9d64186050f..abe0ff53daf 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -664,8 +664,13 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx, while (len) { u32 buf_size; - buf_size = len > VMXNET3_MAX_TX_BUF_SIZE ? - VMXNET3_MAX_TX_BUF_SIZE : len; + if (len < VMXNET3_MAX_TX_BUF_SIZE) { + buf_size = len; + dw2 |= len; + } else { + buf_size = VMXNET3_MAX_TX_BUF_SIZE; + /* spec says that for TxDesc.len, 0 == 2^14 */ + } tbi = tq->buf_info + tq->tx_ring.next2fill; tbi->map_type = VMXNET3_MAP_SINGLE; @@ -673,13 +678,13 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx, skb->data + buf_offset, buf_size, PCI_DMA_TODEVICE); - tbi->len = buf_size; /* this automatically convert 2^14 to 0 */ + tbi->len = buf_size; gdesc = tq->tx_ring.base + tq->tx_ring.next2fill; BUG_ON(gdesc->txd.gen == tq->tx_ring.gen); gdesc->txd.addr = cpu_to_le64(tbi->dma_addr); - gdesc->dword[2] = cpu_to_le32(dw2 | buf_size); + gdesc->dword[2] = cpu_to_le32(dw2); gdesc->dword[3] = 0; dev_dbg(&adapter->netdev->dev, diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h index 762a6a7763f..2121c735cab 100644 --- a/drivers/net/vmxnet3/vmxnet3_int.h +++ b/drivers/net/vmxnet3/vmxnet3_int.h @@ -68,10 +68,10 @@ /* * Version numbers */ -#define VMXNET3_DRIVER_VERSION_STRING "1.0.13.0-k" +#define VMXNET3_DRIVER_VERSION_STRING "1.0.14.0-k" /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */ -#define VMXNET3_DRIVER_VERSION_NUM 0x01000B00 +#define VMXNET3_DRIVER_VERSION_NUM 0x01000E00 /* diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index 94d87e80abc..c7c5605b372 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c @@ -41,6 +41,8 @@ * ******************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/if_vlan.h> #include <linux/pci.h> #include <linux/slab.h> @@ -144,7 +146,7 @@ vxge_callback_link_up(struct __vxge_hw_device *hldev) vxge_debug_entryexit(VXGE_TRACE, "%s: %s:%d", vdev->ndev->name, __func__, __LINE__); - printk(KERN_NOTICE "%s: Link Up\n", vdev->ndev->name); + netdev_notice(vdev->ndev, "Link Up\n"); vdev->stats.link_up++; netif_carrier_on(vdev->ndev); @@ -168,7 +170,7 @@ vxge_callback_link_down(struct __vxge_hw_device *hldev) vxge_debug_entryexit(VXGE_TRACE, "%s: %s:%d", vdev->ndev->name, __func__, __LINE__); - printk(KERN_NOTICE "%s: Link Down\n", vdev->ndev->name); + netdev_notice(vdev->ndev, "Link Down\n"); vdev->stats.link_down++; netif_carrier_off(vdev->ndev); @@ -2679,7 +2681,7 @@ vxge_open(struct net_device *dev) if (vxge_hw_device_link_state_get(vdev->devh) == VXGE_HW_LINK_UP) { netif_carrier_on(vdev->ndev); - printk(KERN_NOTICE "%s: Link Up\n", vdev->ndev->name); + netdev_notice(vdev->ndev, "Link Up\n"); vdev->stats.link_up++; } @@ -2817,7 +2819,7 @@ int do_vxge_close(struct net_device *dev, int do_io) } netif_carrier_off(vdev->ndev); - printk(KERN_NOTICE "%s: Link Down\n", vdev->ndev->name); + netdev_notice(vdev->ndev, "Link Down\n"); netif_tx_stop_all_queues(vdev->ndev); /* Note that at this point xmit() is stopped by upper layer */ @@ -3844,9 +3846,7 @@ static pci_ers_result_t vxge_io_slot_reset(struct pci_dev *pdev) struct vxgedev *vdev = netdev_priv(netdev); if (pci_enable_device(pdev)) { - printk(KERN_ERR "%s: " - "Cannot re-enable device after reset\n", - VXGE_DRIVER_NAME); + netdev_err(netdev, "Cannot re-enable device after reset\n"); return PCI_ERS_RESULT_DISCONNECT; } @@ -3871,9 +3871,8 @@ static void vxge_io_resume(struct pci_dev *pdev) if (netif_running(netdev)) { if (vxge_open(netdev)) { - printk(KERN_ERR "%s: " - "Can't bring device back up after reset\n", - VXGE_DRIVER_NAME); + netdev_err(netdev, + "Can't bring device back up after reset\n"); return; } } @@ -4430,13 +4429,9 @@ static int __init vxge_starter(void) { int ret = 0; - char version[32]; - snprintf(version, 32, "%s", DRV_VERSION); - printk(KERN_INFO "%s: Copyright(c) 2002-2010 Exar Corp.\n", - VXGE_DRIVER_NAME); - printk(KERN_INFO "%s: Driver version: %s\n", - VXGE_DRIVER_NAME, version); + pr_info("Copyright(c) 2002-2010 Exar Corp.\n"); + pr_info("Driver version: %s\n", DRV_VERSION); verify_bandwidth(); diff --git a/drivers/net/wimax/i2400m/i2400m-usb.h b/drivers/net/wimax/i2400m/i2400m-usb.h index 2d7c96d7e86..eb80243e22d 100644 --- a/drivers/net/wimax/i2400m/i2400m-usb.h +++ b/drivers/net/wimax/i2400m/i2400m-usb.h @@ -152,6 +152,7 @@ enum { /* Device IDs */ USB_DEVICE_ID_I6050 = 0x0186, USB_DEVICE_ID_I6050_2 = 0x0188, + USB_DEVICE_ID_I6250 = 0x0187, }; diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index 0d5081d77dc..d3365ac85dd 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c @@ -491,6 +491,7 @@ int i2400mu_probe(struct usb_interface *iface, switch (id->idProduct) { case USB_DEVICE_ID_I6050: case USB_DEVICE_ID_I6050_2: + case USB_DEVICE_ID_I6250: i2400mu->i6050 = 1; break; default: @@ -739,6 +740,7 @@ static struct usb_device_id i2400mu_id_table[] = { { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050) }, { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050_2) }, + { USB_DEVICE(0x8086, USB_DEVICE_ID_I6250) }, { USB_DEVICE(0x8086, 0x0181) }, { USB_DEVICE(0x8086, 0x1403) }, { USB_DEVICE(0x8086, 0x1405) }, diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index bde2fa8bb63..a105087af96 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -373,8 +373,8 @@ static void adm8211_interrupt_rci(struct ieee80211_hw *dev) pktlen = status & RDES0_STATUS_FL; if (pktlen > RX_PKT_SIZE) { if (net_ratelimit()) - printk(KERN_DEBUG "%s: frame too long (%d)\n", - wiphy_name(dev->wiphy), pktlen); + wiphy_debug(dev->wiphy, "frame too long (%d)\n", + pktlen); pktlen = RX_PKT_SIZE; } @@ -454,10 +454,10 @@ static void adm8211_interrupt_rci(struct ieee80211_hw *dev) static irqreturn_t adm8211_interrupt(int irq, void *dev_id) { -#define ADM8211_INT(x) \ -do { \ - if (unlikely(stsr & ADM8211_STSR_ ## x)) \ - printk(KERN_DEBUG "%s: " #x "\n", wiphy_name(dev->wiphy)); \ +#define ADM8211_INT(x) \ +do { \ + if (unlikely(stsr & ADM8211_STSR_ ## x)) \ + wiphy_debug(dev->wiphy, "%s\n", #x); \ } while (0) struct ieee80211_hw *dev = dev_id; @@ -570,9 +570,9 @@ static int adm8211_write_bbp(struct ieee80211_hw *dev, u8 addr, u8 data) } if (timeout == 0) { - printk(KERN_DEBUG "%s: adm8211_write_bbp(%d,%d) failed" - " prewrite (reg=0x%08x)\n", - wiphy_name(dev->wiphy), addr, data, reg); + wiphy_debug(dev->wiphy, + "adm8211_write_bbp(%d,%d) failed prewrite (reg=0x%08x)\n", + addr, data, reg); return -ETIMEDOUT; } @@ -605,9 +605,9 @@ static int adm8211_write_bbp(struct ieee80211_hw *dev, u8 addr, u8 data) if (timeout == 0) { ADM8211_CSR_WRITE(BBPCTL, ADM8211_CSR_READ(BBPCTL) & ~ADM8211_BBPCTL_WR); - printk(KERN_DEBUG "%s: adm8211_write_bbp(%d,%d) failed" - " postwrite (reg=0x%08x)\n", - wiphy_name(dev->wiphy), addr, data, reg); + wiphy_debug(dev->wiphy, + "adm8211_write_bbp(%d,%d) failed postwrite (reg=0x%08x)\n", + addr, data, reg); return -ETIMEDOUT; } @@ -675,8 +675,8 @@ static int adm8211_rf_set_channel(struct ieee80211_hw *dev, unsigned int chan) break; default: - printk(KERN_DEBUG "%s: unsupported transceiver type %d\n", - wiphy_name(dev->wiphy), priv->transceiver_type); + wiphy_debug(dev->wiphy, "unsupported transceiver type %d\n", + priv->transceiver_type); break; } @@ -732,8 +732,8 @@ static int adm8211_rf_set_channel(struct ieee80211_hw *dev, unsigned int chan) /* Nothing to do for ADMtek BBP */ } else if (priv->bbp_type != ADM8211_TYPE_ADMTEK) - printk(KERN_DEBUG "%s: unsupported BBP type %d\n", - wiphy_name(dev->wiphy), priv->bbp_type); + wiphy_debug(dev->wiphy, "unsupported bbp type %d\n", + priv->bbp_type); ADM8211_RESTORE(); @@ -1027,13 +1027,12 @@ static int adm8211_hw_init_bbp(struct ieee80211_hw *dev) break; default: - printk(KERN_DEBUG "%s: unsupported transceiver %d\n", - wiphy_name(dev->wiphy), priv->transceiver_type); + wiphy_debug(dev->wiphy, "unsupported transceiver %d\n", + priv->transceiver_type); break; } } else - printk(KERN_DEBUG "%s: unsupported BBP %d\n", - wiphy_name(dev->wiphy), priv->bbp_type); + wiphy_debug(dev->wiphy, "unsupported bbp %d\n", priv->bbp_type); ADM8211_CSR_WRITE(SYNRF, 0); @@ -1509,15 +1508,13 @@ static int adm8211_start(struct ieee80211_hw *dev) /* Power up MAC and RF chips */ retval = adm8211_hw_reset(dev); if (retval) { - printk(KERN_ERR "%s: hardware reset failed\n", - wiphy_name(dev->wiphy)); + wiphy_err(dev->wiphy, "hardware reset failed\n"); goto fail; } retval = adm8211_init_rings(dev); if (retval) { - printk(KERN_ERR "%s: failed to initialize rings\n", - wiphy_name(dev->wiphy)); + wiphy_err(dev->wiphy, "failed to initialize rings\n"); goto fail; } @@ -1528,8 +1525,7 @@ static int adm8211_start(struct ieee80211_hw *dev) retval = request_irq(priv->pdev->irq, adm8211_interrupt, IRQF_SHARED, "adm8211", dev); if (retval) { - printk(KERN_ERR "%s: failed to register IRQ handler\n", - wiphy_name(dev->wiphy)); + wiphy_err(dev->wiphy, "failed to register irq handler\n"); goto fail; } @@ -1906,9 +1902,8 @@ static int __devinit adm8211_probe(struct pci_dev *pdev, goto err_free_eeprom; } - printk(KERN_INFO "%s: hwaddr %pM, Rev 0x%02x\n", - wiphy_name(dev->wiphy), dev->wiphy->perm_addr, - pdev->revision); + wiphy_info(dev->wiphy, "hwaddr %pm, rev 0x%02x\n", + dev->wiphy->perm_addr, pdev->revision); return 0; diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 6b605df8a92..1d05445d4ba 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -2931,8 +2931,8 @@ err_out_res: release_region( dev->base_addr, 64 ); err_out_nets: airo_networks_free(ai); - del_airo_dev(ai); err_out_free: + del_airo_dev(ai); free_netdev(dev); return NULL; } @@ -4657,7 +4657,7 @@ static ssize_t proc_write( struct file *file, loff_t *offset ) { loff_t pos = *offset; - struct proc_data *priv = (struct proc_data*)file->private_data; + struct proc_data *priv = file->private_data; if (!priv->wbuffer) return -EINVAL; @@ -4689,7 +4689,7 @@ static int proc_status_open(struct inode *inode, struct file *file) if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; - data = (struct proc_data *)file->private_data; + data = file->private_data; if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) { kfree (file->private_data); return -ENOMEM; @@ -4772,7 +4772,7 @@ static int proc_stats_rid_open( struct inode *inode, if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; - data = (struct proc_data *)file->private_data; + data = file->private_data; if ((data->rbuffer = kmalloc( 4096, GFP_KERNEL )) == NULL) { kfree (file->private_data); return -ENOMEM; @@ -5045,7 +5045,7 @@ static int proc_config_open(struct inode *inode, struct file *file) if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; - data = (struct proc_data *)file->private_data; + data = file->private_data; if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) { kfree (file->private_data); return -ENOMEM; @@ -5127,7 +5127,7 @@ static int proc_config_open(struct inode *inode, struct file *file) static void proc_SSID_on_close(struct inode *inode, struct file *file) { - struct proc_data *data = (struct proc_data *)file->private_data; + struct proc_data *data = file->private_data; struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; struct airo_info *ai = dev->ml_priv; @@ -5163,7 +5163,7 @@ static void proc_SSID_on_close(struct inode *inode, struct file *file) } static void proc_APList_on_close( struct inode *inode, struct file *file ) { - struct proc_data *data = (struct proc_data *)file->private_data; + struct proc_data *data = file->private_data; struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; struct airo_info *ai = dev->ml_priv; @@ -5309,7 +5309,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { memset(key, 0, sizeof(key)); - data = (struct proc_data *)file->private_data; + data = file->private_data; if ( !data->writelen ) return; if (data->wbuffer[0] >= '0' && data->wbuffer[0] <= '3' && @@ -5363,7 +5363,7 @@ static int proc_wepkey_open( struct inode *inode, struct file *file ) if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; memset(&wkr, 0, sizeof(wkr)); - data = (struct proc_data *)file->private_data; + data = file->private_data; if ((data->rbuffer = kzalloc( 180, GFP_KERNEL )) == NULL) { kfree (file->private_data); return -ENOMEM; @@ -5409,7 +5409,7 @@ static int proc_SSID_open(struct inode *inode, struct file *file) if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; - data = (struct proc_data *)file->private_data; + data = file->private_data; if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) { kfree (file->private_data); return -ENOMEM; @@ -5453,7 +5453,7 @@ static int proc_APList_open( struct inode *inode, struct file *file ) { if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; - data = (struct proc_data *)file->private_data; + data = file->private_data; if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) { kfree (file->private_data); return -ENOMEM; @@ -5495,7 +5495,7 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) { if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; - data = (struct proc_data *)file->private_data; + data = file->private_data; if ((data->rbuffer = kmalloc( 1024, GFP_KERNEL )) == NULL) { kfree (file->private_data); return -ENOMEM; diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index cd8caeab86e..d5140a87f07 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -89,22 +89,19 @@ #define DBG_DEFAULTS 0 /* Use our own dbg macro */ -#define at76_dbg(bits, format, arg...) \ - do { \ - if (at76_debug & (bits)) \ - printk(KERN_DEBUG DRIVER_NAME ": " format "\n" , \ - ## arg); \ - } while (0) - -#define at76_dbg_dump(bits, buf, len, format, arg...) \ - do { \ - if (at76_debug & (bits)) { \ - printk(KERN_DEBUG DRIVER_NAME ": " format "\n" , \ - ## arg); \ - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, \ - buf, len); \ - } \ - } while (0) +#define at76_dbg(bits, format, arg...) \ +do { \ + if (at76_debug & (bits)) \ + printk(KERN_DEBUG DRIVER_NAME ": " format "\n", ##arg); \ +} while (0) + +#define at76_dbg_dump(bits, buf, len, format, arg...) \ +do { \ + if (at76_debug & (bits)) { \ + printk(KERN_DEBUG DRIVER_NAME ": " format "\n", ##arg); \ + print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len); \ + } \ +} while (0) static uint at76_debug = DBG_DEFAULTS; @@ -658,8 +655,8 @@ static int at76_get_hw_config(struct at76_priv *priv) exit: kfree(hwcfg); if (ret < 0) - printk(KERN_ERR "%s: cannot get HW Config (error %d)\n", - wiphy_name(priv->hw->wiphy), ret); + wiphy_err(priv->hw->wiphy, "cannot get hw config (error %d)\n", + ret); return ret; } @@ -794,8 +791,9 @@ static int at76_wait_completion(struct at76_priv *priv, int cmd) do { status = at76_get_cmd_status(priv->udev, cmd); if (status < 0) { - printk(KERN_ERR "%s: at76_get_cmd_status failed: %d\n", - wiphy_name(priv->hw->wiphy), status); + wiphy_err(priv->hw->wiphy, + "at76_get_cmd_status failed: %d\n", + status); break; } @@ -810,9 +808,8 @@ static int at76_wait_completion(struct at76_priv *priv, int cmd) schedule_timeout_interruptible(HZ / 10); /* 100 ms */ if (time_after(jiffies, timeout)) { - printk(KERN_ERR - "%s: completion timeout for command %d\n", - wiphy_name(priv->hw->wiphy), cmd); + wiphy_err(priv->hw->wiphy, + "completion timeout for command %d\n", cmd); status = -ETIMEDOUT; break; } @@ -833,9 +830,9 @@ static int at76_set_mib(struct at76_priv *priv, struct set_mib_buffer *buf) ret = at76_wait_completion(priv, CMD_SET_MIB); if (ret != CMD_STATUS_COMPLETE) { - printk(KERN_INFO - "%s: set_mib: at76_wait_completion failed " - "with %d\n", wiphy_name(priv->hw->wiphy), ret); + wiphy_info(priv->hw->wiphy, + "set_mib: at76_wait_completion failed with %d\n", + ret); ret = -EIO; } @@ -855,8 +852,8 @@ static int at76_set_radio(struct at76_priv *priv, int enable) ret = at76_set_card_command(priv->udev, cmd, NULL, 0); if (ret < 0) - printk(KERN_ERR "%s: at76_set_card_command(%d) failed: %d\n", - wiphy_name(priv->hw->wiphy), cmd, ret); + wiphy_err(priv->hw->wiphy, + "at76_set_card_command(%d) failed: %d\n", cmd, ret); else ret = 1; @@ -876,8 +873,8 @@ static int at76_set_pm_mode(struct at76_priv *priv) ret = at76_set_mib(priv, &priv->mib_buf); if (ret < 0) - printk(KERN_ERR "%s: set_mib (pm_mode) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + wiphy_err(priv->hw->wiphy, "set_mib (pm_mode) failed: %d\n", + ret); return ret; } @@ -893,8 +890,8 @@ static int at76_set_preamble(struct at76_priv *priv, u8 type) ret = at76_set_mib(priv, &priv->mib_buf); if (ret < 0) - printk(KERN_ERR "%s: set_mib (preamble) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + wiphy_err(priv->hw->wiphy, "set_mib (preamble) failed: %d\n", + ret); return ret; } @@ -910,8 +907,8 @@ static int at76_set_frag(struct at76_priv *priv, u16 size) ret = at76_set_mib(priv, &priv->mib_buf); if (ret < 0) - printk(KERN_ERR "%s: set_mib (frag threshold) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + wiphy_err(priv->hw->wiphy, + "set_mib (frag threshold) failed: %d\n", ret); return ret; } @@ -927,8 +924,7 @@ static int at76_set_rts(struct at76_priv *priv, u16 size) ret = at76_set_mib(priv, &priv->mib_buf); if (ret < 0) - printk(KERN_ERR "%s: set_mib (rts) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + wiphy_err(priv->hw->wiphy, "set_mib (rts) failed: %d\n", ret); return ret; } @@ -944,8 +940,8 @@ static int at76_set_autorate_fallback(struct at76_priv *priv, int onoff) ret = at76_set_mib(priv, &priv->mib_buf); if (ret < 0) - printk(KERN_ERR "%s: set_mib (autorate fallback) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + wiphy_err(priv->hw->wiphy, + "set_mib (autorate fallback) failed: %d\n", ret); return ret; } @@ -963,8 +959,8 @@ static void at76_dump_mib_mac_addr(struct at76_priv *priv) ret = at76_get_mib(priv->udev, MIB_MAC_ADDR, m, sizeof(struct mib_mac_addr)); if (ret < 0) { - printk(KERN_ERR "%s: at76_get_mib (MAC_ADDR) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + wiphy_err(priv->hw->wiphy, + "at76_get_mib (mac_addr) failed: %d\n", ret); goto exit; } @@ -992,8 +988,8 @@ static void at76_dump_mib_mac_wep(struct at76_priv *priv) ret = at76_get_mib(priv->udev, MIB_MAC_WEP, m, sizeof(struct mib_mac_wep)); if (ret < 0) { - printk(KERN_ERR "%s: at76_get_mib (MAC_WEP) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + wiphy_err(priv->hw->wiphy, + "at76_get_mib (mac_wep) failed: %d\n", ret); goto exit; } @@ -1029,8 +1025,8 @@ static void at76_dump_mib_mac_mgmt(struct at76_priv *priv) ret = at76_get_mib(priv->udev, MIB_MAC_MGMT, m, sizeof(struct mib_mac_mgmt)); if (ret < 0) { - printk(KERN_ERR "%s: at76_get_mib (MAC_MGMT) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + wiphy_err(priv->hw->wiphy, + "at76_get_mib (mac_mgmt) failed: %d\n", ret); goto exit; } @@ -1065,8 +1061,8 @@ static void at76_dump_mib_mac(struct at76_priv *priv) ret = at76_get_mib(priv->udev, MIB_MAC, m, sizeof(struct mib_mac)); if (ret < 0) { - printk(KERN_ERR "%s: at76_get_mib (MAC) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + wiphy_err(priv->hw->wiphy, + "at76_get_mib (mac) failed: %d\n", ret); goto exit; } @@ -1102,8 +1098,8 @@ static void at76_dump_mib_phy(struct at76_priv *priv) ret = at76_get_mib(priv->udev, MIB_PHY, m, sizeof(struct mib_phy)); if (ret < 0) { - printk(KERN_ERR "%s: at76_get_mib (PHY) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + wiphy_err(priv->hw->wiphy, + "at76_get_mib (phy) failed: %d\n", ret); goto exit; } @@ -1135,8 +1131,8 @@ static void at76_dump_mib_local(struct at76_priv *priv) ret = at76_get_mib(priv->udev, MIB_LOCAL, m, sizeof(struct mib_local)); if (ret < 0) { - printk(KERN_ERR "%s: at76_get_mib (LOCAL) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + wiphy_err(priv->hw->wiphy, + "at76_get_mib (local) failed: %d\n", ret); goto exit; } @@ -1161,8 +1157,8 @@ static void at76_dump_mib_mdomain(struct at76_priv *priv) ret = at76_get_mib(priv->udev, MIB_MDOMAIN, m, sizeof(struct mib_mdomain)); if (ret < 0) { - printk(KERN_ERR "%s: at76_get_mib (MDOMAIN) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + wiphy_err(priv->hw->wiphy, + "at76_get_mib (mdomain) failed: %d\n", ret); goto exit; } @@ -1233,16 +1229,16 @@ static int at76_submit_rx_urb(struct at76_priv *priv) struct sk_buff *skb = priv->rx_skb; if (!priv->rx_urb) { - printk(KERN_ERR "%s: %s: priv->rx_urb is NULL\n", - wiphy_name(priv->hw->wiphy), __func__); + wiphy_err(priv->hw->wiphy, "%s: priv->rx_urb is null\n", + __func__); return -EFAULT; } if (!skb) { skb = dev_alloc_skb(sizeof(struct at76_rx_buffer)); if (!skb) { - printk(KERN_ERR "%s: cannot allocate rx skbuff\n", - wiphy_name(priv->hw->wiphy)); + wiphy_err(priv->hw->wiphy, + "cannot allocate rx skbuff\n"); ret = -ENOMEM; goto exit; } @@ -1261,15 +1257,14 @@ static int at76_submit_rx_urb(struct at76_priv *priv) at76_dbg(DBG_DEVSTART, "usb_submit_urb returned -ENODEV"); else - printk(KERN_ERR "%s: rx, usb_submit_urb failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + wiphy_err(priv->hw->wiphy, + "rx, usb_submit_urb failed: %d\n", ret); } exit: if (ret < 0 && ret != -ENODEV) - printk(KERN_ERR "%s: cannot submit rx urb - please unload the " - "driver and/or power cycle the device\n", - wiphy_name(priv->hw->wiphy)); + wiphy_err(priv->hw->wiphy, + "cannot submit rx urb - please unload the driver and/or power cycle the device\n"); return ret; } @@ -1438,8 +1433,8 @@ static int at76_startup_device(struct at76_priv *priv) ret = at76_set_card_command(priv->udev, CMD_STARTUP, &priv->card_config, sizeof(struct at76_card_config)); if (ret < 0) { - printk(KERN_ERR "%s: at76_set_card_command failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + wiphy_err(priv->hw->wiphy, "at76_set_card_command failed: %d\n", + ret); return ret; } @@ -1504,8 +1499,8 @@ static void at76_work_set_promisc(struct work_struct *work) ret = at76_set_mib(priv, &priv->mib_buf); if (ret < 0) - printk(KERN_ERR "%s: set_mib (promiscuous_mode) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + wiphy_err(priv->hw->wiphy, + "set_mib (promiscuous_mode) failed: %d\n", ret); mutex_unlock(&priv->mtx); } @@ -1668,16 +1663,16 @@ static int at76_join(struct at76_priv *priv) sizeof(struct at76_req_join)); if (ret < 0) { - printk(KERN_ERR "%s: at76_set_card_command failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + wiphy_err(priv->hw->wiphy, "at76_set_card_command failed: %d\n", + ret); return 0; } ret = at76_wait_completion(priv, CMD_JOIN); at76_dbg(DBG_MAC80211, "%s: CMD_JOIN returned: 0x%02x", __func__, ret); if (ret != CMD_STATUS_COMPLETE) { - printk(KERN_ERR "%s: at76_wait_completion failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + wiphy_err(priv->hw->wiphy, "at76_wait_completion failed: %d\n", + ret); return 0; } @@ -1745,8 +1740,8 @@ static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb) at76_dbg(DBG_MAC80211, "%s()", __func__); if (priv->tx_urb->status == -EINPROGRESS) { - printk(KERN_ERR "%s: %s called while tx urb is pending\n", - wiphy_name(priv->hw->wiphy), __func__); + wiphy_err(priv->hw->wiphy, + "%s called while tx urb is pending\n", __func__); return NETDEV_TX_BUSY; } @@ -1794,13 +1789,12 @@ static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb) submit_len, at76_mac80211_tx_callback, priv); ret = usb_submit_urb(priv->tx_urb, GFP_ATOMIC); if (ret) { - printk(KERN_ERR "%s: error in tx submit urb: %d\n", - wiphy_name(priv->hw->wiphy), ret); + wiphy_err(priv->hw->wiphy, "error in tx submit urb: %d\n", ret); if (ret == -EINVAL) - printk(KERN_ERR - "%s: -EINVAL: tx urb %p hcpriv %p complete %p\n", - wiphy_name(priv->hw->wiphy), priv->tx_urb, - priv->tx_urb->hcpriv, priv->tx_urb->complete); + wiphy_err(priv->hw->wiphy, + "-einval: tx urb %p hcpriv %p complete %p\n", + priv->tx_urb, + priv->tx_urb->hcpriv, priv->tx_urb->complete); } return 0; @@ -1817,8 +1811,8 @@ static int at76_mac80211_start(struct ieee80211_hw *hw) ret = at76_submit_rx_urb(priv); if (ret < 0) { - printk(KERN_ERR "%s: open: submit_rx_urb failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + wiphy_err(priv->hw->wiphy, "open: submit_rx_urb failed: %d\n", + ret); goto error; } @@ -2316,14 +2310,12 @@ static int at76_init_new_device(struct at76_priv *priv, priv->mac80211_registered = 1; - printk(KERN_INFO "%s: USB %s, MAC %pM, firmware %d.%d.%d-%d\n", - wiphy_name(priv->hw->wiphy), - dev_name(&interface->dev), priv->mac_addr, - priv->fw_version.major, priv->fw_version.minor, - priv->fw_version.patch, priv->fw_version.build); - printk(KERN_INFO "%s: regulatory domain 0x%02x: %s\n", - wiphy_name(priv->hw->wiphy), - priv->regulatory_domain, priv->domain->name); + wiphy_info(priv->hw->wiphy, "usb %s, mac %pm, firmware %d.%d.%d-%d\n", + dev_name(&interface->dev), priv->mac_addr, + priv->fw_version.major, priv->fw_version.minor, + priv->fw_version.patch, priv->fw_version.build); + wiphy_info(priv->hw->wiphy, "regulatory domain 0x%02x: %s\n", + priv->regulatory_domain, priv->domain->name); exit: return ret; @@ -2485,7 +2477,7 @@ static void at76_disconnect(struct usb_interface *interface) if (!priv) return; - printk(KERN_INFO "%s: disconnecting\n", wiphy_name(priv->hw->wiphy)); + wiphy_info(priv->hw->wiphy, "disconnecting\n"); at76_delete_device(priv); dev_printk(KERN_INFO, &interface->dev, "disconnected\n"); } diff --git a/drivers/net/wireless/ath/ar9170/cmd.c b/drivers/net/wireless/ath/ar9170/cmd.c index cf6f5c4174a..4604de09a8b 100644 --- a/drivers/net/wireless/ath/ar9170/cmd.c +++ b/drivers/net/wireless/ath/ar9170/cmd.c @@ -48,8 +48,7 @@ int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len) err = ar->exec_cmd(ar, AR9170_CMD_WMEM, len, (u8 *) data, 0, NULL); if (err) - printk(KERN_DEBUG "%s: writing memory failed\n", - wiphy_name(ar->hw->wiphy)); + wiphy_debug(ar->hw->wiphy, "writing memory failed\n"); return err; } @@ -67,8 +66,8 @@ int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val) err = ar->exec_cmd(ar, AR9170_CMD_WREG, sizeof(buf), (u8 *) buf, 0, NULL); if (err) - printk(KERN_DEBUG "%s: writing reg %#x (val %#x) failed\n", - wiphy_name(ar->hw->wiphy), reg, val); + wiphy_debug(ar->hw->wiphy, "writing reg %#x (val %#x) failed\n", + reg, val); return err; } diff --git a/drivers/net/wireless/ath/ar9170/led.c b/drivers/net/wireless/ath/ar9170/led.c index 86c4e79f6bc..832d90087f8 100644 --- a/drivers/net/wireless/ath/ar9170/led.c +++ b/drivers/net/wireless/ath/ar9170/led.c @@ -133,8 +133,8 @@ static int ar9170_register_led(struct ar9170 *ar, int i, char *name, err = led_classdev_register(wiphy_dev(ar->hw->wiphy), &ar->leds[i].l); if (err) - printk(KERN_ERR "%s: failed to register %s LED (%d).\n", - wiphy_name(ar->hw->wiphy), ar->leds[i].name, err); + wiphy_err(ar->hw->wiphy, "failed to register %s LED (%d).\n", + ar->leds[i].name, err); else ar->leds[i].registered = true; diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 2abc8757899..c67b05f3bcb 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -198,12 +198,13 @@ static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; struct ieee80211_hdr *hdr = (void *) txc->frame_data; - printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] s:%d " - "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n", - wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb), - ieee80211_get_DA(hdr), ar9170_get_seq_h(hdr), - le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control), - jiffies_to_msecs(arinfo->timeout - jiffies)); + wiphy_debug(ar->hw->wiphy, + "=> FRAME [skb:%p, q:%d, DA:[%pM] s:%d " + "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n", + skb, skb_get_queue_mapping(skb), + ieee80211_get_DA(hdr), ar9170_get_seq_h(hdr), + le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control), + jiffies_to_msecs(arinfo->timeout - jiffies)); } static void __ar9170_dump_txqueue(struct ar9170 *ar, @@ -213,8 +214,8 @@ static void __ar9170_dump_txqueue(struct ar9170 *ar, int i = 0; printk(KERN_DEBUG "---[ cut here ]---\n"); - printk(KERN_DEBUG "%s: %d entries in queue.\n", - wiphy_name(ar->hw->wiphy), skb_queue_len(queue)); + wiphy_debug(ar->hw->wiphy, "%d entries in queue.\n", + skb_queue_len(queue)); skb_queue_walk(queue, skb) { printk(KERN_DEBUG "index:%d =>\n", i++); @@ -244,15 +245,14 @@ static void __ar9170_dump_txstats(struct ar9170 *ar) { int i; - printk(KERN_DEBUG "%s: QoS queue stats\n", - wiphy_name(ar->hw->wiphy)); + wiphy_debug(ar->hw->wiphy, "qos queue stats\n"); for (i = 0; i < __AR9170_NUM_TXQ; i++) - printk(KERN_DEBUG "%s: queue:%d limit:%d len:%d waitack:%d " - " stopped:%d\n", wiphy_name(ar->hw->wiphy), i, - ar->tx_stats[i].limit, ar->tx_stats[i].len, - skb_queue_len(&ar->tx_status[i]), - ieee80211_queue_stopped(ar->hw, i)); + wiphy_debug(ar->hw->wiphy, + "queue:%d limit:%d len:%d waitack:%d stopped:%d\n", + i, ar->tx_stats[i].limit, ar->tx_stats[i].len, + skb_queue_len(&ar->tx_status[i]), + ieee80211_queue_stopped(ar->hw, i)); } #endif /* AR9170_QUEUE_STOP_DEBUG */ @@ -274,9 +274,9 @@ static void ar9170_recycle_expired(struct ar9170 *ar, if (time_is_before_jiffies(arinfo->timeout)) { #ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: [%ld > %ld] frame expired => " - "recycle\n", wiphy_name(ar->hw->wiphy), - jiffies, arinfo->timeout); + wiphy_debug(ar->hw->wiphy, + "[%ld > %ld] frame expired => recycle\n", + jiffies, arinfo->timeout); ar9170_print_txheader(ar, skb); #endif /* AR9170_QUEUE_DEBUG */ __skb_unlink(skb, queue); @@ -317,8 +317,8 @@ static void ar9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, break; default: - printk(KERN_ERR "%s: invalid tx_status response (%x).\n", - wiphy_name(ar->hw->wiphy), tx_status); + wiphy_err(ar->hw->wiphy, + "invalid tx_status response (%x)\n", tx_status); break; } @@ -339,8 +339,7 @@ void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) if (ar->tx_stats[queue].len < AR9170_NUM_TX_LIMIT_SOFT) { #ifdef AR9170_QUEUE_STOP_DEBUG - printk(KERN_DEBUG "%s: wake queue %d\n", - wiphy_name(ar->hw->wiphy), queue); + wiphy_debug(ar->hw->wiphy, "wake queue %d\n", queue); __ar9170_dump_txstats(ar); #endif /* AR9170_QUEUE_STOP_DEBUG */ ieee80211_wake_queue(ar->hw, queue); @@ -387,9 +386,9 @@ static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar, if (mac && compare_ether_addr(ieee80211_get_DA(hdr), mac)) { #ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: skip frame => DA %pM != %pM\n", - wiphy_name(ar->hw->wiphy), mac, - ieee80211_get_DA(hdr)); + wiphy_debug(ar->hw->wiphy, + "skip frame => da %pm != %pm\n", + mac, ieee80211_get_DA(hdr)); ar9170_print_txheader(ar, skb); #endif /* AR9170_QUEUE_DEBUG */ continue; @@ -400,8 +399,8 @@ static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar, if ((rate != AR9170_TX_INVALID_RATE) && (r != rate)) { #ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: skip frame => rate %d != %d\n", - wiphy_name(ar->hw->wiphy), rate, r); + wiphy_debug(ar->hw->wiphy, + "skip frame => rate %d != %d\n", rate, r); ar9170_print_txheader(ar, skb); #endif /* AR9170_QUEUE_DEBUG */ continue; @@ -413,9 +412,9 @@ static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar, } #ifdef AR9170_QUEUE_DEBUG - printk(KERN_ERR "%s: ESS:[%pM] does not have any " - "outstanding frames in queue.\n", - wiphy_name(ar->hw->wiphy), mac); + wiphy_err(ar->hw->wiphy, + "ESS:[%pM] does not have any outstanding frames in queue.\n", + mac); __ar9170_dump_txqueue(ar, queue); #endif /* AR9170_QUEUE_DEBUG */ spin_unlock_irqrestore(&queue->lock, flags); @@ -444,8 +443,8 @@ static void ar9170_tx_janitor(struct work_struct *work) for (i = 0; i < __AR9170_NUM_TXQ; i++) { #ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: garbage collector scans queue:%d\n", - wiphy_name(ar->hw->wiphy), i); + wiphy_debug(ar->hw->wiphy, "garbage collector scans queue:%d\n", + i); ar9170_dump_txqueue(ar, &ar->tx_pending[i]); ar9170_dump_txqueue(ar, &ar->tx_status[i]); #endif /* AR9170_QUEUE_DEBUG */ @@ -495,8 +494,9 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) u32 q = (phy & AR9170_TX_PHY_QOS_MASK) >> AR9170_TX_PHY_QOS_SHIFT; #ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: recv tx_status for %pM, p:%08x, q:%d\n", - wiphy_name(ar->hw->wiphy), cmd->tx_status.dst, phy, q); + wiphy_debug(ar->hw->wiphy, + "recv tx_status for %pm, p:%08x, q:%d\n", + cmd->tx_status.dst, phy, q); #endif /* AR9170_QUEUE_DEBUG */ skb = ar9170_get_queued_skb(ar, cmd->tx_status.dst, @@ -582,7 +582,7 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) break; default: - printk(KERN_INFO "received unhandled event %x\n", cmd->type); + pr_info("received unhandled event %x\n", cmd->type); print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len); break; } @@ -675,9 +675,9 @@ static int ar9170_rx_mac_status(struct ar9170 *ar, /* TODO: update netdevice's RX dropped/errors statistics */ if (ar9170_nag_limiter(ar)) - printk(KERN_DEBUG "%s: received frame with " - "suspicious error code (%#x).\n", - wiphy_name(ar->hw->wiphy), error); + wiphy_debug(ar->hw->wiphy, + "received frame with suspicious error code (%#x).\n", + error); return -EINVAL; } @@ -704,9 +704,9 @@ static int ar9170_rx_mac_status(struct ar9170 *ar, break; default: if (ar9170_nag_limiter(ar)) - printk(KERN_ERR "%s: invalid plcp cck rate " - "(%x).\n", wiphy_name(ar->hw->wiphy), - head->plcp[0]); + wiphy_err(ar->hw->wiphy, + "invalid plcp cck rate (%x).\n", + head->plcp[0]); return -EINVAL; } break; @@ -740,9 +740,9 @@ static int ar9170_rx_mac_status(struct ar9170 *ar, break; default: if (ar9170_nag_limiter(ar)) - printk(KERN_ERR "%s: invalid plcp ofdm rate " - "(%x).\n", wiphy_name(ar->hw->wiphy), - head->plcp[0]); + wiphy_err(ar->hw->wiphy, + "invalid plcp ofdm rate (%x).\n", + head->plcp[0]); return -EINVAL; } if (status->band == IEEE80211_BAND_2GHZ) @@ -761,8 +761,7 @@ static int ar9170_rx_mac_status(struct ar9170 *ar, default: if (ar9170_nag_limiter(ar)) - printk(KERN_ERR "%s: invalid modulation\n", - wiphy_name(ar->hw->wiphy)); + wiphy_err(ar->hw->wiphy, "invalid modulation\n"); return -EINVAL; } @@ -863,8 +862,8 @@ static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) ar->rx_mpdu.has_plcp = true; } else { if (ar9170_nag_limiter(ar)) - printk(KERN_ERR "%s: plcp info is clipped.\n", - wiphy_name(ar->hw->wiphy)); + wiphy_err(ar->hw->wiphy, + "plcp info is clipped.\n"); return ; } break; @@ -877,8 +876,8 @@ static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) phy = (void *)(buf + mpdu_len); } else { if (ar9170_nag_limiter(ar)) - printk(KERN_ERR "%s: frame tail is clipped.\n", - wiphy_name(ar->hw->wiphy)); + wiphy_err(ar->hw->wiphy, + "frame tail is clipped.\n"); return ; } @@ -888,9 +887,8 @@ static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) if (!ar9170_nag_limiter(ar)) return ; - printk(KERN_ERR "%s: rx stream did not start " - "with a first_mpdu frame tag.\n", - wiphy_name(ar->hw->wiphy)); + wiphy_err(ar->hw->wiphy, + "rx stream did not start with a first_mpdu frame tag.\n"); return ; } @@ -954,8 +952,8 @@ void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb) if (!ar->rx_failover_missing) { /* this is no "short read". */ if (ar9170_nag_limiter(ar)) { - printk(KERN_ERR "%s: missing tag!\n", - wiphy_name(ar->hw->wiphy)); + wiphy_err(ar->hw->wiphy, + "missing tag!\n"); goto err_telluser; } else goto err_silent; @@ -963,9 +961,8 @@ void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb) if (ar->rx_failover_missing > tlen) { if (ar9170_nag_limiter(ar)) { - printk(KERN_ERR "%s: possible multi " - "stream corruption!\n", - wiphy_name(ar->hw->wiphy)); + wiphy_err(ar->hw->wiphy, + "possible multi stream corruption!\n"); goto err_telluser; } else goto err_silent; @@ -997,9 +994,8 @@ void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb) if (ar->rx_failover_missing) { /* TODO: handle double stream corruption. */ if (ar9170_nag_limiter(ar)) { - printk(KERN_ERR "%s: double rx stream " - "corruption!\n", - wiphy_name(ar->hw->wiphy)); + wiphy_err(ar->hw->wiphy, + "double rx stream corruption!\n"); goto err_telluser; } else goto err_silent; @@ -1042,9 +1038,9 @@ void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb) if (tlen) { if (net_ratelimit()) - printk(KERN_ERR "%s: %d bytes of unprocessed " - "data left in rx stream!\n", - wiphy_name(ar->hw->wiphy), tlen); + wiphy_err(ar->hw->wiphy, + "%d bytes of unprocessed data left in rx stream!\n", + tlen); goto err_telluser; } @@ -1052,10 +1048,9 @@ void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb) return ; err_telluser: - printk(KERN_ERR "%s: damaged RX stream data [want:%d, " - "data:%d, rx:%d, pending:%d ]\n", - wiphy_name(ar->hw->wiphy), clen, wlen, tlen, - ar->rx_failover_missing); + wiphy_err(ar->hw->wiphy, + "damaged RX stream data [want:%d, data:%d, rx:%d, pending:%d ]\n", + clen, wlen, tlen, ar->rx_failover_missing); if (ar->rx_failover_missing) print_hex_dump_bytes("rxbuf:", DUMP_PREFIX_OFFSET, @@ -1065,9 +1060,8 @@ err_telluser: print_hex_dump_bytes("stream:", DUMP_PREFIX_OFFSET, skb->data, skb->len); - printk(KERN_ERR "%s: please check your hardware and cables, if " - "you see this message frequently.\n", - wiphy_name(ar->hw->wiphy)); + wiphy_err(ar->hw->wiphy, + "If you see this message frequently, please check your hardware and cables.\n"); err_silent: if (ar->rx_failover_missing) { @@ -1384,10 +1378,10 @@ static void ar9170_tx(struct ar9170 *ar) if (remaining_space < frames) { #ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: tx quota reached queue:%d, " - "remaining slots:%d, needed:%d\n", - wiphy_name(ar->hw->wiphy), i, remaining_space, - frames); + wiphy_debug(ar->hw->wiphy, + "tx quota reached queue:%d, " + "remaining slots:%d, needed:%d\n", + i, remaining_space, frames); #endif /* AR9170_QUEUE_DEBUG */ frames = remaining_space; } @@ -1396,18 +1390,14 @@ static void ar9170_tx(struct ar9170 *ar) ar->tx_stats[i].count += frames; if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) { #ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: queue %d full\n", - wiphy_name(ar->hw->wiphy), i); - - printk(KERN_DEBUG "%s: stuck frames: ===>\n", - wiphy_name(ar->hw->wiphy)); + wiphy_debug(ar->hw->wiphy, "queue %d full\n", i); + wiphy_debug(ar->hw->wiphy, "stuck frames: ===>\n"); ar9170_dump_txqueue(ar, &ar->tx_pending[i]); ar9170_dump_txqueue(ar, &ar->tx_status[i]); #endif /* AR9170_QUEUE_DEBUG */ #ifdef AR9170_QUEUE_STOP_DEBUG - printk(KERN_DEBUG "%s: stop queue %d\n", - wiphy_name(ar->hw->wiphy), i); + wiphy_debug(ar->hw->wiphy, "stop queue %d\n", i); __ar9170_dump_txstats(ar); #endif /* AR9170_QUEUE_STOP_DEBUG */ ieee80211_stop_queue(ar->hw, i); @@ -1435,8 +1425,7 @@ static void ar9170_tx(struct ar9170 *ar) msecs_to_jiffies(AR9170_TX_TIMEOUT); #ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: send frame q:%d =>\n", - wiphy_name(ar->hw->wiphy), i); + wiphy_debug(ar->hw->wiphy, "send frame q:%d =>\n", i); ar9170_print_txheader(ar, skb); #endif /* AR9170_QUEUE_DEBUG */ @@ -1453,26 +1442,25 @@ static void ar9170_tx(struct ar9170 *ar) } #ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: ar9170_tx report for queue %d\n", - wiphy_name(ar->hw->wiphy), i); + wiphy_debug(ar->hw->wiphy, + "ar9170_tx report for queue %d\n", i); - printk(KERN_DEBUG "%s: unprocessed pending frames left:\n", - wiphy_name(ar->hw->wiphy)); + wiphy_debug(ar->hw->wiphy, + "unprocessed pending frames left:\n"); ar9170_dump_txqueue(ar, &ar->tx_pending[i]); #endif /* AR9170_QUEUE_DEBUG */ if (unlikely(frames_failed)) { #ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: frames failed %d =>\n", - wiphy_name(ar->hw->wiphy), frames_failed); + wiphy_debug(ar->hw->wiphy, + "frames failed %d =>\n", frames_failed); #endif /* AR9170_QUEUE_DEBUG */ spin_lock_irqsave(&ar->tx_stats_lock, flags); ar->tx_stats[i].len -= frames_failed; ar->tx_stats[i].count -= frames_failed; #ifdef AR9170_QUEUE_STOP_DEBUG - printk(KERN_DEBUG "%s: wake queue %d\n", - wiphy_name(ar->hw->wiphy), i); + wiphy_debug(ar->hw->wiphy, "wake queue %d\n", i); __ar9170_dump_txstats(ar); #endif /* AR9170_QUEUE_STOP_DEBUG */ ieee80211_wake_queue(ar->hw, i); @@ -1917,6 +1905,24 @@ static int ar9170_get_stats(struct ieee80211_hw *hw, return 0; } +static int ar9170_get_survey(struct ieee80211_hw *hw, int idx, + struct survey_info *survey) +{ + struct ar9170 *ar = hw->priv; + struct ieee80211_conf *conf = &hw->conf; + + if (idx != 0) + return -ENOENT; + + /* TODO: update noise value, e.g. call ar9170_set_channel */ + + survey->channel = conf->channel; + survey->filled = SURVEY_INFO_NOISE_DBM; + survey->noise = ar->noise[0]; + + return 0; +} + static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *param) { @@ -1969,6 +1975,7 @@ static const struct ieee80211_ops ar9170_ops = { .get_tsf = ar9170_op_get_tsf, .set_key = ar9170_set_key, .get_stats = ar9170_get_stats, + .get_survey = ar9170_get_survey, .ampdu_action = ar9170_ampdu_action, }; diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c index 45a415ea809..0dbfcf79ac9 100644 --- a/drivers/net/wireless/ath/ar9170/phy.c +++ b/drivers/net/wireless/ath/ar9170/phy.c @@ -670,8 +670,7 @@ static int ar9170_init_rf_banks_0_7(struct ar9170 *ar, bool band5ghz) ar9170_regwrite_finish(); err = ar9170_regwrite_result(); if (err) - printk(KERN_ERR "%s: rf init failed\n", - wiphy_name(ar->hw->wiphy)); + wiphy_err(ar->hw->wiphy, "rf init failed\n"); return err; } @@ -1702,9 +1701,8 @@ int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, 0x200 | ar->phy_heavy_clip); if (err) { if (ar9170_nag_limiter(ar)) - printk(KERN_ERR "%s: failed to set " - "heavy clip\n", - wiphy_name(ar->hw->wiphy)); + wiphy_err(ar->hw->wiphy, + "failed to set heavy clip\n"); } } diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 20328bdd138..0d5de2574dd 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -388,7 +388,7 @@ static int ath5k_init(struct ath5k_softc *sc); static int ath5k_stop_locked(struct ath5k_softc *sc); static int ath5k_stop_hw(struct ath5k_softc *sc); static irqreturn_t ath5k_intr(int irq, void *dev_id); -static void ath5k_tasklet_reset(unsigned long data); +static void ath5k_reset_work(struct work_struct *work); static void ath5k_tasklet_calibrate(unsigned long data); @@ -831,11 +831,12 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); - tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc); + INIT_WORK(&sc->reset_work, ath5k_reset_work); + ret = ath5k_eeprom_read_mac(ah, mac); if (ret) { ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n", @@ -1727,8 +1728,6 @@ ath5k_rx_stop(struct ath5k_softc *sc) ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */ ath5k_debug_printrxbuffs(sc, ah); - - sc->rxlink = NULL; /* just in case */ } static unsigned int @@ -2294,8 +2293,8 @@ err_unmap: * frame contents are done as needed and the slot time is * also adjusted based on current state. * - * This is called from software irq context (beacontq or restq - * tasklets) or user context from ath5k_beacon_config. + * This is called from software irq context (beacontq tasklets) + * or user context from ath5k_beacon_config. */ static void ath5k_beacon_send(struct ath5k_softc *sc) @@ -2328,7 +2327,7 @@ ath5k_beacon_send(struct ath5k_softc *sc) sc->bmisscount); ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "stuck beacon, resetting\n"); - tasklet_schedule(&sc->restq); + ieee80211_queue_work(sc->hw, &sc->reset_work); } return; } @@ -2632,12 +2631,20 @@ ath5k_stop_locked(struct ath5k_softc *sc) if (!test_bit(ATH_STAT_INVALID, sc->status)) { ath5k_rx_stop(sc); ath5k_hw_phy_disable(ah); - } else - sc->rxlink = NULL; + } return 0; } +static void stop_tasklets(struct ath5k_softc *sc) +{ + tasklet_kill(&sc->rxtq); + tasklet_kill(&sc->txtq); + tasklet_kill(&sc->calib); + tasklet_kill(&sc->beacontq); + tasklet_kill(&sc->ani_tasklet); +} + /* * Stop the device, grabbing the top-level lock to protect * against concurrent entry through ath5k_init (which can happen @@ -2682,12 +2689,7 @@ ath5k_stop_hw(struct ath5k_softc *sc) mmiowb(); mutex_unlock(&sc->lock); - tasklet_kill(&sc->rxtq); - tasklet_kill(&sc->txtq); - tasklet_kill(&sc->restq); - tasklet_kill(&sc->calib); - tasklet_kill(&sc->beacontq); - tasklet_kill(&sc->ani_tasklet); + stop_tasklets(sc); ath5k_rfkill_hw_stop(sc->ah); @@ -2737,7 +2739,7 @@ ath5k_intr(int irq, void *dev_id) */ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "fatal int, resetting\n"); - tasklet_schedule(&sc->restq); + ieee80211_queue_work(sc->hw, &sc->reset_work); } else if (unlikely(status & AR5K_INT_RXORN)) { /* * Receive buffers are full. Either the bus is busy or @@ -2752,7 +2754,7 @@ ath5k_intr(int irq, void *dev_id) if (ah->ah_mac_srev < AR5K_SREV_AR5212) { ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "rx overrun, resetting\n"); - tasklet_schedule(&sc->restq); + ieee80211_queue_work(sc->hw, &sc->reset_work); } else tasklet_schedule(&sc->rxtq); @@ -2766,7 +2768,7 @@ ath5k_intr(int irq, void *dev_id) * RXE bit is written, but it doesn't work at * least on older hardware revs. */ - sc->rxlink = NULL; + sc->stats.rxeol_intr++; } if (status & AR5K_INT_TXURN) { /* bump tx trigger level */ @@ -2799,14 +2801,6 @@ ath5k_intr(int irq, void *dev_id) return IRQ_HANDLED; } -static void -ath5k_tasklet_reset(unsigned long data) -{ - struct ath5k_softc *sc = (void *)data; - - ath5k_reset(sc, sc->curchan); -} - /* * Periodically recalibrate the PHY to account * for temperature/environment changes. @@ -2830,7 +2824,7 @@ ath5k_tasklet_calibrate(unsigned long data) * to load new gain values. */ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n"); - ath5k_reset(sc, sc->curchan); + ieee80211_queue_work(sc->hw, &sc->reset_work); } if (ath5k_hw_phy_calibrate(ah, sc->curchan)) ATH5K_ERR(sc, "calibration of channel %u failed\n", @@ -2934,6 +2928,8 @@ drop_packet: /* * Reset the hardware. If chan is not NULL, then also pause rx/tx * and change to the given channel. + * + * This should be called with sc->lock. */ static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) @@ -2943,8 +2939,11 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); + ath5k_hw_set_imr(ah, 0); + synchronize_irq(sc->pdev->irq); + stop_tasklets(sc); + if (chan) { - ath5k_hw_set_imr(ah, 0); ath5k_txq_cleanup(sc); ath5k_rx_stop(sc); @@ -2990,6 +2989,16 @@ err: return ret; } +static void ath5k_reset_work(struct work_struct *work) +{ + struct ath5k_softc *sc = container_of(work, struct ath5k_softc, + reset_work); + + mutex_lock(&sc->lock); + ath5k_reset(sc, sc->curchan); + mutex_unlock(&sc->lock); +} + static int ath5k_start(struct ieee80211_hw *hw) { return ath5k_init(hw->priv); diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 56221bc7c8c..dc1241f9c4e 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -47,6 +47,7 @@ #include <linux/if_ether.h> #include <linux/leds.h> #include <linux/rfkill.h> +#include <linux/workqueue.h> #include "ath5k.h" #include "debug.h" @@ -136,6 +137,7 @@ struct ath5k_statistics { unsigned int mib_intr; unsigned int rxorn_intr; + unsigned int rxeol_intr; }; #if CHAN_DEBUG @@ -189,7 +191,7 @@ struct ath5k_softc { unsigned int led_pin, /* GPIO pin for driving LED */ led_on; /* pin setting for LED on */ - struct tasklet_struct restq; /* reset tasklet */ + struct work_struct reset_work; /* deferred chip reset */ unsigned int rxbufsize; /* rx size based on mtu */ struct list_head rxbuf; /* receive buffer */ diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 8c638865c71..4cccc29964f 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -239,6 +239,9 @@ static ssize_t read_file_beacon(struct file *file, char __user *user_buf, "TSF\t\t0x%016llx\tTU: %08x\n", (unsigned long long)tsf, TSF_TO_TU(tsf)); + if (len > sizeof(buf)) + len = sizeof(buf); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -279,7 +282,7 @@ static ssize_t write_file_reset(struct file *file, { struct ath5k_softc *sc = file->private_data; ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "debug file triggered reset\n"); - tasklet_schedule(&sc->restq); + ieee80211_queue_work(sc->hw, &sc->reset_work); return count; } @@ -334,6 +337,9 @@ static ssize_t read_file_debug(struct file *file, char __user *user_buf, sc->debug.level == dbg_info[i].level ? '+' : ' ', dbg_info[i].level, dbg_info[i].desc); + if (len > sizeof(buf)) + len = sizeof(buf); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -433,6 +439,9 @@ static ssize_t read_file_antenna(struct file *file, char __user *user_buf, len += snprintf(buf+len, sizeof(buf)-len, "AR5K_PHY_ANT_SWITCH_TABLE_1\t0x%08x\n", v); + if (len > sizeof(buf)) + len = sizeof(buf); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -542,6 +551,9 @@ static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf, len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%d]\n", st->tx_all_count); + if (len > sizeof(buf)) + len = sizeof(buf); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -681,6 +693,9 @@ static ssize_t read_file_ani(struct file *file, char __user *user_buf, ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT2))); + if (len > sizeof(buf)) + len = sizeof(buf); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -766,6 +781,9 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf, len += snprintf(buf+len, sizeof(buf)-len, " len: %d\n", n); } + if (len > sizeof(buf)) + len = sizeof(buf); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); } diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 85fdd26039c..1a984b02e9e 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -131,11 +131,8 @@ static int ath_ahb_probe(struct platform_device *pdev) ah = sc->sc_ah; ath9k_hw_name(ah, hw_name, sizeof(hw_name)); - printk(KERN_INFO - "%s: %s mem=0x%lx, irq=%d\n", - wiphy_name(hw->wiphy), - hw_name, - (unsigned long)mem, irq); + wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n", + hw_name, (unsigned long)mem, irq); return 0; diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index 4a910b78de5..3d2c8679bc8 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -1506,6 +1506,9 @@ static void ar5008_hw_do_getnf(struct ath_hw *ah, nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR); nfarray[2] = sign_extend(nf, 9); + if (!IS_CHAN_HT40(ah->curchan)) + return; + nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); nfarray[3] = sign_extend(nf, 9); diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index 75b80d13ff9..303c63da5ea 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -85,21 +85,6 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah) ar9287PciePhy_clkreq_always_on_L1_9287_1_1, ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_1), 2); - } else if (AR_SREV_9287_10_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_0, - ARRAY_SIZE(ar9287Modes_9287_1_0), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_0, - ARRAY_SIZE(ar9287Common_9287_1_0), 2); - - if (ah->config.pcie_clock_req) - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9287PciePhy_clkreq_off_L1_9287_1_0, - ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_0), 2); - else - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9287PciePhy_clkreq_always_on_L1_9287_1_0, - ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_0), - 2); } else if (AR_SREV_9285_12_OR_LATER(ah)) { @@ -118,21 +103,6 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah) ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2), 2); } - } else if (AR_SREV_9285_10_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285, - ARRAY_SIZE(ar9285Modes_9285), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285, - ARRAY_SIZE(ar9285Common_9285), 2); - - if (ah->config.pcie_clock_req) { - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9285PciePhy_clkreq_off_L1_9285, - ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285), 2); - } else { - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9285PciePhy_clkreq_always_on_L1_9285, - ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285), 2); - } } else if (AR_SREV_9280_20_OR_LATER(ah)) { INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2, ARRAY_SIZE(ar9280Modes_9280_2), 6); @@ -151,11 +121,6 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah) INIT_INI_ARRAY(&ah->iniModesAdditional, ar9280Modes_fast_clock_9280_2, ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3); - } else if (AR_SREV_9280_10_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280, - ARRAY_SIZE(ar9280Modes_9280), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280, - ARRAY_SIZE(ar9280Common_9280), 2); } else if (AR_SREV_9160_10_OR_LATER(ah)) { INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160, ARRAY_SIZE(ar5416Modes_9160), 6); @@ -305,10 +270,6 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah) INIT_INI_ARRAY(&ah->iniModesRxGain, ar9287Modes_rx_gain_9287_1_1, ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6); - else if (AR_SREV_9287_10(ah)) - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9287Modes_rx_gain_9287_1_0, - ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_0), 6); else if (AR_SREV_9280_20(ah)) ar9280_20_hw_init_rxgain_ini(ah); @@ -316,10 +277,6 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9287Modes_tx_gain_9287_1_1, ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6); - } else if (AR_SREV_9287_10(ah)) { - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9287Modes_tx_gain_9287_1_0, - ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_0), 6); } else if (AR_SREV_9280_20(ah)) { ar9280_20_hw_init_txgain_ini(ah); } else if (AR_SREV_9285_12_OR_LATER(ah)) { @@ -389,29 +346,6 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah, REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0), INI_RA(&ah->iniPcieSerdes, i, 1)); } - } else if (AR_SREV_9280(ah) && - (ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) { - REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00); - REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); - - /* RX shut off when elecidle is asserted */ - REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019); - REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820); - REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560); - - /* Shut off CLKREQ active in L1 */ - if (ah->config.pcie_clock_req) - REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc); - else - REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd); - - REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); - REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); - REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007); - - /* Load the new settings */ - REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); - } else { ENABLE_REGWRITE_BUFFER(ah); diff --git a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h index 13b5e484c2e..6203eed860d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h @@ -14,556 +14,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -static const u32 ar9280Modes_9280[][6] = { - {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0}, - {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0}, - {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180}, - {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008}, - {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801080, 0x08400840, 0x06e006e0}, - {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f}, - {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303}, - {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200}, - {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, - {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001}, - {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, - {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007}, - {0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0}, - {0x00009848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563}, - {0x0000a848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563}, - {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2}, - {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e}, - {0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e}, - {0x00009860, 0x00049d18, 0x00049d18, 0x00049d20, 0x00049d20, 0x00049d18}, - {0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00}, - {0x00009868, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190}, - {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881}, - {0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0}, - {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016}, - {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d}, - {0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010}, - {0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010}, - {0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010}, - {0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210}, - {0x0000c9b8, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, - {0x0000c9bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00}, - {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, - {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77}, - {0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c}, - {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8}, - {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384}, - {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00009a00, 0x00008184, 0x00008184, 0x00000214, 0x00000214, 0x00000214}, - {0x00009a04, 0x00008188, 0x00008188, 0x00000218, 0x00000218, 0x00000218}, - {0x00009a08, 0x0000818c, 0x0000818c, 0x00000224, 0x00000224, 0x00000224}, - {0x00009a0c, 0x00008190, 0x00008190, 0x00000228, 0x00000228, 0x00000228}, - {0x00009a10, 0x00008194, 0x00008194, 0x0000022c, 0x0000022c, 0x0000022c}, - {0x00009a14, 0x00008200, 0x00008200, 0x00000230, 0x00000230, 0x00000230}, - {0x00009a18, 0x00008204, 0x00008204, 0x000002a4, 0x000002a4, 0x000002a4}, - {0x00009a1c, 0x00008208, 0x00008208, 0x000002a8, 0x000002a8, 0x000002a8}, - {0x00009a20, 0x0000820c, 0x0000820c, 0x000002ac, 0x000002ac, 0x000002ac}, - {0x00009a24, 0x00008210, 0x00008210, 0x000002b0, 0x000002b0, 0x000002b0}, - {0x00009a28, 0x00008214, 0x00008214, 0x000002b4, 0x000002b4, 0x000002b4}, - {0x00009a2c, 0x00008280, 0x00008280, 0x000002b8, 0x000002b8, 0x000002b8}, - {0x00009a30, 0x00008284, 0x00008284, 0x00000390, 0x00000390, 0x00000390}, - {0x00009a34, 0x00008288, 0x00008288, 0x00000394, 0x00000394, 0x00000394}, - {0x00009a38, 0x0000828c, 0x0000828c, 0x00000398, 0x00000398, 0x00000398}, - {0x00009a3c, 0x00008290, 0x00008290, 0x00000334, 0x00000334, 0x00000334}, - {0x00009a40, 0x00008300, 0x00008300, 0x00000338, 0x00000338, 0x00000338}, - {0x00009a44, 0x00008304, 0x00008304, 0x000003ac, 0x000003ac, 0x000003ac}, - {0x00009a48, 0x00008308, 0x00008308, 0x000003b0, 0x000003b0, 0x000003b0}, - {0x00009a4c, 0x0000830c, 0x0000830c, 0x000003b4, 0x000003b4, 0x000003b4}, - {0x00009a50, 0x00008310, 0x00008310, 0x000003b8, 0x000003b8, 0x000003b8}, - {0x00009a54, 0x00008314, 0x00008314, 0x000003a5, 0x000003a5, 0x000003a5}, - {0x00009a58, 0x00008380, 0x00008380, 0x000003a9, 0x000003a9, 0x000003a9}, - {0x00009a5c, 0x00008384, 0x00008384, 0x000003ad, 0x000003ad, 0x000003ad}, - {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194}, - {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0}, - {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c}, - {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8}, - {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284}, - {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288}, - {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224}, - {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290}, - {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300}, - {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304}, - {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308}, - {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c}, - {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380}, - {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384}, - {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700}, - {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704}, - {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708}, - {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c}, - {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780}, - {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784}, - {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00}, - {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04}, - {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08}, - {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c}, - {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80}, - {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84}, - {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88}, - {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c}, - {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90}, - {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80}, - {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84}, - {0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88}, - {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c}, - {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90}, - {0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c}, - {0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310}, - {0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384}, - {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388}, - {0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324}, - {0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704}, - {0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4}, - {0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8}, - {0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710}, - {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714}, - {0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720}, - {0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724}, - {0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728}, - {0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c}, - {0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0}, - {0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4}, - {0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8}, - {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0}, - {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4}, - {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8}, - {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5}, - {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9}, - {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad}, - {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1}, - {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5}, - {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9}, - {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5}, - {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9}, - {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1}, - {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5}, - {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9}, - {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6}, - {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca}, - {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce}, - {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2}, - {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6}, - {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3}, - {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7}, - {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb}, - {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf}, - {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7}, - {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db}, - {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db}, - {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db}, - {0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, - {0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444}, - {0x0000a208, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788}, - {0x0000a20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019}, - {0x0000b20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019}, - {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a}, - {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000}, - {0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652}, - {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002}, - {0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009}, - {0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b}, - {0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012}, - {0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048}, - {0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a}, - {0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211}, - {0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213}, - {0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b}, - {0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412}, - {0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414}, - {0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a}, - {0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649}, - {0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b}, - {0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49}, - {0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48}, - {0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a}, - {0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88}, - {0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a}, - {0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9}, - {0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42}, - {0x0000784c, 0x0e4f048c, 0x0e4f048c, 0x0e4d048c, 0x0e4d048c, 0x0e4d048c}, - {0x00007854, 0x12031828, 0x12031828, 0x12035828, 0x12035828, 0x12035828}, - {0x00007870, 0x807ec400, 0x807ec400, 0x807ec000, 0x807ec000, 0x807ec000}, - {0x0000788c, 0x00010000, 0x00010000, 0x00110000, 0x00110000, 0x00110000}, -}; - -static const u32 ar9280Common_9280[][2] = { - /* Addr allmodes */ - {0x0000000c, 0x00000000}, - {0x00000030, 0x00020015}, - {0x00000034, 0x00000005}, - {0x00000040, 0x00000000}, - {0x00000044, 0x00000008}, - {0x00000048, 0x00000008}, - {0x0000004c, 0x00000010}, - {0x00000050, 0x00000000}, - {0x00000054, 0x0000001f}, - {0x00000800, 0x00000000}, - {0x00000804, 0x00000000}, - {0x00000808, 0x00000000}, - {0x0000080c, 0x00000000}, - {0x00000810, 0x00000000}, - {0x00000814, 0x00000000}, - {0x00000818, 0x00000000}, - {0x0000081c, 0x00000000}, - {0x00000820, 0x00000000}, - {0x00000824, 0x00000000}, - {0x00001040, 0x002ffc0f}, - {0x00001044, 0x002ffc0f}, - {0x00001048, 0x002ffc0f}, - {0x0000104c, 0x002ffc0f}, - {0x00001050, 0x002ffc0f}, - {0x00001054, 0x002ffc0f}, - {0x00001058, 0x002ffc0f}, - {0x0000105c, 0x002ffc0f}, - {0x00001060, 0x002ffc0f}, - {0x00001064, 0x002ffc0f}, - {0x00001230, 0x00000000}, - {0x00001270, 0x00000000}, - {0x00001038, 0x00000000}, - {0x00001078, 0x00000000}, - {0x000010b8, 0x00000000}, - {0x000010f8, 0x00000000}, - {0x00001138, 0x00000000}, - {0x00001178, 0x00000000}, - {0x000011b8, 0x00000000}, - {0x000011f8, 0x00000000}, - {0x00001238, 0x00000000}, - {0x00001278, 0x00000000}, - {0x000012b8, 0x00000000}, - {0x000012f8, 0x00000000}, - {0x00001338, 0x00000000}, - {0x00001378, 0x00000000}, - {0x000013b8, 0x00000000}, - {0x000013f8, 0x00000000}, - {0x00001438, 0x00000000}, - {0x00001478, 0x00000000}, - {0x000014b8, 0x00000000}, - {0x000014f8, 0x00000000}, - {0x00001538, 0x00000000}, - {0x00001578, 0x00000000}, - {0x000015b8, 0x00000000}, - {0x000015f8, 0x00000000}, - {0x00001638, 0x00000000}, - {0x00001678, 0x00000000}, - {0x000016b8, 0x00000000}, - {0x000016f8, 0x00000000}, - {0x00001738, 0x00000000}, - {0x00001778, 0x00000000}, - {0x000017b8, 0x00000000}, - {0x000017f8, 0x00000000}, - {0x0000103c, 0x00000000}, - {0x0000107c, 0x00000000}, - {0x000010bc, 0x00000000}, - {0x000010fc, 0x00000000}, - {0x0000113c, 0x00000000}, - {0x0000117c, 0x00000000}, - {0x000011bc, 0x00000000}, - {0x000011fc, 0x00000000}, - {0x0000123c, 0x00000000}, - {0x0000127c, 0x00000000}, - {0x000012bc, 0x00000000}, - {0x000012fc, 0x00000000}, - {0x0000133c, 0x00000000}, - {0x0000137c, 0x00000000}, - {0x000013bc, 0x00000000}, - {0x000013fc, 0x00000000}, - {0x0000143c, 0x00000000}, - {0x0000147c, 0x00000000}, - {0x00004030, 0x00000002}, - {0x0000403c, 0x00000002}, - {0x00004024, 0x0000001f}, - {0x00007010, 0x00000033}, - {0x00007038, 0x000004c2}, - {0x00008004, 0x00000000}, - {0x00008008, 0x00000000}, - {0x0000800c, 0x00000000}, - {0x00008018, 0x00000700}, - {0x00008020, 0x00000000}, - {0x00008038, 0x00000000}, - {0x0000803c, 0x00000000}, - {0x00008048, 0x40000000}, - {0x00008054, 0x00000000}, - {0x00008058, 0x00000000}, - {0x0000805c, 0x000fc78f}, - {0x00008060, 0x0000000f}, - {0x00008064, 0x00000000}, - {0x00008070, 0x00000000}, - {0x000080c0, 0x2a82301a}, - {0x000080c4, 0x05dc01e0}, - {0x000080c8, 0x1f402710}, - {0x000080cc, 0x01f40000}, - {0x000080d0, 0x00001e00}, - {0x000080d4, 0x00000000}, - {0x000080d8, 0x00400000}, - {0x000080e0, 0xffffffff}, - {0x000080e4, 0x0000ffff}, - {0x000080e8, 0x003f3f3f}, - {0x000080ec, 0x00000000}, - {0x000080f0, 0x00000000}, - {0x000080f4, 0x00000000}, - {0x000080f8, 0x00000000}, - {0x000080fc, 0x00020000}, - {0x00008100, 0x00020000}, - {0x00008104, 0x00000001}, - {0x00008108, 0x00000052}, - {0x0000810c, 0x00000000}, - {0x00008110, 0x00000168}, - {0x00008118, 0x000100aa}, - {0x0000811c, 0x00003210}, - {0x00008120, 0x08f04800}, - {0x00008124, 0x00000000}, - {0x00008128, 0x00000000}, - {0x0000812c, 0x00000000}, - {0x00008130, 0x00000000}, - {0x00008134, 0x00000000}, - {0x00008138, 0x00000000}, - {0x0000813c, 0x00000000}, - {0x00008144, 0x00000000}, - {0x00008168, 0x00000000}, - {0x0000816c, 0x00000000}, - {0x00008170, 0x32143320}, - {0x00008174, 0xfaa4fa50}, - {0x00008178, 0x00000100}, - {0x0000817c, 0x00000000}, - {0x000081c4, 0x00000000}, - {0x000081d0, 0x00003210}, - {0x000081ec, 0x00000000}, - {0x000081f0, 0x00000000}, - {0x000081f4, 0x00000000}, - {0x000081f8, 0x00000000}, - {0x000081fc, 0x00000000}, - {0x00008200, 0x00000000}, - {0x00008204, 0x00000000}, - {0x00008208, 0x00000000}, - {0x0000820c, 0x00000000}, - {0x00008210, 0x00000000}, - {0x00008214, 0x00000000}, - {0x00008218, 0x00000000}, - {0x0000821c, 0x00000000}, - {0x00008220, 0x00000000}, - {0x00008224, 0x00000000}, - {0x00008228, 0x00000000}, - {0x0000822c, 0x00000000}, - {0x00008230, 0x00000000}, - {0x00008234, 0x00000000}, - {0x00008238, 0x00000000}, - {0x0000823c, 0x00000000}, - {0x00008240, 0x00100000}, - {0x00008244, 0x0010f400}, - {0x00008248, 0x00000100}, - {0x0000824c, 0x0001e800}, - {0x00008250, 0x00000000}, - {0x00008254, 0x00000000}, - {0x00008258, 0x00000000}, - {0x0000825c, 0x400000ff}, - {0x00008260, 0x00080922}, - {0x00008270, 0x00000000}, - {0x00008274, 0x40000000}, - {0x00008278, 0x003e4180}, - {0x0000827c, 0x00000000}, - {0x00008284, 0x0000002c}, - {0x00008288, 0x0000002c}, - {0x0000828c, 0x00000000}, - {0x00008294, 0x00000000}, - {0x00008298, 0x00000000}, - {0x00008300, 0x00000000}, - {0x00008304, 0x00000000}, - {0x00008308, 0x00000000}, - {0x0000830c, 0x00000000}, - {0x00008310, 0x00000000}, - {0x00008314, 0x00000000}, - {0x00008318, 0x00000000}, - {0x00008328, 0x00000000}, - {0x0000832c, 0x00000007}, - {0x00008330, 0x00000302}, - {0x00008334, 0x00000e00}, - {0x00008338, 0x00000000}, - {0x0000833c, 0x00000000}, - {0x00008340, 0x000107ff}, - {0x00008344, 0x00000000}, - {0x00009808, 0x00000000}, - {0x0000980c, 0xaf268e30}, - {0x00009810, 0xfd14e000}, - {0x00009814, 0x9c0a9f6b}, - {0x0000981c, 0x00000000}, - {0x0000982c, 0x0000a000}, - {0x00009830, 0x00000000}, - {0x0000983c, 0x00200400}, - {0x00009840, 0x206a01ae}, - {0x0000984c, 0x0040233c}, - {0x0000a84c, 0x0040233c}, - {0x00009854, 0x00000044}, - {0x00009900, 0x00000000}, - {0x00009904, 0x00000000}, - {0x00009908, 0x00000000}, - {0x0000990c, 0x00000000}, - {0x0000991c, 0x10000fff}, - {0x00009920, 0x04900000}, - {0x0000a920, 0x04900000}, - {0x00009928, 0x00000001}, - {0x0000992c, 0x00000004}, - {0x00009934, 0x1e1f2022}, - {0x00009938, 0x0a0b0c0d}, - {0x0000993c, 0x00000000}, - {0x00009948, 0x9280c00a}, - {0x0000994c, 0x00020028}, - {0x00009954, 0xe250a51e}, - {0x00009958, 0x3388ffff}, - {0x00009940, 0x00781204}, - {0x0000c95c, 0x004b6a8e}, - {0x0000c968, 0x000003ce}, - {0x00009970, 0x190fb514}, - {0x00009974, 0x00000000}, - {0x00009978, 0x00000001}, - {0x0000997c, 0x00000000}, - {0x00009980, 0x00000000}, - {0x00009984, 0x00000000}, - {0x00009988, 0x00000000}, - {0x0000998c, 0x00000000}, - {0x00009990, 0x00000000}, - {0x00009994, 0x00000000}, - {0x00009998, 0x00000000}, - {0x0000999c, 0x00000000}, - {0x000099a0, 0x00000000}, - {0x000099a4, 0x00000001}, - {0x000099a8, 0x201fff00}, - {0x000099ac, 0x006f00c4}, - {0x000099b0, 0x03051000}, - {0x000099b4, 0x00000820}, - {0x000099dc, 0x00000000}, - {0x000099e0, 0x00000000}, - {0x000099e4, 0xaaaaaaaa}, - {0x000099e8, 0x3c466478}, - {0x000099ec, 0x0cc80caa}, - {0x000099fc, 0x00001042}, - {0x0000a210, 0x4080a333}, - {0x0000a214, 0x40206c10}, - {0x0000a218, 0x009c4060}, - {0x0000a220, 0x01834061}, - {0x0000a224, 0x00000400}, - {0x0000a228, 0x000003b5}, - {0x0000a22c, 0x23277200}, - {0x0000a234, 0x20202020}, - {0x0000a238, 0x20202020}, - {0x0000a23c, 0x13c889af}, - {0x0000a240, 0x38490a20}, - {0x0000a244, 0x00007bb6}, - {0x0000a248, 0x0fff3ffc}, - {0x0000a24c, 0x00000001}, - {0x0000a250, 0x001da000}, - {0x0000a254, 0x00000000}, - {0x0000a258, 0x0cdbd380}, - {0x0000a25c, 0x0f0f0f01}, - {0x0000a260, 0xdfa91f01}, - {0x0000a268, 0x00000000}, - {0x0000a26c, 0x0ebae9c6}, - {0x0000b26c, 0x0ebae9c6}, - {0x0000d270, 0x00820820}, - {0x0000a278, 0x1ce739ce}, - {0x0000a27c, 0x050701ce}, - {0x0000a358, 0x7999aa0f}, - {0x0000d35c, 0x07ffffef}, - {0x0000d360, 0x0fffffe7}, - {0x0000d364, 0x17ffffe5}, - {0x0000d368, 0x1fffffe4}, - {0x0000d36c, 0x37ffffe3}, - {0x0000d370, 0x3fffffe3}, - {0x0000d374, 0x57ffffe3}, - {0x0000d378, 0x5fffffe2}, - {0x0000d37c, 0x7fffffe2}, - {0x0000d380, 0x7f3c7bba}, - {0x0000d384, 0xf3307ff0}, - {0x0000a388, 0x0c000000}, - {0x0000a38c, 0x20202020}, - {0x0000a390, 0x20202020}, - {0x0000a394, 0x1ce739ce}, - {0x0000a398, 0x000001ce}, - {0x0000a39c, 0x00000001}, - {0x0000a3a0, 0x00000000}, - {0x0000a3a4, 0x00000000}, - {0x0000a3a8, 0x00000000}, - {0x0000a3ac, 0x00000000}, - {0x0000a3b0, 0x00000000}, - {0x0000a3b4, 0x00000000}, - {0x0000a3b8, 0x00000000}, - {0x0000a3bc, 0x00000000}, - {0x0000a3c0, 0x00000000}, - {0x0000a3c4, 0x00000000}, - {0x0000a3c8, 0x00000246}, - {0x0000a3cc, 0x20202020}, - {0x0000a3d0, 0x20202020}, - {0x0000a3d4, 0x20202020}, - {0x0000a3dc, 0x1ce739ce}, - {0x0000a3e0, 0x000001ce}, - {0x0000a3e4, 0x00000000}, - {0x0000a3e8, 0x18c43433}, - {0x0000a3ec, 0x00f38081}, - {0x00007800, 0x00040000}, - {0x00007804, 0xdb005012}, - {0x00007808, 0x04924914}, - {0x0000780c, 0x21084210}, - {0x00007810, 0x6d801300}, - {0x00007814, 0x0019beff}, - {0x00007818, 0x07e40000}, - {0x0000781c, 0x00492000}, - {0x00007820, 0x92492480}, - {0x00007824, 0x00040000}, - {0x00007828, 0xdb005012}, - {0x0000782c, 0x04924914}, - {0x00007830, 0x21084210}, - {0x00007834, 0x6d801300}, - {0x00007838, 0x0019beff}, - {0x0000783c, 0x07e40000}, - {0x00007840, 0x00492000}, - {0x00007844, 0x92492480}, - {0x00007848, 0x00120000}, - {0x00007850, 0x54214514}, - {0x00007858, 0x92592692}, - {0x00007860, 0x52802000}, - {0x00007864, 0x0a8e370e}, - {0x00007868, 0xc0102850}, - {0x0000786c, 0x812d4000}, - {0x00007874, 0x001b6db0}, - {0x00007878, 0x00376b63}, - {0x0000787c, 0x06db6db6}, - {0x00007880, 0x006d8000}, - {0x00007884, 0xffeffffe}, - {0x00007888, 0xffeffffe}, - {0x00007890, 0x00060aeb}, - {0x00007894, 0x5a108000}, - {0x00007898, 0x2a850160}, -}; - static const u32 ar9280Modes_9280_2[][6] = { {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0}, {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0}, @@ -1469,662 +919,6 @@ static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = { {0x00004044, 0x00000000}, }; -static const u32 ar9285Modes_9285[][6] = { - {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0}, - {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0}, - {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180}, - {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008}, - {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0}, - {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f}, - {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880}, - {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303}, - {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200}, - {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, - {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001}, - {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, - {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007}, - {0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e}, - {0x00009844, 0x0372161e, 0x0372161e, 0x03720020, 0x03720020, 0x037216a0}, - {0x00009848, 0x00001066, 0x00001066, 0x0000004e, 0x0000004e, 0x00001059}, - {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2}, - {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e}, - {0x0000985c, 0x3139605e, 0x3139605e, 0x3136605e, 0x3136605e, 0x3139605e}, - {0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18}, - {0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00}, - {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, - {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881}, - {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0}, - {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016}, - {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d}, - {0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1020, 0xdfbc1020, 0xdfbc1010}, - {0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x000099b8, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c}, - {0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00}, - {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, - {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77}, - {0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329}, - {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8}, - {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384}, - {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00009a00, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000}, - {0x00009a04, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000}, - {0x00009a08, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000}, - {0x00009a0c, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000}, - {0x00009a10, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000}, - {0x00009a14, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000}, - {0x00009a18, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000}, - {0x00009a1c, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000}, - {0x00009a20, 0x00000000, 0x00000000, 0x00068114, 0x00068114, 0x00000000}, - {0x00009a24, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000}, - {0x00009a28, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000}, - {0x00009a2c, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000}, - {0x00009a30, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000}, - {0x00009a34, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000}, - {0x00009a38, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000}, - {0x00009a3c, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000}, - {0x00009a40, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000}, - {0x00009a44, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000}, - {0x00009a48, 0x00000000, 0x00000000, 0x00068284, 0x00068284, 0x00000000}, - {0x00009a4c, 0x00000000, 0x00000000, 0x00068288, 0x00068288, 0x00000000}, - {0x00009a50, 0x00000000, 0x00000000, 0x00068220, 0x00068220, 0x00000000}, - {0x00009a54, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000}, - {0x00009a58, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000}, - {0x00009a5c, 0x00000000, 0x00000000, 0x00068304, 0x00068304, 0x00000000}, - {0x00009a60, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000}, - {0x00009a64, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000}, - {0x00009a68, 0x00000000, 0x00000000, 0x00068380, 0x00068380, 0x00000000}, - {0x00009a6c, 0x00000000, 0x00000000, 0x00068384, 0x00068384, 0x00000000}, - {0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000}, - {0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000}, - {0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000}, - {0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000}, - {0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000}, - {0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000}, - {0x00009a88, 0x00000000, 0x00000000, 0x00068b04, 0x00068b04, 0x00000000}, - {0x00009a8c, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000}, - {0x00009a90, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000}, - {0x00009a94, 0x00000000, 0x00000000, 0x00068b0c, 0x00068b0c, 0x00000000}, - {0x00009a98, 0x00000000, 0x00000000, 0x00068b80, 0x00068b80, 0x00000000}, - {0x00009a9c, 0x00000000, 0x00000000, 0x00068b84, 0x00068b84, 0x00000000}, - {0x00009aa0, 0x00000000, 0x00000000, 0x00068b88, 0x00068b88, 0x00000000}, - {0x00009aa4, 0x00000000, 0x00000000, 0x00068b8c, 0x00068b8c, 0x00000000}, - {0x00009aa8, 0x00000000, 0x00000000, 0x000b8b90, 0x000b8b90, 0x00000000}, - {0x00009aac, 0x00000000, 0x00000000, 0x000b8f80, 0x000b8f80, 0x00000000}, - {0x00009ab0, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000}, - {0x00009ab4, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000}, - {0x00009ab8, 0x00000000, 0x00000000, 0x000b8f8c, 0x000b8f8c, 0x00000000}, - {0x00009abc, 0x00000000, 0x00000000, 0x000b8f90, 0x000b8f90, 0x00000000}, - {0x00009ac0, 0x00000000, 0x00000000, 0x000bb30c, 0x000bb30c, 0x00000000}, - {0x00009ac4, 0x00000000, 0x00000000, 0x000bb310, 0x000bb310, 0x00000000}, - {0x00009ac8, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000}, - {0x00009acc, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000}, - {0x00009ad0, 0x00000000, 0x00000000, 0x000bb324, 0x000bb324, 0x00000000}, - {0x00009ad4, 0x00000000, 0x00000000, 0x000bb704, 0x000bb704, 0x00000000}, - {0x00009ad8, 0x00000000, 0x00000000, 0x000f96a4, 0x000f96a4, 0x00000000}, - {0x00009adc, 0x00000000, 0x00000000, 0x000f96a8, 0x000f96a8, 0x00000000}, - {0x00009ae0, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000}, - {0x00009ae4, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000}, - {0x00009ae8, 0x00000000, 0x00000000, 0x000f9720, 0x000f9720, 0x00000000}, - {0x00009aec, 0x00000000, 0x00000000, 0x000f9724, 0x000f9724, 0x00000000}, - {0x00009af0, 0x00000000, 0x00000000, 0x000f9728, 0x000f9728, 0x00000000}, - {0x00009af4, 0x00000000, 0x00000000, 0x000f972c, 0x000f972c, 0x00000000}, - {0x00009af8, 0x00000000, 0x00000000, 0x000f97a0, 0x000f97a0, 0x00000000}, - {0x00009afc, 0x00000000, 0x00000000, 0x000f97a4, 0x000f97a4, 0x00000000}, - {0x00009b00, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000}, - {0x00009b04, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000}, - {0x00009b08, 0x00000000, 0x00000000, 0x000fb7b4, 0x000fb7b4, 0x00000000}, - {0x00009b0c, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000}, - {0x00009b10, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000}, - {0x00009b14, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000}, - {0x00009b18, 0x00000000, 0x00000000, 0x000fb7ad, 0x000fb7ad, 0x00000000}, - {0x00009b1c, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000}, - {0x00009b20, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000}, - {0x00009b24, 0x00000000, 0x00000000, 0x000fb7b9, 0x000fb7b9, 0x00000000}, - {0x00009b28, 0x00000000, 0x00000000, 0x000fb7c5, 0x000fb7c5, 0x00000000}, - {0x00009b2c, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000}, - {0x00009b30, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000}, - {0x00009b34, 0x00000000, 0x00000000, 0x000fb7d5, 0x000fb7d5, 0x00000000}, - {0x00009b38, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000}, - {0x00009b3c, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000}, - {0x00009b40, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000}, - {0x00009b44, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000}, - {0x00009b48, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000}, - {0x00009b4c, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000}, - {0x00009b50, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000}, - {0x00009b54, 0x00000000, 0x00000000, 0x000fb7c7, 0x000fb7c7, 0x00000000}, - {0x00009b58, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000}, - {0x00009b5c, 0x00000000, 0x00000000, 0x000fb7cf, 0x000fb7cf, 0x00000000}, - {0x00009b60, 0x00000000, 0x00000000, 0x000fb7d7, 0x000fb7d7, 0x00000000}, - {0x00009b64, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009b68, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009b6c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009b70, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009b74, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009b78, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009b7c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009b80, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009b84, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009b88, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009b8c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009b90, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009b94, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009b98, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009b9c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009ba0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009ba4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009ba8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009bac, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009bb0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009bb4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009bb8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009bbc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009bc0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009bc4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009bc8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009bcc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009bd0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009bd4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009bd8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009bdc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009be0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009be4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009be8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009bec, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009bf0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009bf4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009bf8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x00009bfc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000}, - {0x0000aa00, 0x00000000, 0x00000000, 0x0006801c, 0x0006801c, 0x00000000}, - {0x0000aa04, 0x00000000, 0x00000000, 0x00068080, 0x00068080, 0x00000000}, - {0x0000aa08, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000}, - {0x0000aa0c, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000}, - {0x0000aa10, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000}, - {0x0000aa14, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000}, - {0x0000aa18, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000}, - {0x0000aa1c, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000}, - {0x0000aa20, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000}, - {0x0000aa24, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000}, - {0x0000aa28, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000}, - {0x0000aa2c, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000}, - {0x0000aa30, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000}, - {0x0000aa34, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000}, - {0x0000aa38, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000}, - {0x0000aa3c, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000}, - {0x0000aa40, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000}, - {0x0000aa44, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000}, - {0x0000aa48, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000}, - {0x0000aa4c, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000}, - {0x0000aa50, 0x00000000, 0x00000000, 0x000681ac, 0x000681ac, 0x00000000}, - {0x0000aa54, 0x00000000, 0x00000000, 0x0006821c, 0x0006821c, 0x00000000}, - {0x0000aa58, 0x00000000, 0x00000000, 0x00068224, 0x00068224, 0x00000000}, - {0x0000aa5c, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000}, - {0x0000aa60, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000}, - {0x0000aa64, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000}, - {0x0000aa68, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000}, - {0x0000aa6c, 0x00000000, 0x00000000, 0x00068310, 0x00068310, 0x00000000}, - {0x0000aa70, 0x00000000, 0x00000000, 0x00068788, 0x00068788, 0x00000000}, - {0x0000aa74, 0x00000000, 0x00000000, 0x0006878c, 0x0006878c, 0x00000000}, - {0x0000aa78, 0x00000000, 0x00000000, 0x00068790, 0x00068790, 0x00000000}, - {0x0000aa7c, 0x00000000, 0x00000000, 0x00068794, 0x00068794, 0x00000000}, - {0x0000aa80, 0x00000000, 0x00000000, 0x00068798, 0x00068798, 0x00000000}, - {0x0000aa84, 0x00000000, 0x00000000, 0x0006879c, 0x0006879c, 0x00000000}, - {0x0000aa88, 0x00000000, 0x00000000, 0x00068b89, 0x00068b89, 0x00000000}, - {0x0000aa8c, 0x00000000, 0x00000000, 0x00068b8d, 0x00068b8d, 0x00000000}, - {0x0000aa90, 0x00000000, 0x00000000, 0x00068b91, 0x00068b91, 0x00000000}, - {0x0000aa94, 0x00000000, 0x00000000, 0x00068b95, 0x00068b95, 0x00000000}, - {0x0000aa98, 0x00000000, 0x00000000, 0x00068b99, 0x00068b99, 0x00000000}, - {0x0000aa9c, 0x00000000, 0x00000000, 0x00068ba5, 0x00068ba5, 0x00000000}, - {0x0000aaa0, 0x00000000, 0x00000000, 0x00068ba9, 0x00068ba9, 0x00000000}, - {0x0000aaa4, 0x00000000, 0x00000000, 0x00068bad, 0x00068bad, 0x00000000}, - {0x0000aaa8, 0x00000000, 0x00000000, 0x000b8b0c, 0x000b8b0c, 0x00000000}, - {0x0000aaac, 0x00000000, 0x00000000, 0x000b8f10, 0x000b8f10, 0x00000000}, - {0x0000aab0, 0x00000000, 0x00000000, 0x000b8f14, 0x000b8f14, 0x00000000}, - {0x0000aab4, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000}, - {0x0000aab8, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000}, - {0x0000aabc, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000}, - {0x0000aac0, 0x00000000, 0x00000000, 0x000bb380, 0x000bb380, 0x00000000}, - {0x0000aac4, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000}, - {0x0000aac8, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000}, - {0x0000aacc, 0x00000000, 0x00000000, 0x000bb38c, 0x000bb38c, 0x00000000}, - {0x0000aad0, 0x00000000, 0x00000000, 0x000bb394, 0x000bb394, 0x00000000}, - {0x0000aad4, 0x00000000, 0x00000000, 0x000bb798, 0x000bb798, 0x00000000}, - {0x0000aad8, 0x00000000, 0x00000000, 0x000f970c, 0x000f970c, 0x00000000}, - {0x0000aadc, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000}, - {0x0000aae0, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000}, - {0x0000aae4, 0x00000000, 0x00000000, 0x000f9718, 0x000f9718, 0x00000000}, - {0x0000aae8, 0x00000000, 0x00000000, 0x000f9705, 0x000f9705, 0x00000000}, - {0x0000aaec, 0x00000000, 0x00000000, 0x000f9709, 0x000f9709, 0x00000000}, - {0x0000aaf0, 0x00000000, 0x00000000, 0x000f970d, 0x000f970d, 0x00000000}, - {0x0000aaf4, 0x00000000, 0x00000000, 0x000f9711, 0x000f9711, 0x00000000}, - {0x0000aaf8, 0x00000000, 0x00000000, 0x000f9715, 0x000f9715, 0x00000000}, - {0x0000aafc, 0x00000000, 0x00000000, 0x000f9719, 0x000f9719, 0x00000000}, - {0x0000ab00, 0x00000000, 0x00000000, 0x000fb7a4, 0x000fb7a4, 0x00000000}, - {0x0000ab04, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000}, - {0x0000ab08, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000}, - {0x0000ab0c, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000}, - {0x0000ab10, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000}, - {0x0000ab14, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000}, - {0x0000ab18, 0x00000000, 0x00000000, 0x000fb7bc, 0x000fb7bc, 0x00000000}, - {0x0000ab1c, 0x00000000, 0x00000000, 0x000fb7a1, 0x000fb7a1, 0x00000000}, - {0x0000ab20, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000}, - {0x0000ab24, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000}, - {0x0000ab28, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000}, - {0x0000ab2c, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000}, - {0x0000ab30, 0x00000000, 0x00000000, 0x000fb7bd, 0x000fb7bd, 0x00000000}, - {0x0000ab34, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000}, - {0x0000ab38, 0x00000000, 0x00000000, 0x000fb7cd, 0x000fb7cd, 0x00000000}, - {0x0000ab3c, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000}, - {0x0000ab40, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000}, - {0x0000ab44, 0x00000000, 0x00000000, 0x000fb7c2, 0x000fb7c2, 0x00000000}, - {0x0000ab48, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000}, - {0x0000ab4c, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000}, - {0x0000ab50, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000}, - {0x0000ab54, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000}, - {0x0000ab58, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000}, - {0x0000ab5c, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000}, - {0x0000ab60, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000}, - {0x0000ab64, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000ab68, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000ab6c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000ab70, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000ab74, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000ab78, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000ab7c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000ab80, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000ab84, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000ab88, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000ab8c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000ab90, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000ab94, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000ab98, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000ab9c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000aba0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000aba4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000aba8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000abac, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000abb0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000abb4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000abb8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000abbc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000abc0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000abc4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000abc8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000abcc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000abd0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000abd4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000abd8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000abdc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000abe0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000abe4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000abe8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000abec, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000abf0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000abf4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000abf8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000abfc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000}, - {0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004}, - {0x0000a20c, 0x00000014, 0x00000014, 0x00000000, 0x00000000, 0x0001f000}, - {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a}, - {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000}, - {0x0000a250, 0x001ff000, 0x001ff000, 0x001ca000, 0x001ca000, 0x001da000}, - {0x0000a274, 0x0a81c652, 0x0a81c652, 0x0a820652, 0x0a820652, 0x0a82a652}, - {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a304, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000}, - {0x0000a308, 0x00000000, 0x00000000, 0x00010408, 0x00010408, 0x00000000}, - {0x0000a30c, 0x00000000, 0x00000000, 0x0001860a, 0x0001860a, 0x00000000}, - {0x0000a310, 0x00000000, 0x00000000, 0x00020818, 0x00020818, 0x00000000}, - {0x0000a314, 0x00000000, 0x00000000, 0x00024858, 0x00024858, 0x00000000}, - {0x0000a318, 0x00000000, 0x00000000, 0x00026859, 0x00026859, 0x00000000}, - {0x0000a31c, 0x00000000, 0x00000000, 0x0002985b, 0x0002985b, 0x00000000}, - {0x0000a320, 0x00000000, 0x00000000, 0x0002c89a, 0x0002c89a, 0x00000000}, - {0x0000a324, 0x00000000, 0x00000000, 0x0002e89b, 0x0002e89b, 0x00000000}, - {0x0000a328, 0x00000000, 0x00000000, 0x0003089c, 0x0003089c, 0x00000000}, - {0x0000a32c, 0x00000000, 0x00000000, 0x0003289d, 0x0003289d, 0x00000000}, - {0x0000a330, 0x00000000, 0x00000000, 0x0003489e, 0x0003489e, 0x00000000}, - {0x0000a334, 0x00000000, 0x00000000, 0x000388de, 0x000388de, 0x00000000}, - {0x0000a338, 0x00000000, 0x00000000, 0x0003b91e, 0x0003b91e, 0x00000000}, - {0x0000a33c, 0x00000000, 0x00000000, 0x0003d95e, 0x0003d95e, 0x00000000}, - {0x0000a340, 0x00000000, 0x00000000, 0x000419df, 0x000419df, 0x00000000}, - {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, - {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e}, -}; - -static const u32 ar9285Common_9285[][2] = { - /* Addr allmodes */ - {0x0000000c, 0x00000000}, - {0x00000030, 0x00020045}, - {0x00000034, 0x00000005}, - {0x00000040, 0x00000000}, - {0x00000044, 0x00000008}, - {0x00000048, 0x00000008}, - {0x0000004c, 0x00000010}, - {0x00000050, 0x00000000}, - {0x00000054, 0x0000001f}, - {0x00000800, 0x00000000}, - {0x00000804, 0x00000000}, - {0x00000808, 0x00000000}, - {0x0000080c, 0x00000000}, - {0x00000810, 0x00000000}, - {0x00000814, 0x00000000}, - {0x00000818, 0x00000000}, - {0x0000081c, 0x00000000}, - {0x00000820, 0x00000000}, - {0x00000824, 0x00000000}, - {0x00001040, 0x002ffc0f}, - {0x00001044, 0x002ffc0f}, - {0x00001048, 0x002ffc0f}, - {0x0000104c, 0x002ffc0f}, - {0x00001050, 0x002ffc0f}, - {0x00001054, 0x002ffc0f}, - {0x00001058, 0x002ffc0f}, - {0x0000105c, 0x002ffc0f}, - {0x00001060, 0x002ffc0f}, - {0x00001064, 0x002ffc0f}, - {0x00001230, 0x00000000}, - {0x00001270, 0x00000000}, - {0x00001038, 0x00000000}, - {0x00001078, 0x00000000}, - {0x000010b8, 0x00000000}, - {0x000010f8, 0x00000000}, - {0x00001138, 0x00000000}, - {0x00001178, 0x00000000}, - {0x000011b8, 0x00000000}, - {0x000011f8, 0x00000000}, - {0x00001238, 0x00000000}, - {0x00001278, 0x00000000}, - {0x000012b8, 0x00000000}, - {0x000012f8, 0x00000000}, - {0x00001338, 0x00000000}, - {0x00001378, 0x00000000}, - {0x000013b8, 0x00000000}, - {0x000013f8, 0x00000000}, - {0x00001438, 0x00000000}, - {0x00001478, 0x00000000}, - {0x000014b8, 0x00000000}, - {0x000014f8, 0x00000000}, - {0x00001538, 0x00000000}, - {0x00001578, 0x00000000}, - {0x000015b8, 0x00000000}, - {0x000015f8, 0x00000000}, - {0x00001638, 0x00000000}, - {0x00001678, 0x00000000}, - {0x000016b8, 0x00000000}, - {0x000016f8, 0x00000000}, - {0x00001738, 0x00000000}, - {0x00001778, 0x00000000}, - {0x000017b8, 0x00000000}, - {0x000017f8, 0x00000000}, - {0x0000103c, 0x00000000}, - {0x0000107c, 0x00000000}, - {0x000010bc, 0x00000000}, - {0x000010fc, 0x00000000}, - {0x0000113c, 0x00000000}, - {0x0000117c, 0x00000000}, - {0x000011bc, 0x00000000}, - {0x000011fc, 0x00000000}, - {0x0000123c, 0x00000000}, - {0x0000127c, 0x00000000}, - {0x000012bc, 0x00000000}, - {0x000012fc, 0x00000000}, - {0x0000133c, 0x00000000}, - {0x0000137c, 0x00000000}, - {0x000013bc, 0x00000000}, - {0x000013fc, 0x00000000}, - {0x0000143c, 0x00000000}, - {0x0000147c, 0x00000000}, - {0x00004030, 0x00000002}, - {0x0000403c, 0x00000002}, - {0x00004024, 0x0000001f}, - {0x00004060, 0x00000000}, - {0x00004064, 0x00000000}, - {0x00007010, 0x00000031}, - {0x00007034, 0x00000002}, - {0x00007038, 0x000004c2}, - {0x00008004, 0x00000000}, - {0x00008008, 0x00000000}, - {0x0000800c, 0x00000000}, - {0x00008018, 0x00000700}, - {0x00008020, 0x00000000}, - {0x00008038, 0x00000000}, - {0x0000803c, 0x00000000}, - {0x00008048, 0x00000000}, - {0x00008054, 0x00000000}, - {0x00008058, 0x00000000}, - {0x0000805c, 0x000fc78f}, - {0x00008060, 0x0000000f}, - {0x00008064, 0x00000000}, - {0x00008070, 0x00000000}, - {0x000080c0, 0x2a80001a}, - {0x000080c4, 0x05dc01e0}, - {0x000080c8, 0x1f402710}, - {0x000080cc, 0x01f40000}, - {0x000080d0, 0x00001e00}, - {0x000080d4, 0x00000000}, - {0x000080d8, 0x00400000}, - {0x000080e0, 0xffffffff}, - {0x000080e4, 0x0000ffff}, - {0x000080e8, 0x003f3f3f}, - {0x000080ec, 0x00000000}, - {0x000080f0, 0x00000000}, - {0x000080f4, 0x00000000}, - {0x000080f8, 0x00000000}, - {0x000080fc, 0x00020000}, - {0x00008100, 0x00020000}, - {0x00008104, 0x00000001}, - {0x00008108, 0x00000052}, - {0x0000810c, 0x00000000}, - {0x00008110, 0x00000168}, - {0x00008118, 0x000100aa}, - {0x0000811c, 0x00003210}, - {0x00008120, 0x08f04800}, - {0x00008124, 0x00000000}, - {0x00008128, 0x00000000}, - {0x0000812c, 0x00000000}, - {0x00008130, 0x00000000}, - {0x00008134, 0x00000000}, - {0x00008138, 0x00000000}, - {0x0000813c, 0x00000000}, - {0x00008144, 0x00000000}, - {0x00008168, 0x00000000}, - {0x0000816c, 0x00000000}, - {0x00008170, 0x32143320}, - {0x00008174, 0xfaa4fa50}, - {0x00008178, 0x00000100}, - {0x0000817c, 0x00000000}, - {0x000081c0, 0x00000000}, - {0x000081d0, 0x00003210}, - {0x000081ec, 0x00000000}, - {0x000081f0, 0x00000000}, - {0x000081f4, 0x00000000}, - {0x000081f8, 0x00000000}, - {0x000081fc, 0x00000000}, - {0x00008200, 0x00000000}, - {0x00008204, 0x00000000}, - {0x00008208, 0x00000000}, - {0x0000820c, 0x00000000}, - {0x00008210, 0x00000000}, - {0x00008214, 0x00000000}, - {0x00008218, 0x00000000}, - {0x0000821c, 0x00000000}, - {0x00008220, 0x00000000}, - {0x00008224, 0x00000000}, - {0x00008228, 0x00000000}, - {0x0000822c, 0x00000000}, - {0x00008230, 0x00000000}, - {0x00008234, 0x00000000}, - {0x00008238, 0x00000000}, - {0x0000823c, 0x00000000}, - {0x00008240, 0x00100000}, - {0x00008244, 0x0010f400}, - {0x00008248, 0x00000100}, - {0x0000824c, 0x0001e800}, - {0x00008250, 0x00000000}, - {0x00008254, 0x00000000}, - {0x00008258, 0x00000000}, - {0x0000825c, 0x400000ff}, - {0x00008260, 0x00080922}, - {0x00008264, 0x88a00010}, - {0x00008270, 0x00000000}, - {0x00008274, 0x40000000}, - {0x00008278, 0x003e4180}, - {0x0000827c, 0x00000000}, - {0x00008284, 0x0000002c}, - {0x00008288, 0x0000002c}, - {0x0000828c, 0x00000000}, - {0x00008294, 0x00000000}, - {0x00008298, 0x00000000}, - {0x0000829c, 0x00000000}, - {0x00008300, 0x00000040}, - {0x00008314, 0x00000000}, - {0x00008328, 0x00000000}, - {0x0000832c, 0x00000001}, - {0x00008330, 0x00000302}, - {0x00008334, 0x00000e00}, - {0x00008338, 0x00000000}, - {0x0000833c, 0x00000000}, - {0x00008340, 0x00010380}, - {0x00008344, 0x00481043}, - {0x00009808, 0x00000000}, - {0x0000980c, 0xafe68e30}, - {0x00009810, 0xfd14e000}, - {0x00009814, 0x9c0a9f6b}, - {0x0000981c, 0x00000000}, - {0x0000982c, 0x0000a000}, - {0x00009830, 0x00000000}, - {0x0000983c, 0x00200400}, - {0x0000984c, 0x0040233c}, - {0x00009854, 0x00000044}, - {0x00009900, 0x00000000}, - {0x00009904, 0x00000000}, - {0x00009908, 0x00000000}, - {0x0000990c, 0x00000000}, - {0x00009910, 0x01002310}, - {0x0000991c, 0x10000fff}, - {0x00009920, 0x04900000}, - {0x00009928, 0x00000001}, - {0x0000992c, 0x00000004}, - {0x00009934, 0x1e1f2022}, - {0x00009938, 0x0a0b0c0d}, - {0x0000993c, 0x00000000}, - {0x00009940, 0x14750604}, - {0x00009948, 0x9280c00a}, - {0x0000994c, 0x00020028}, - {0x00009954, 0x5f3ca3de}, - {0x00009958, 0x2108ecff}, - {0x00009968, 0x000003ce}, - {0x00009970, 0x1927b515}, - {0x00009974, 0x00000000}, - {0x00009978, 0x00000001}, - {0x0000997c, 0x00000000}, - {0x00009980, 0x00000000}, - {0x00009984, 0x00000000}, - {0x00009988, 0x00000000}, - {0x0000998c, 0x00000000}, - {0x00009990, 0x00000000}, - {0x00009994, 0x00000000}, - {0x00009998, 0x00000000}, - {0x0000999c, 0x00000000}, - {0x000099a0, 0x00000000}, - {0x000099a4, 0x00000001}, - {0x000099a8, 0x201fff00}, - {0x000099ac, 0x2def0a00}, - {0x000099b0, 0x03051000}, - {0x000099b4, 0x00000820}, - {0x000099dc, 0x00000000}, - {0x000099e0, 0x00000000}, - {0x000099e4, 0xaaaaaaaa}, - {0x000099e8, 0x3c466478}, - {0x000099ec, 0x0cc80caa}, - {0x000099f0, 0x00000000}, - {0x0000a208, 0x803e6788}, - {0x0000a210, 0x4080a333}, - {0x0000a214, 0x00206c10}, - {0x0000a218, 0x009c4060}, - {0x0000a220, 0x01834061}, - {0x0000a224, 0x00000400}, - {0x0000a228, 0x000003b5}, - {0x0000a22c, 0x00000000}, - {0x0000a234, 0x20202020}, - {0x0000a238, 0x20202020}, - {0x0000a244, 0x00000000}, - {0x0000a248, 0xfffffffc}, - {0x0000a24c, 0x00000000}, - {0x0000a254, 0x00000000}, - {0x0000a258, 0x0ccb5380}, - {0x0000a25c, 0x15151501}, - {0x0000a260, 0xdfa90f01}, - {0x0000a268, 0x00000000}, - {0x0000a26c, 0x0ebae9e6}, - {0x0000d270, 0x0d820820}, - {0x0000a278, 0x39ce739c}, - {0x0000a27c, 0x050e039c}, - {0x0000d35c, 0x07ffffef}, - {0x0000d360, 0x0fffffe7}, - {0x0000d364, 0x17ffffe5}, - {0x0000d368, 0x1fffffe4}, - {0x0000d36c, 0x37ffffe3}, - {0x0000d370, 0x3fffffe3}, - {0x0000d374, 0x57ffffe3}, - {0x0000d378, 0x5fffffe2}, - {0x0000d37c, 0x7fffffe2}, - {0x0000d380, 0x7f3c7bba}, - {0x0000d384, 0xf3307ff0}, - {0x0000a388, 0x0c000000}, - {0x0000a38c, 0x20202020}, - {0x0000a390, 0x20202020}, - {0x0000a394, 0x39ce739c}, - {0x0000a398, 0x0000039c}, - {0x0000a39c, 0x00000001}, - {0x0000a3a0, 0x00000000}, - {0x0000a3a4, 0x00000000}, - {0x0000a3a8, 0x00000000}, - {0x0000a3ac, 0x00000000}, - {0x0000a3b0, 0x00000000}, - {0x0000a3b4, 0x00000000}, - {0x0000a3b8, 0x00000000}, - {0x0000a3bc, 0x00000000}, - {0x0000a3c0, 0x00000000}, - {0x0000a3c4, 0x00000000}, - {0x0000a3cc, 0x20202020}, - {0x0000a3d0, 0x20202020}, - {0x0000a3d4, 0x20202020}, - {0x0000a3dc, 0x39ce739c}, - {0x0000a3e0, 0x0000039c}, - {0x0000a3e4, 0x00000000}, - {0x0000a3e8, 0x18c43433}, - {0x0000a3ec, 0x00f70081}, - {0x00007800, 0x00140000}, - {0x00007804, 0x0e4548d8}, - {0x00007808, 0x54214514}, - {0x0000780c, 0x02025820}, - {0x00007810, 0x71c0d388}, - {0x00007814, 0x924934a8}, - {0x0000781c, 0x00000000}, - {0x00007820, 0x00000c04}, - {0x00007824, 0x00d86fff}, - {0x00007828, 0x26d2491b}, - {0x0000782c, 0x6e36d97b}, - {0x00007830, 0xedb6d96c}, - {0x00007834, 0x71400086}, - {0x00007838, 0xfac68800}, - {0x0000783c, 0x0001fffe}, - {0x00007840, 0xffeb1a20}, - {0x00007844, 0x000c0db6}, - {0x00007848, 0x6db61b6f}, - {0x0000784c, 0x6d9b66db}, - {0x00007850, 0x6d8c6dba}, - {0x00007854, 0x00040000}, - {0x00007858, 0xdb003012}, - {0x0000785c, 0x04924914}, - {0x00007860, 0x21084210}, - {0x00007864, 0xf7d7ffde}, - {0x00007868, 0xc2034080}, - {0x0000786c, 0x48609eb4}, - {0x00007870, 0x10142c00}, -}; - static const u32 ar9285PciePhy_clkreq_always_on_L1_9285[][2] = { /* Addr allmodes */ {0x00004040, 0x9248fd00}, @@ -2966,761 +1760,6 @@ static const u32 ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = { {0x00004044, 0x00000000}, }; -static const u32 ar9287Modes_9287_1_0[][6] = { - {0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0}, - {0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0}, - {0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38, 0x00001180}, - {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008}, - {0x00008014, 0x00000000, 0x00000000, 0x10801600, 0x08400b00, 0x06e006e0}, - {0x0000801c, 0x00000000, 0x00000000, 0x12e00057, 0x12e0002b, 0x0988004f}, - {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810}, - {0x000081d0, 0x00003200, 0x00003200, 0x0000320a, 0x0000320a, 0x0000320a}, - {0x00008318, 0x00000000, 0x00000000, 0x00006880, 0x00003440, 0x00006880}, - {0x00009804, 0x00000000, 0x00000000, 0x000003c4, 0x00000300, 0x00000303}, - {0x00009820, 0x00000000, 0x00000000, 0x02020200, 0x02020200, 0x02020200}, - {0x00009824, 0x00000000, 0x00000000, 0x01000e0e, 0x01000e0e, 0x01000e0e}, - {0x00009828, 0x00000000, 0x00000000, 0x0a020001, 0x0a020001, 0x0a020001}, - {0x00009834, 0x00000000, 0x00000000, 0x00000e0e, 0x00000e0e, 0x00000e0e}, - {0x00009838, 0x00000003, 0x00000003, 0x00000007, 0x00000007, 0x00000007}, - {0x00009840, 0x206a002e, 0x206a002e, 0x206a012e, 0x206a012e, 0x206a012e}, - {0x00009844, 0x03720000, 0x03720000, 0x037216a0, 0x037216a0, 0x037216a0}, - {0x00009850, 0x60000000, 0x60000000, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2}, - {0x00009858, 0x7c000d00, 0x7c000d00, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e}, - {0x0000985c, 0x3100005e, 0x3100005e, 0x3139605e, 0x31395d5e, 0x31395d5e}, - {0x00009860, 0x00058d00, 0x00058d00, 0x00058d20, 0x00058d20, 0x00058d18}, - {0x00009864, 0x00000e00, 0x00000e00, 0x0001ce00, 0x0001ce00, 0x0001ce00}, - {0x00009868, 0x000040c0, 0x000040c0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, - {0x0000986c, 0x00000080, 0x00000080, 0x06903881, 0x06903881, 0x06903881}, - {0x00009914, 0x00000000, 0x00000000, 0x00001130, 0x00000898, 0x000007d0}, - {0x00009918, 0x00000000, 0x00000000, 0x00000016, 0x0000000b, 0x00000016}, - {0x00009924, 0xd00a8a01, 0xd00a8a01, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d}, - {0x00009944, 0xefbc0000, 0xefbc0000, 0xefbc1010, 0xefbc1010, 0xefbc1010}, - {0x00009960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010}, - {0x0000a960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010}, - {0x00009964, 0x00000000, 0x00000000, 0x00000210, 0x00000210, 0x00000210}, - {0x0000c968, 0x00000200, 0x00000200, 0x000003ce, 0x000003ce, 0x000003ce}, - {0x000099b8, 0x00000000, 0x00000000, 0x0000001c, 0x0000001c, 0x0000001c}, - {0x000099bc, 0x00000000, 0x00000000, 0x00000c00, 0x00000c00, 0x00000c00}, - {0x000099c0, 0x00000000, 0x00000000, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, - {0x0000a204, 0x00000440, 0x00000440, 0x00000444, 0x00000444, 0x00000444}, - {0x0000a20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a21c, 0x1803800a, 0x1803800a, 0x1883800a, 0x1883800a, 0x1883800a}, - {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000}, - {0x0000a250, 0x00000000, 0x00000000, 0x0004a000, 0x0004a000, 0x0004a000}, - {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e}, - {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -}; - -static const u32 ar9287Common_9287_1_0[][2] = { - /* Addr allmodes */ - {0x0000000c, 0x00000000}, - {0x00000030, 0x00020015}, - {0x00000034, 0x00000005}, - {0x00000040, 0x00000000}, - {0x00000044, 0x00000008}, - {0x00000048, 0x00000008}, - {0x0000004c, 0x00000010}, - {0x00000050, 0x00000000}, - {0x00000054, 0x0000001f}, - {0x00000800, 0x00000000}, - {0x00000804, 0x00000000}, - {0x00000808, 0x00000000}, - {0x0000080c, 0x00000000}, - {0x00000810, 0x00000000}, - {0x00000814, 0x00000000}, - {0x00000818, 0x00000000}, - {0x0000081c, 0x00000000}, - {0x00000820, 0x00000000}, - {0x00000824, 0x00000000}, - {0x00001040, 0x002ffc0f}, - {0x00001044, 0x002ffc0f}, - {0x00001048, 0x002ffc0f}, - {0x0000104c, 0x002ffc0f}, - {0x00001050, 0x002ffc0f}, - {0x00001054, 0x002ffc0f}, - {0x00001058, 0x002ffc0f}, - {0x0000105c, 0x002ffc0f}, - {0x00001060, 0x002ffc0f}, - {0x00001064, 0x002ffc0f}, - {0x00001230, 0x00000000}, - {0x00001270, 0x00000000}, - {0x00001038, 0x00000000}, - {0x00001078, 0x00000000}, - {0x000010b8, 0x00000000}, - {0x000010f8, 0x00000000}, - {0x00001138, 0x00000000}, - {0x00001178, 0x00000000}, - {0x000011b8, 0x00000000}, - {0x000011f8, 0x00000000}, - {0x00001238, 0x00000000}, - {0x00001278, 0x00000000}, - {0x000012b8, 0x00000000}, - {0x000012f8, 0x00000000}, - {0x00001338, 0x00000000}, - {0x00001378, 0x00000000}, - {0x000013b8, 0x00000000}, - {0x000013f8, 0x00000000}, - {0x00001438, 0x00000000}, - {0x00001478, 0x00000000}, - {0x000014b8, 0x00000000}, - {0x000014f8, 0x00000000}, - {0x00001538, 0x00000000}, - {0x00001578, 0x00000000}, - {0x000015b8, 0x00000000}, - {0x000015f8, 0x00000000}, - {0x00001638, 0x00000000}, - {0x00001678, 0x00000000}, - {0x000016b8, 0x00000000}, - {0x000016f8, 0x00000000}, - {0x00001738, 0x00000000}, - {0x00001778, 0x00000000}, - {0x000017b8, 0x00000000}, - {0x000017f8, 0x00000000}, - {0x0000103c, 0x00000000}, - {0x0000107c, 0x00000000}, - {0x000010bc, 0x00000000}, - {0x000010fc, 0x00000000}, - {0x0000113c, 0x00000000}, - {0x0000117c, 0x00000000}, - {0x000011bc, 0x00000000}, - {0x000011fc, 0x00000000}, - {0x0000123c, 0x00000000}, - {0x0000127c, 0x00000000}, - {0x000012bc, 0x00000000}, - {0x000012fc, 0x00000000}, - {0x0000133c, 0x00000000}, - {0x0000137c, 0x00000000}, - {0x000013bc, 0x00000000}, - {0x000013fc, 0x00000000}, - {0x0000143c, 0x00000000}, - {0x0000147c, 0x00000000}, - {0x00004030, 0x00000002}, - {0x0000403c, 0x00000002}, - {0x00004024, 0x0000001f}, - {0x00004060, 0x00000000}, - {0x00004064, 0x00000000}, - {0x00007010, 0x00000033}, - {0x00007020, 0x00000000}, - {0x00007034, 0x00000002}, - {0x00007038, 0x000004c2}, - {0x00008004, 0x00000000}, - {0x00008008, 0x00000000}, - {0x0000800c, 0x00000000}, - {0x00008018, 0x00000700}, - {0x00008020, 0x00000000}, - {0x00008038, 0x00000000}, - {0x0000803c, 0x00000000}, - {0x00008048, 0x40000000}, - {0x00008054, 0x00000000}, - {0x00008058, 0x00000000}, - {0x0000805c, 0x000fc78f}, - {0x00008060, 0x0000000f}, - {0x00008064, 0x00000000}, - {0x00008070, 0x00000000}, - {0x000080c0, 0x2a80001a}, - {0x000080c4, 0x05dc01e0}, - {0x000080c8, 0x1f402710}, - {0x000080cc, 0x01f40000}, - {0x000080d0, 0x00001e00}, - {0x000080d4, 0x00000000}, - {0x000080d8, 0x00400000}, - {0x000080e0, 0xffffffff}, - {0x000080e4, 0x0000ffff}, - {0x000080e8, 0x003f3f3f}, - {0x000080ec, 0x00000000}, - {0x000080f0, 0x00000000}, - {0x000080f4, 0x00000000}, - {0x000080f8, 0x00000000}, - {0x000080fc, 0x00020000}, - {0x00008100, 0x00020000}, - {0x00008104, 0x00000001}, - {0x00008108, 0x00000052}, - {0x0000810c, 0x00000000}, - {0x00008110, 0x00000168}, - {0x00008118, 0x000100aa}, - {0x0000811c, 0x00003210}, - {0x00008124, 0x00000000}, - {0x00008128, 0x00000000}, - {0x0000812c, 0x00000000}, - {0x00008130, 0x00000000}, - {0x00008134, 0x00000000}, - {0x00008138, 0x00000000}, - {0x0000813c, 0x00000000}, - {0x00008144, 0xffffffff}, - {0x00008168, 0x00000000}, - {0x0000816c, 0x00000000}, - {0x00008170, 0x18487320}, - {0x00008174, 0xfaa4fa50}, - {0x00008178, 0x00000100}, - {0x0000817c, 0x00000000}, - {0x000081c0, 0x00000000}, - {0x000081c4, 0x00000000}, - {0x000081d4, 0x00000000}, - {0x000081ec, 0x00000000}, - {0x000081f0, 0x00000000}, - {0x000081f4, 0x00000000}, - {0x000081f8, 0x00000000}, - {0x000081fc, 0x00000000}, - {0x00008200, 0x00000000}, - {0x00008204, 0x00000000}, - {0x00008208, 0x00000000}, - {0x0000820c, 0x00000000}, - {0x00008210, 0x00000000}, - {0x00008214, 0x00000000}, - {0x00008218, 0x00000000}, - {0x0000821c, 0x00000000}, - {0x00008220, 0x00000000}, - {0x00008224, 0x00000000}, - {0x00008228, 0x00000000}, - {0x0000822c, 0x00000000}, - {0x00008230, 0x00000000}, - {0x00008234, 0x00000000}, - {0x00008238, 0x00000000}, - {0x0000823c, 0x00000000}, - {0x00008240, 0x00100000}, - {0x00008244, 0x0010f400}, - {0x00008248, 0x00000100}, - {0x0000824c, 0x0001e800}, - {0x00008250, 0x00000000}, - {0x00008254, 0x00000000}, - {0x00008258, 0x00000000}, - {0x0000825c, 0x400000ff}, - {0x00008260, 0x00080922}, - {0x00008264, 0x88a00010}, - {0x00008270, 0x00000000}, - {0x00008274, 0x40000000}, - {0x00008278, 0x003e4180}, - {0x0000827c, 0x00000000}, - {0x00008284, 0x0000002c}, - {0x00008288, 0x0000002c}, - {0x0000828c, 0x000000ff}, - {0x00008294, 0x00000000}, - {0x00008298, 0x00000000}, - {0x0000829c, 0x00000000}, - {0x00008300, 0x00000040}, - {0x00008314, 0x00000000}, - {0x00008328, 0x00000000}, - {0x0000832c, 0x00000007}, - {0x00008330, 0x00000302}, - {0x00008334, 0x00000e00}, - {0x00008338, 0x00ff0000}, - {0x0000833c, 0x00000000}, - {0x00008340, 0x000107ff}, - {0x00008344, 0x01c81043}, - {0x00008360, 0xffffffff}, - {0x00008364, 0xffffffff}, - {0x00008368, 0x00000000}, - {0x00008370, 0x00000000}, - {0x00008374, 0x000000ff}, - {0x00008378, 0x00000000}, - {0x0000837c, 0x00000000}, - {0x00008380, 0xffffffff}, - {0x00008384, 0xffffffff}, - {0x00008390, 0x0fffffff}, - {0x00008394, 0x0fffffff}, - {0x00008398, 0x00000000}, - {0x0000839c, 0x00000000}, - {0x000083a0, 0x00000000}, - {0x00009808, 0x00000000}, - {0x0000980c, 0xafe68e30}, - {0x00009810, 0xfd14e000}, - {0x00009814, 0x9c0a9f6b}, - {0x0000981c, 0x00000000}, - {0x0000982c, 0x0000a000}, - {0x00009830, 0x00000000}, - {0x0000983c, 0x00200400}, - {0x0000984c, 0x0040233c}, - {0x0000a84c, 0x0040233c}, - {0x00009854, 0x00000044}, - {0x00009900, 0x00000000}, - {0x00009904, 0x00000000}, - {0x00009908, 0x00000000}, - {0x0000990c, 0x00000000}, - {0x00009910, 0x10002310}, - {0x0000991c, 0x10000fff}, - {0x00009920, 0x04900000}, - {0x0000a920, 0x04900000}, - {0x00009928, 0x00000001}, - {0x0000992c, 0x00000004}, - {0x00009930, 0x00000000}, - {0x0000a930, 0x00000000}, - {0x00009934, 0x1e1f2022}, - {0x00009938, 0x0a0b0c0d}, - {0x0000993c, 0x00000000}, - {0x00009948, 0x9280c00a}, - {0x0000994c, 0x00020028}, - {0x00009954, 0x5f3ca3de}, - {0x00009958, 0x0108ecff}, - {0x00009940, 0x14750604}, - {0x0000c95c, 0x004b6a8e}, - {0x00009970, 0x990bb515}, - {0x00009974, 0x00000000}, - {0x00009978, 0x00000001}, - {0x0000997c, 0x00000000}, - {0x000099a0, 0x00000000}, - {0x000099a4, 0x00000001}, - {0x000099a8, 0x201fff00}, - {0x000099ac, 0x0c6f0000}, - {0x000099b0, 0x03051000}, - {0x000099b4, 0x00000820}, - {0x000099c4, 0x06336f77}, - {0x000099c8, 0x6af65329}, - {0x000099cc, 0x08f186c8}, - {0x000099d0, 0x00046384}, - {0x000099dc, 0x00000000}, - {0x000099e0, 0x00000000}, - {0x000099e4, 0xaaaaaaaa}, - {0x000099e8, 0x3c466478}, - {0x000099ec, 0x0cc80caa}, - {0x000099f0, 0x00000000}, - {0x000099fc, 0x00001042}, - {0x0000a1f4, 0x00fffeff}, - {0x0000a1f8, 0x00f5f9ff}, - {0x0000a1fc, 0xb79f6427}, - {0x0000a208, 0x803e4788}, - {0x0000a210, 0x4080a333}, - {0x0000a214, 0x40206c10}, - {0x0000a218, 0x009c4060}, - {0x0000a220, 0x01834061}, - {0x0000a224, 0x00000400}, - {0x0000a228, 0x000003b5}, - {0x0000a22c, 0x233f7180}, - {0x0000a234, 0x20202020}, - {0x0000a238, 0x20202020}, - {0x0000a23c, 0x13c889af}, - {0x0000a240, 0x38490a20}, - {0x0000a244, 0x00000000}, - {0x0000a248, 0xfffffffc}, - {0x0000a24c, 0x00000000}, - {0x0000a254, 0x00000000}, - {0x0000a258, 0x0cdbd380}, - {0x0000a25c, 0x0f0f0f01}, - {0x0000a260, 0xdfa91f01}, - {0x0000a264, 0x00418a11}, - {0x0000b264, 0x00418a11}, - {0x0000a268, 0x00000000}, - {0x0000a26c, 0x0e79e5c6}, - {0x0000b26c, 0x0e79e5c6}, - {0x0000d270, 0x00820820}, - {0x0000a278, 0x1ce739ce}, - {0x0000a27c, 0x050701ce}, - {0x0000d35c, 0x07ffffef}, - {0x0000d360, 0x0fffffe7}, - {0x0000d364, 0x17ffffe5}, - {0x0000d368, 0x1fffffe4}, - {0x0000d36c, 0x37ffffe3}, - {0x0000d370, 0x3fffffe3}, - {0x0000d374, 0x57ffffe3}, - {0x0000d378, 0x5fffffe2}, - {0x0000d37c, 0x7fffffe2}, - {0x0000d380, 0x7f3c7bba}, - {0x0000d384, 0xf3307ff0}, - {0x0000a388, 0x0c000000}, - {0x0000a38c, 0x20202020}, - {0x0000a390, 0x20202020}, - {0x0000a394, 0x1ce739ce}, - {0x0000a398, 0x000001ce}, - {0x0000b398, 0x000001ce}, - {0x0000a39c, 0x00000001}, - {0x0000a3c8, 0x00000246}, - {0x0000a3cc, 0x20202020}, - {0x0000a3d0, 0x20202020}, - {0x0000a3d4, 0x20202020}, - {0x0000a3dc, 0x1ce739ce}, - {0x0000a3e0, 0x000001ce}, - {0x0000a3e4, 0x00000000}, - {0x0000a3e8, 0x18c43433}, - {0x0000a3ec, 0x00f70081}, - {0x0000a3f0, 0x01036a1e}, - {0x0000a3f4, 0x00000000}, - {0x0000b3f4, 0x00000000}, - {0x0000a7d8, 0x00000001}, - {0x00007800, 0x00000800}, - {0x00007804, 0x6c35ffb0}, - {0x00007808, 0x6db6c000}, - {0x0000780c, 0x6db6cb30}, - {0x00007810, 0x6db6cb6c}, - {0x00007814, 0x0501e200}, - {0x00007818, 0x0094128d}, - {0x0000781c, 0x976ee392}, - {0x00007820, 0xf75ff6fc}, - {0x00007824, 0x00040000}, - {0x00007828, 0xdb003012}, - {0x0000782c, 0x04924914}, - {0x00007830, 0x21084210}, - {0x00007834, 0x00140000}, - {0x00007838, 0x0e4548d8}, - {0x0000783c, 0x54214514}, - {0x00007840, 0x02025820}, - {0x00007844, 0x71c0d388}, - {0x00007848, 0x934934a8}, - {0x00007850, 0x00000000}, - {0x00007854, 0x00000800}, - {0x00007858, 0x6c35ffb0}, - {0x0000785c, 0x6db6c000}, - {0x00007860, 0x6db6cb2c}, - {0x00007864, 0x6db6cb6c}, - {0x00007868, 0x0501e200}, - {0x0000786c, 0x0094128d}, - {0x00007870, 0x976ee392}, - {0x00007874, 0xf75ff6fc}, - {0x00007878, 0x00040000}, - {0x0000787c, 0xdb003012}, - {0x00007880, 0x04924914}, - {0x00007884, 0x21084210}, - {0x00007888, 0x001b6db0}, - {0x0000788c, 0x00376b63}, - {0x00007890, 0x06db6db6}, - {0x00007894, 0x006d8000}, - {0x00007898, 0x48100000}, - {0x0000789c, 0x00000000}, - {0x000078a0, 0x08000000}, - {0x000078a4, 0x0007ffd8}, - {0x000078a8, 0x0007ffd8}, - {0x000078ac, 0x001c0020}, - {0x000078b0, 0x000611eb}, - {0x000078b4, 0x40008080}, - {0x000078b8, 0x2a850160}, -}; - -static const u32 ar9287Modes_tx_gain_9287_1_0[][6] = { - {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002, 0x00004002}, - {0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004, 0x00008004}, - {0x0000a30c, 0x00000000, 0x00000000, 0x0000c00a, 0x0000c00a, 0x0000c00a}, - {0x0000a310, 0x00000000, 0x00000000, 0x0001000c, 0x0001000c, 0x0001000c}, - {0x0000a314, 0x00000000, 0x00000000, 0x0001420b, 0x0001420b, 0x0001420b}, - {0x0000a318, 0x00000000, 0x00000000, 0x0001824a, 0x0001824a, 0x0001824a}, - {0x0000a31c, 0x00000000, 0x00000000, 0x0001c44a, 0x0001c44a, 0x0001c44a}, - {0x0000a320, 0x00000000, 0x00000000, 0x0002064a, 0x0002064a, 0x0002064a}, - {0x0000a324, 0x00000000, 0x00000000, 0x0002484a, 0x0002484a, 0x0002484a}, - {0x0000a328, 0x00000000, 0x00000000, 0x00028a4a, 0x00028a4a, 0x00028a4a}, - {0x0000a32c, 0x00000000, 0x00000000, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a}, - {0x0000a330, 0x00000000, 0x00000000, 0x00030e4a, 0x00030e4a, 0x00030e4a}, - {0x0000a334, 0x00000000, 0x00000000, 0x00034e8a, 0x00034e8a, 0x00034e8a}, - {0x0000a338, 0x00000000, 0x00000000, 0x00038e8c, 0x00038e8c, 0x00038e8c}, - {0x0000a33c, 0x00000000, 0x00000000, 0x0003cecc, 0x0003cecc, 0x0003cecc}, - {0x0000a340, 0x00000000, 0x00000000, 0x00040ed4, 0x00040ed4, 0x00040ed4}, - {0x0000a344, 0x00000000, 0x00000000, 0x00044edc, 0x00044edc, 0x00044edc}, - {0x0000a348, 0x00000000, 0x00000000, 0x00048ede, 0x00048ede, 0x00048ede}, - {0x0000a34c, 0x00000000, 0x00000000, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e}, - {0x0000a350, 0x00000000, 0x00000000, 0x00050f5e, 0x00050f5e, 0x00050f5e}, - {0x0000a354, 0x00000000, 0x00000000, 0x00054f9e, 0x00054f9e, 0x00054f9e}, - {0x0000a780, 0x00000000, 0x00000000, 0x00000060, 0x00000060, 0x00000060}, - {0x0000a784, 0x00000000, 0x00000000, 0x00004062, 0x00004062, 0x00004062}, - {0x0000a788, 0x00000000, 0x00000000, 0x00008064, 0x00008064, 0x00008064}, - {0x0000a78c, 0x00000000, 0x00000000, 0x0000c0a4, 0x0000c0a4, 0x0000c0a4}, - {0x0000a790, 0x00000000, 0x00000000, 0x000100b0, 0x000100b0, 0x000100b0}, - {0x0000a794, 0x00000000, 0x00000000, 0x000140b2, 0x000140b2, 0x000140b2}, - {0x0000a798, 0x00000000, 0x00000000, 0x000180b4, 0x000180b4, 0x000180b4}, - {0x0000a79c, 0x00000000, 0x00000000, 0x0001c0f4, 0x0001c0f4, 0x0001c0f4}, - {0x0000a7a0, 0x00000000, 0x00000000, 0x00020134, 0x00020134, 0x00020134}, - {0x0000a7a4, 0x00000000, 0x00000000, 0x000240fe, 0x000240fe, 0x000240fe}, - {0x0000a7a8, 0x00000000, 0x00000000, 0x0002813e, 0x0002813e, 0x0002813e}, - {0x0000a7ac, 0x00000000, 0x00000000, 0x0002c17e, 0x0002c17e, 0x0002c17e}, - {0x0000a7b0, 0x00000000, 0x00000000, 0x000301be, 0x000301be, 0x000301be}, - {0x0000a7b4, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe}, - {0x0000a7b8, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe}, - {0x0000a7bc, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe}, - {0x0000a7c0, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe}, - {0x0000a7c4, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe}, - {0x0000a7c8, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe}, - {0x0000a7cc, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe}, - {0x0000a7d0, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe}, - {0x0000a7d4, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe}, - {0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000, 0x0a1aa000}, -}; - -static const u32 ar9287Modes_rx_gain_9287_1_0[][6] = { - {0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120}, - {0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124}, - {0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128}, - {0x00009a0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c}, - {0x00009a10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130}, - {0x00009a14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194}, - {0x00009a18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198}, - {0x00009a1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c}, - {0x00009a20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210}, - {0x00009a24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284}, - {0x00009a28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288}, - {0x00009a2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c}, - {0x00009a30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290}, - {0x00009a34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294}, - {0x00009a38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0}, - {0x00009a3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4}, - {0x00009a40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8}, - {0x00009a44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac}, - {0x00009a48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0}, - {0x00009a4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4}, - {0x00009a50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8}, - {0x00009a54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4}, - {0x00009a58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708}, - {0x00009a5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c}, - {0x00009a60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710}, - {0x00009a64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04}, - {0x00009a68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08}, - {0x00009a6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c}, - {0x00009a70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10}, - {0x00009a74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14}, - {0x00009a78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18}, - {0x00009a7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c}, - {0x00009a80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90}, - {0x00009a84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94}, - {0x00009a88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98}, - {0x00009a8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4}, - {0x00009a90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8}, - {0x00009a94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04}, - {0x00009a98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08}, - {0x00009a9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c}, - {0x00009aa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10}, - {0x00009aa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14}, - {0x00009aa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18}, - {0x00009aac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c}, - {0x00009ab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90}, - {0x00009ab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18}, - {0x00009ab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24}, - {0x00009abc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28}, - {0x00009ac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314}, - {0x00009ac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318}, - {0x00009ac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c}, - {0x00009acc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390}, - {0x00009ad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394}, - {0x00009ad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398}, - {0x00009ad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4}, - {0x00009adc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8}, - {0x00009ae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac}, - {0x00009ae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0}, - {0x00009ae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380}, - {0x00009aec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384}, - {0x00009af0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388}, - {0x00009af4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710}, - {0x00009af8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714}, - {0x00009afc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718}, - {0x00009b00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10}, - {0x00009b04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14}, - {0x00009b08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18}, - {0x00009b0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c}, - {0x00009b10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90}, - {0x00009b14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94}, - {0x00009b18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c}, - {0x00009b1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90}, - {0x00009b20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94}, - {0x00009b24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0}, - {0x00009b28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4}, - {0x00009b2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8}, - {0x00009b30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac}, - {0x00009b34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0}, - {0x00009b38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4}, - {0x00009b3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1}, - {0x00009b40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5}, - {0x00009b44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9}, - {0x00009b48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad}, - {0x00009b4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1}, - {0x00009b50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5}, - {0x00009b54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9}, - {0x00009b58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5}, - {0x00009b5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9}, - {0x00009b60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd}, - {0x00009b64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1}, - {0x00009b68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5}, - {0x00009b6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2}, - {0x00009b70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6}, - {0x00009b74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca}, - {0x00009b78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce}, - {0x00009b7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2}, - {0x00009b80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6}, - {0x00009b84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda}, - {0x00009b88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7}, - {0x00009b8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb}, - {0x00009b90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf}, - {0x00009b94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3}, - {0x00009b98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7}, - {0x00009b9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009ba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009ba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009ba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009bac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009bb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009bb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009bb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009bbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009bc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009bc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009bc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009bcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009bd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009bd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009bd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009bdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009be0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009be4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009be8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009bec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009bf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009bf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009bf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009bfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000aa00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120}, - {0x0000aa04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124}, - {0x0000aa08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128}, - {0x0000aa0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c}, - {0x0000aa10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130}, - {0x0000aa14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194}, - {0x0000aa18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198}, - {0x0000aa1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c}, - {0x0000aa20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210}, - {0x0000aa24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284}, - {0x0000aa28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288}, - {0x0000aa2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c}, - {0x0000aa30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290}, - {0x0000aa34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294}, - {0x0000aa38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0}, - {0x0000aa3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4}, - {0x0000aa40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8}, - {0x0000aa44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac}, - {0x0000aa48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0}, - {0x0000aa4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4}, - {0x0000aa50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8}, - {0x0000aa54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4}, - {0x0000aa58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708}, - {0x0000aa5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c}, - {0x0000aa60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710}, - {0x0000aa64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04}, - {0x0000aa68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08}, - {0x0000aa6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c}, - {0x0000aa70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10}, - {0x0000aa74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14}, - {0x0000aa78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18}, - {0x0000aa7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c}, - {0x0000aa80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90}, - {0x0000aa84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94}, - {0x0000aa88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98}, - {0x0000aa8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4}, - {0x0000aa90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8}, - {0x0000aa94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04}, - {0x0000aa98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08}, - {0x0000aa9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c}, - {0x0000aaa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10}, - {0x0000aaa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14}, - {0x0000aaa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18}, - {0x0000aaac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c}, - {0x0000aab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90}, - {0x0000aab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18}, - {0x0000aab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24}, - {0x0000aabc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28}, - {0x0000aac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314}, - {0x0000aac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318}, - {0x0000aac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c}, - {0x0000aacc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390}, - {0x0000aad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394}, - {0x0000aad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398}, - {0x0000aad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4}, - {0x0000aadc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8}, - {0x0000aae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac}, - {0x0000aae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0}, - {0x0000aae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380}, - {0x0000aaec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384}, - {0x0000aaf0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388}, - {0x0000aaf4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710}, - {0x0000aaf8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714}, - {0x0000aafc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718}, - {0x0000ab00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10}, - {0x0000ab04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14}, - {0x0000ab08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18}, - {0x0000ab0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c}, - {0x0000ab10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90}, - {0x0000ab14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94}, - {0x0000ab18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c}, - {0x0000ab1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90}, - {0x0000ab20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94}, - {0x0000ab24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0}, - {0x0000ab28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4}, - {0x0000ab2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8}, - {0x0000ab30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac}, - {0x0000ab34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0}, - {0x0000ab38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4}, - {0x0000ab3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1}, - {0x0000ab40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5}, - {0x0000ab44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9}, - {0x0000ab48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad}, - {0x0000ab4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1}, - {0x0000ab50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5}, - {0x0000ab54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9}, - {0x0000ab58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5}, - {0x0000ab5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9}, - {0x0000ab60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd}, - {0x0000ab64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1}, - {0x0000ab68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5}, - {0x0000ab6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2}, - {0x0000ab70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6}, - {0x0000ab74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca}, - {0x0000ab78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce}, - {0x0000ab7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2}, - {0x0000ab80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6}, - {0x0000ab84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda}, - {0x0000ab88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7}, - {0x0000ab8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb}, - {0x0000ab90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf}, - {0x0000ab94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3}, - {0x0000ab98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7}, - {0x0000ab9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000aba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000aba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000aba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000abac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000abb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000abb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000abb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000abbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000abc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000abc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000abc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000abcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000abd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000abd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000abd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000abdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000abe0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000abe4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000abe8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000abec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000abf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000abf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000abf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x0000abfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, - {0x00009848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067}, - {0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067}, -}; - -static const u32 ar9287PciePhy_clkreq_always_on_L1_9287_1_0[][2] = { - /* Addr allmodes */ - {0x00004040, 0x9248fd00}, - {0x00004040, 0x24924924}, - {0x00004040, 0xa8000019}, - {0x00004040, 0x13160820}, - {0x00004040, 0xe5980560}, - {0x00004040, 0xc01dcffd}, - {0x00004040, 0x1aaabe41}, - {0x00004040, 0xbe105554}, - {0x00004040, 0x00043007}, - {0x00004044, 0x00000000}, -}; - -static const u32 ar9287PciePhy_clkreq_off_L1_9287_1_0[][2] = { - /* Addr allmodes */ - {0x00004040, 0x9248fd00}, - {0x00004040, 0x24924924}, - {0x00004040, 0xa8000019}, - {0x00004040, 0x13160820}, - {0x00004040, 0xe5980560}, - {0x00004040, 0xc01dcffc}, - {0x00004040, 0x1aaabe41}, - {0x00004040, 0xbe105554}, - {0x00004040, 0x00043007}, - {0x00004044, 0x00000000}, -}; - static const u32 ar9287Modes_9287_1_1[][6] = { {0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0}, {0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0}, diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index 4922b8d4a93..adbf031fbc5 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c @@ -477,7 +477,8 @@ static void ar9002_hw_do_getnf(struct ath_hw *ah, nfarray[0] = sign_extend(nf, 9); nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR); - nfarray[3] = sign_extend(nf, 9); + if (IS_CHAN_HT40(ah->curchan)) + nfarray[3] = sign_extend(nf, 9); if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) return; @@ -486,7 +487,8 @@ static void ar9002_hw_do_getnf(struct ath_hw *ah, nfarray[1] = sign_extend(nf, 9); nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR9280_PHY_CH1_EXT_MINCCA_PWR); - nfarray[4] = sign_extend(nf, 9); + if (IS_CHAN_HT40(ah->curchan)) + nfarray[4] = sign_extend(nf, 9); } static void ar9002_hw_set_nf_limits(struct ath_hw *ah) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 06ef71019c1..5b995bee70a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -579,12 +579,39 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, rxs->rs_flags |= ATH9K_RX_DECRYPT_BUSY; if ((rxsp->status11 & AR_RxFrameOK) == 0) { + /* + * AR_CRCErr will bet set to true if we're on the last + * subframe and the AR_PostDelimCRCErr is caught. + * In a way this also gives us a guarantee that when + * (!(AR_CRCErr) && (AR_PostDelimCRCErr)) we cannot + * possibly be reviewing the last subframe. AR_CRCErr + * is the CRC of the actual data. + */ if (rxsp->status11 & AR_CRCErr) { rxs->rs_status |= ATH9K_RXERR_CRC; } else if (rxsp->status11 & AR_PHYErr) { - rxs->rs_status |= ATH9K_RXERR_PHY; phyerr = MS(rxsp->status11, AR_PHYErrCode); - rxs->rs_phyerr = phyerr; + /* + * If we reach a point here where AR_PostDelimCRCErr is + * true it implies we're *not* on the last subframe. In + * in that case that we know already that the CRC of + * the frame was OK, and MAC would send an ACK for that + * subframe, even if we did get a phy error of type + * ATH9K_PHYERR_OFDM_RESTART. This is only applicable + * to frame that are prior to the last subframe. + * The AR_PostDelimCRCErr is the CRC for the MPDU + * delimiter, which contains the 4 reserved bits, + * the MPDU length (12 bits), and follows the MPDU + * delimiter for an A-MPDU subframe (0x4E = 'N' ASCII). + */ + if ((phyerr == ATH9K_PHYERR_OFDM_RESTART) && + (rxsp->status11 & AR_PostDelimCRCErr)) { + rxs->rs_phyerr = 0; + } else { + rxs->rs_status |= ATH9K_RXERR_PHY; + rxs->rs_phyerr = phyerr; + } + } else if (rxsp->status11 & AR_DecryptCRCErr) { rxs->rs_status |= ATH9K_RXERR_DECRYPT; } else if (rxsp->status11 & AR_MichaelErr) { diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 7c93338540a..a753a431bb1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -1029,6 +1029,9 @@ static void ar9003_hw_do_getnf(struct ath_hw *ah, nf = MS(REG_READ(ah, AR_PHY_CCA_2), AR_PHY_CH2_MINCCA_PWR); nfarray[2] = sign_extend(nf, 9); + if (!IS_CHAN_HT40(ah->curchan)) + return; + nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); nfarray[3] = sign_extend(nf, 9); diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 6e486a508ed..998ae2c49ed 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -687,7 +687,7 @@ bool ath9k_all_wiphys_idle(struct ath_softc *sc); void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle); void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue); -void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue); +bool ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue); void ath_start_rfkill_poll(struct ath_softc *sc); extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 7f4c55f90e7..139289e4e93 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -172,26 +172,9 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) struct ath9k_nfcal_hist *h; unsigned i, j; int32_t val; - u8 chainmask; + u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; struct ath_common *common = ath9k_hw_common(ah); - if (AR_SREV_9300_20_OR_LATER(ah)) - chainmask = 0x3F; - else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) - chainmask = 0x9; - else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) { - if ((ah->rxchainmask & 0x2) || (ah->rxchainmask & 0x4)) - chainmask = 0x1B; - else - chainmask = 0x09; - } else { - if (ah->rxchainmask & 0x4) - chainmask = 0x3F; - else if (ah->rxchainmask & 0x2) - chainmask = 0x1B; - else - chainmask = 0x09; - } h = ah->nfCalHist; for (i = 0; i < NUM_NF_READINGS; i++) { @@ -278,7 +261,7 @@ static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf) ath_print(common, ATH_DBG_CALIBRATE, "NF calibrated [%s] [chain %d] is %d\n", - (i > 3 ? "ext" : "ctl"), i % 3, nf[i]); + (i >= 3 ? "ext" : "ctl"), i % 3, nf[i]); if (nf[i] > limit->max) { ath_print(common, ATH_DBG_CALIBRATE, diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index afafc4d4b8f..9cccd12e8f2 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -222,7 +222,7 @@ static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah, struct ath9k_channel *chan, struct cal_data_per_freq_4k *pRawDataSet, u8 *bChans, u16 availPiers, - u16 tPdGainOverlap, int16_t *pMinCalPower, + u16 tPdGainOverlap, u16 *pPdGainBoundaries, u8 *pPDADCValues, u16 numXpdGains) { @@ -308,8 +308,6 @@ static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah, } } - *pMinCalPower = (int16_t)(minPwrT4[0] / 2); - k = 0; for (i = 0; i < numXpdGains; i++) { @@ -399,7 +397,6 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK]; u16 numPiers, i, j; - int16_t tMinCalPower; u16 numXpdGain, xpdMask; u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 }; u32 reg32, regOffset, regChainOffset; @@ -452,7 +449,7 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan, pRawDataset, pCalBChans, numPiers, pdGainOverlap_t2, - &tMinCalPower, gainBoundaries, + gainBoundaries, pdadcValues, numXpdGain); ENABLE_REGWRITE_BUFFER(ah); diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 37207dfd179..4a52cf03808 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -223,7 +223,6 @@ static void ath9k_hw_get_ar9287_gain_boundaries_pdadcs(struct ath_hw *ah, struct cal_data_per_freq_ar9287 *pRawDataSet, u8 *bChans, u16 availPiers, u16 tPdGainOverlap, - int16_t *pMinCalPower, u16 *pPdGainBoundaries, u8 *pPDADCValues, u16 numXpdGains) @@ -303,7 +302,6 @@ static void ath9k_hw_get_ar9287_gain_boundaries_pdadcs(struct ath_hw *ah, } } - *pMinCalPower = (int16_t)(minPwrT4[0] / 2); k = 0; for (i = 0; i < numXpdGains; i++) { @@ -458,7 +456,6 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, u8 pdadcValues[AR9287_NUM_PDADC_VALUES]; u16 gainBoundaries[AR9287_PD_GAINS_IN_MASK]; u16 numPiers = 0, i, j; - int16_t tMinCalPower; u16 numXpdGain, xpdMask; u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0}; u32 reg32, regOffset, regChainOffset, regval; @@ -530,7 +527,6 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, pRawDataset, pCalBChans, numPiers, pdGainOverlap_t2, - &tMinCalPower, gainBoundaries, pdadcValues, numXpdGain); diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 02e6c2a55fe..afa2b73ddbd 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -593,7 +593,7 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah, struct ath9k_channel *chan, struct cal_data_per_freq *pRawDataSet, u8 *bChans, u16 availPiers, - u16 tPdGainOverlap, int16_t *pMinCalPower, + u16 tPdGainOverlap, u16 *pPdGainBoundaries, u8 *pPDADCValues, u16 numXpdGains) { @@ -675,8 +675,6 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah, } } - *pMinCalPower = (int16_t)(minPwrT4[0] / 2); - k = 0; for (i = 0; i < numXpdGains; i++) { @@ -838,7 +836,7 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK]; u16 numPiers, i, j; - int16_t tMinCalPower, diff = 0; + int16_t diff = 0; u16 numXpdGain, xpdMask; u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 }; u32 reg32, regOffset, regChainOffset; @@ -923,7 +921,6 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, chan, pRawDataset, pCalBChans, numPiers, pdGainOverlap_t2, - &tMinCalPower, gainBoundaries, pdadcValues, numXpdGain); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index e38ca66db84..cf9bcc67ade 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -438,10 +438,11 @@ static void ath9k_htc_update_rate(struct ath9k_htc_priv *priv, bss_conf->bssid, be32_to_cpu(trate.capflags)); } -int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - enum ieee80211_ampdu_mlme_action action, u16 tid) +static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + enum ieee80211_ampdu_mlme_action action, + u16 tid) { struct ath_common *common = ath9k_hw_common(priv->ah); struct ath9k_htc_target_aggr aggr; @@ -492,8 +493,7 @@ static int ath9k_debugfs_open(struct inode *inode, struct file *file) static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct ath9k_htc_priv *priv = - (struct ath9k_htc_priv *) file->private_data; + struct ath9k_htc_priv *priv = file->private_data; struct ath9k_htc_target_stats cmd_rsp; char buf[512]; unsigned int len = 0; @@ -524,6 +524,9 @@ static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, len += snprintf(buf + len, sizeof(buf) - len, "%19s : %10u\n", "TX Rate", priv->debug.txrate); + if (len > sizeof(buf)) + len = sizeof(buf); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -536,8 +539,7 @@ static const struct file_operations fops_tgt_stats = { static ssize_t read_file_xmit(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct ath9k_htc_priv *priv = - (struct ath9k_htc_priv *) file->private_data; + struct ath9k_htc_priv *priv = file->private_data; char buf[512]; unsigned int len = 0; @@ -570,6 +572,9 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, "%20s : %10u\n", "VO queued", priv->debug.tx_stats.queue_stats[WME_AC_VO]); + if (len > sizeof(buf)) + len = sizeof(buf); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -582,8 +587,7 @@ static const struct file_operations fops_xmit = { static ssize_t read_file_recv(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct ath9k_htc_priv *priv = - (struct ath9k_htc_priv *) file->private_data; + struct ath9k_htc_priv *priv = file->private_data; char buf[512]; unsigned int len = 0; @@ -597,6 +601,9 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, "%20s : %10u\n", "SKBs Dropped", priv->debug.rx_stats.skb_dropped); + if (len > sizeof(buf)) + len = sizeof(buf); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); } diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 2f83f975b89..8d291ccf5c8 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -532,7 +532,8 @@ static int __ath9k_hw_init(struct ath_hw *ah) if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) { if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI || - (AR_SREV_9280(ah) && !ah->is_pciexpress)) { + ((AR_SREV_9160(ah) || AR_SREV_9280(ah)) && + !ah->is_pciexpress)) { ah->config.serialize_regmode = SER_REG_MODE_ON; } else { diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index fe730cb16ec..243c1775f34 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -787,12 +787,12 @@ void ath9k_deinit_device(struct ath_softc *sc) ieee80211_unregister_hw(aphy->hw); ieee80211_free_hw(aphy->hw); } - kfree(sc->sec_wiphy); ieee80211_unregister_hw(hw); ath_rx_cleanup(sc); ath_tx_cleanup(sc); ath9k_deinit_softc(sc); + kfree(sc->sec_wiphy); } void ath_descdma_cleanup(struct ath_softc *sc, diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 4c0831ff6e9..0429dda0961 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -279,7 +279,7 @@ void ath_paprd_calibrate(struct work_struct *work) hdr = (struct ieee80211_hdr *)skb->data; ftype = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC; hdr->frame_control = cpu_to_le16(ftype); - hdr->duration_id = 10; + hdr->duration_id = cpu_to_le16(10); memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN); memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); @@ -857,9 +857,14 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) ath9k_ps_wakeup(sc); ieee80211_stop_queues(hw); - /* Disable LED */ - ath9k_hw_set_gpio(ah, ah->led_pin, 1); - ath9k_hw_cfg_gpio_input(ah, ah->led_pin); + /* + * Keep the LED on when the radio is disabled + * during idle unassociated state. + */ + if (!sc->ps_idle) { + ath9k_hw_set_gpio(ah, ah->led_pin, 1); + ath9k_hw_cfg_gpio_input(ah, ah->led_pin); + } /* Disable interrupts */ ath9k_hw_set_interrupts(ah, 0); @@ -1264,6 +1269,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) struct ath_softc *sc = aphy->sc; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); + int i; mutex_lock(&sc->mutex); @@ -1276,7 +1282,12 @@ static void ath9k_stop(struct ieee80211_hw *hw) cancel_work_sync(&sc->paprd_work); cancel_work_sync(&sc->hw_check_work); - if (!sc->num_sec_wiphy) { + for (i = 0; i < sc->num_sec_wiphy; i++) { + if (sc->sec_wiphy[i]) + break; + } + + if (i == sc->num_sec_wiphy) { cancel_delayed_work_sync(&sc->wiphy_work); cancel_work_sync(&sc->chan_work); } @@ -1983,11 +1994,12 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) mutex_lock(&sc->mutex); if (ath9k_wiphy_scanning(sc)) { - printk(KERN_DEBUG "ath9k: Two wiphys trying to scan at the " - "same time\n"); /* - * Do not allow the concurrent scanning state for now. This - * could be improved with scanning control moved into ath9k. + * There is a race here in mac80211 but fixing it requires + * we revisit how we handle the scan complete callback. + * After mac80211 fixes we will not have configured hardware + * to the home channel nor would we have configured the RX + * filter yet. */ mutex_unlock(&sc->mutex); return; @@ -2003,6 +2015,10 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) mutex_unlock(&sc->mutex); } +/* + * XXX: this requires a revisit after the driver + * scan_complete gets moved to another place/removed in mac80211. + */ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) { struct ath_wiphy *aphy = hw->priv; diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 257b10ba6f5..b5b651413e7 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -209,11 +209,8 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) } ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name)); - printk(KERN_INFO - "%s: %s mem=0x%lx, irq=%d\n", - wiphy_name(hw->wiphy), - hw_name, - (unsigned long)mem, pdev->irq); + wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n", + hw_name, (unsigned long)mem, pdev->irq); return 0; diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 600ee0ba288..e49be733d54 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -20,95 +20,145 @@ #include "ath9k.h" static const struct ath_rate_table ar5416_11na_ratetable = { - 43, + 68, 8, /* MCS start */ { - { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ - 5400, 0, 12, 0, 0, 0, 0, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ - 7800, 1, 18, 0, 1, 1, 1, 1 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ - 10000, 2, 24, 2, 2, 2, 2, 2 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ - 13900, 3, 36, 2, 3, 3, 3, 3 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ - 17300, 4, 48, 4, 4, 4, 4, 4 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ - 23000, 5, 72, 4, 5, 5, 5, 5 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ - 27400, 6, 96, 4, 6, 6, 6, 6 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ - 29300, 7, 108, 4, 7, 7, 7, 7 }, - { VALID_2040, VALID_2040, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ - 6400, 0, 0, 0, 8, 25, 8, 25 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ - 12700, 1, 1, 2, 9, 26, 9, 26 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ - 18800, 2, 2, 2, 10, 27, 10, 27 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ - 25000, 3, 3, 4, 11, 28, 11, 28 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ - 36700, 4, 4, 4, 12, 29, 12, 29 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ - 48100, 5, 5, 4, 13, 30, 13, 30 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ - 53500, 6, 6, 4, 14, 31, 14, 31 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ - 59000, 7, 7, 4, 15, 32, 15, 33 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ - 12700, 8, 8, 3, 16, 34, 16, 34 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ - 24800, 9, 9, 2, 17, 35, 17, 35 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ - 36600, 10, 10, 2, 18, 36, 18, 36 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ - 48100, 11, 11, 4, 19, 37, 19, 37 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ - 69500, 12, 12, 4, 20, 38, 20, 38 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ - 89500, 13, 13, 4, 21, 39, 21, 39 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ - 98900, 14, 14, 4, 22, 40, 22, 40 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ - 108300, 15, 15, 4, 23, 41, 24, 42 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS_HGI, 144400, /* 144.4 Mb */ - 12000, 15, 15, 4, 23, 41, 24, 42 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ - 13200, 0, 0, 0, 8, 25, 25, 25 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ - 25900, 1, 1, 2, 9, 26, 26, 26 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ - 38600, 2, 2, 2, 10, 27, 27, 27 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ - 49800, 3, 3, 4, 11, 28, 28, 28 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ - 72200, 4, 4, 4, 12, 29, 29, 29 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ - 92900, 5, 5, 4, 13, 30, 30, 30 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ - 102700, 6, 6, 4, 14, 31, 31, 31 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ - 112000, 7, 7, 4, 15, 32, 33, 33 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ - 122000, 7, 7, 4, 15, 32, 33, 33 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ - 25800, 8, 8, 0, 16, 34, 34, 34 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ - 49800, 9, 9, 2, 17, 35, 35, 35 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ - 71900, 10, 10, 2, 18, 36, 36, 36 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ - 92500, 11, 11, 4, 19, 37, 37, 37 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ - 130300, 12, 12, 4, 20, 38, 38, 38 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ - 162800, 13, 13, 4, 21, 39, 39, 39 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ - 178200, 14, 14, 4, 22, 40, 40, 40 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ - 192100, 15, 15, 4, 23, 41, 42, 42 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ - 207000, 15, 15, 4, 23, 41, 42, 42 }, + [0] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 6000, + 5400, 0, 12, 0, 0, 0, 0 }, /* 6 Mb */ + [1] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 9000, + 7800, 1, 18, 0, 1, 1, 1 }, /* 9 Mb */ + [2] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, + 10000, 2, 24, 2, 2, 2, 2 }, /* 12 Mb */ + [3] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, + 13900, 3, 36, 2, 3, 3, 3 }, /* 18 Mb */ + [4] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, + 17300, 4, 48, 4, 4, 4, 4 }, /* 24 Mb */ + [5] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, + 23000, 5, 72, 4, 5, 5, 5 }, /* 36 Mb */ + [6] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, + 27400, 6, 96, 4, 6, 6, 6 }, /* 48 Mb */ + [7] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, + 29300, 7, 108, 4, 7, 7, 7 }, /* 54 Mb */ + [8] = { RC_HT_SDT_2040, WLAN_RC_PHY_HT_20_SS, 6500, + 6400, 0, 0, 0, 38, 8, 38 }, /* 6.5 Mb */ + [9] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 13000, + 12700, 1, 1, 2, 39, 9, 39 }, /* 13 Mb */ + [10] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 19500, + 18800, 2, 2, 2, 40, 10, 40 }, /* 19.5 Mb */ + [11] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 26000, + 25000, 3, 3, 4, 41, 11, 41 }, /* 26 Mb */ + [12] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 39000, + 36700, 4, 4, 4, 42, 12, 42 }, /* 39 Mb */ + [13] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 52000, + 48100, 5, 5, 4, 43, 13, 43 }, /* 52 Mb */ + [14] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 58500, + 53500, 6, 6, 4, 44, 14, 44 }, /* 58.5 Mb */ + [15] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 65000, + 59000, 7, 7, 4, 45, 16, 46 }, /* 65 Mb */ + [16] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS_HGI, 72200, + 65400, 7, 7, 4, 45, 16, 46 }, /* 75 Mb */ + [17] = { RC_INVALID, WLAN_RC_PHY_HT_20_DS, 13000, + 12700, 8, 8, 0, 47, 17, 47 }, /* 13 Mb */ + [18] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 26000, + 24800, 9, 9, 2, 48, 18, 48 }, /* 26 Mb */ + [19] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 39000, + 36600, 10, 10, 2, 49, 19, 49 }, /* 39 Mb */ + [20] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 52000, + 48100, 11, 11, 4, 50, 20, 50 }, /* 52 Mb */ + [21] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 78000, + 69500, 12, 12, 4, 51, 21, 51 }, /* 78 Mb */ + [22] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 104000, + 89500, 13, 13, 4, 52, 22, 52 }, /* 104 Mb */ + [23] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 117000, + 98900, 14, 14, 4, 53, 23, 53 }, /* 117 Mb */ + [24] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 130000, + 108300, 15, 15, 4, 54, 25, 55 }, /* 130 Mb */ + [25] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS_HGI, 144400, + 120000, 15, 15, 4, 54, 25, 55 }, /* 144.4 Mb */ + [26] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 19500, + 17400, 16, 16, 0, 56, 26, 56 }, /* 19.5 Mb */ + [27] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 39000, + 35100, 17, 17, 2, 57, 27, 57 }, /* 39 Mb */ + [28] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 58500, + 52600, 18, 18, 2, 58, 28, 58 }, /* 58.5 Mb */ + [29] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 78000, + 70400, 19, 19, 4, 59, 29, 59 }, /* 78 Mb */ + [30] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 117000, + 104900, 20, 20, 4, 60, 31, 61 }, /* 117 Mb */ + [31] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS_HGI, 130000, + 115800, 20, 20, 4, 60, 31, 61 }, /* 130 Mb*/ + [32] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 156000, + 137200, 21, 21, 4, 62, 33, 63 }, /* 156 Mb */ + [33] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 173300, + 151100, 21, 21, 4, 62, 33, 63 }, /* 173.3 Mb */ + [34] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 175500, + 152800, 22, 22, 4, 64, 35, 65 }, /* 175.5 Mb */ + [35] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 195000, + 168400, 22, 22, 4, 64, 35, 65 }, /* 195 Mb*/ + [36] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 195000, + 168400, 23, 23, 4, 66, 37, 67 }, /* 195 Mb */ + [37] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 216700, + 185000, 23, 23, 4, 66, 37, 67 }, /* 216.7 Mb */ + [38] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 13500, + 13200, 0, 0, 0, 38, 38, 38 }, /* 13.5 Mb*/ + [39] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 27500, + 25900, 1, 1, 2, 39, 39, 39 }, /* 27.0 Mb*/ + [40] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 40500, + 38600, 2, 2, 2, 40, 40, 40 }, /* 40.5 Mb*/ + [41] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 54000, + 49800, 3, 3, 4, 41, 41, 41 }, /* 54 Mb */ + [42] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 81500, + 72200, 4, 4, 4, 42, 42, 42 }, /* 81 Mb */ + [43] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 108000, + 92900, 5, 5, 4, 43, 43, 43 }, /* 108 Mb */ + [44] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 121500, + 102700, 6, 6, 4, 44, 44, 44 }, /* 121.5 Mb*/ + [45] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 135000, + 112000, 7, 7, 4, 45, 46, 46 }, /* 135 Mb */ + [46] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, + 122000, 7, 7, 4, 45, 46, 46 }, /* 150 Mb */ + [47] = { RC_INVALID, WLAN_RC_PHY_HT_40_DS, 27000, + 25800, 8, 8, 0, 47, 47, 47 }, /* 27 Mb */ + [48] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 54000, + 49800, 9, 9, 2, 48, 48, 48 }, /* 54 Mb */ + [49] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 81000, + 71900, 10, 10, 2, 49, 49, 49 }, /* 81 Mb */ + [50] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 108000, + 92500, 11, 11, 4, 50, 50, 50 }, /* 108 Mb */ + [51] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 162000, + 130300, 12, 12, 4, 51, 51, 51 }, /* 162 Mb */ + [52] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 216000, + 162800, 13, 13, 4, 52, 52, 52 }, /* 216 Mb */ + [53] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 243000, + 178200, 14, 14, 4, 53, 53, 53 }, /* 243 Mb */ + [54] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 270000, + 192100, 15, 15, 4, 54, 55, 55 }, /* 270 Mb */ + [55] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS_HGI, 300000, + 207000, 15, 15, 4, 54, 55, 55 }, /* 300 Mb */ + [56] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 40500, + 36100, 16, 16, 0, 56, 56, 56 }, /* 40.5 Mb */ + [57] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 81000, + 72900, 17, 17, 2, 57, 57, 57 }, /* 81 Mb */ + [58] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 121500, + 108300, 18, 18, 2, 58, 58, 58 }, /* 121.5 Mb */ + [59] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 162000, + 142000, 19, 19, 4, 59, 59, 59 }, /* 162 Mb */ + [60] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000, + 205100, 20, 20, 4, 60, 61, 61 }, /* 243 Mb */ + [61] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000, + 224700, 20, 20, 4, 60, 61, 61 }, /* 270 Mb */ + [62] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000, + 263100, 21, 21, 4, 62, 63, 63 }, /* 324 Mb */ + [63] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000, + 288000, 21, 21, 4, 62, 63, 63 }, /* 360 Mb */ + [64] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 364500, + 290700, 22, 22, 4, 64, 65, 65 }, /* 364.5 Mb */ + [65] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 405000, + 317200, 22, 22, 4, 64, 65, 65 }, /* 405 Mb */ + [66] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 405000, + 317200, 23, 23, 4, 66, 67, 67 }, /* 405 Mb */ + [67] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 450000, + 346400, 23, 23, 4, 66, 67, 67 }, /* 450 Mb */ }, 50, /* probe interval */ WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ @@ -118,103 +168,153 @@ static const struct ath_rate_table ar5416_11na_ratetable = { * for HT are the 64K max aggregate limit */ static const struct ath_rate_table ar5416_11ng_ratetable = { - 47, + 72, 12, /* MCS start */ { - { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ - 900, 0, 2, 0, 0, 0, 0, 0 }, - { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ - 1900, 1, 4, 1, 1, 1, 1, 1 }, - { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ - 4900, 2, 11, 2, 2, 2, 2, 2 }, - { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ - 8100, 3, 22, 3, 3, 3, 3, 3 }, - { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ - 5400, 4, 12, 4, 4, 4, 4, 4 }, - { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ - 7800, 5, 18, 4, 5, 5, 5, 5 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ - 10100, 6, 24, 6, 6, 6, 6, 6 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ - 14100, 7, 36, 6, 7, 7, 7, 7 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ - 17700, 8, 48, 8, 8, 8, 8, 8 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ - 23700, 9, 72, 8, 9, 9, 9, 9 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ - 27400, 10, 96, 8, 10, 10, 10, 10 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ - 30900, 11, 108, 8, 11, 11, 11, 11 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ - 6400, 0, 0, 4, 12, 29, 12, 29 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ - 12700, 1, 1, 6, 13, 30, 13, 30 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ - 18800, 2, 2, 6, 14, 31, 14, 31 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ - 25000, 3, 3, 8, 15, 32, 15, 32 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ - 36700, 4, 4, 8, 16, 33, 16, 33 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ - 48100, 5, 5, 8, 17, 34, 17, 34 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ - 53500, 6, 6, 8, 18, 35, 18, 35 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ - 59000, 7, 7, 8, 19, 36, 19, 37 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ - 12700, 8, 8, 4, 20, 38, 20, 38 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ - 24800, 9, 9, 6, 21, 39, 21, 39 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ - 36600, 10, 10, 6, 22, 40, 22, 40 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ - 48100, 11, 11, 8, 23, 41, 23, 41 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ - 69500, 12, 12, 8, 24, 42, 24, 42 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ - 89500, 13, 13, 8, 25, 43, 25, 43 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ - 98900, 14, 14, 8, 26, 44, 26, 44 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ - 108300, 15, 15, 8, 27, 45, 28, 46 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS_HGI, 144400, /* 130 Mb */ - 120000, 15, 15, 8, 27, 45, 28, 46 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ - 13200, 0, 0, 8, 12, 29, 29, 29 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ - 25900, 1, 1, 8, 13, 30, 30, 30 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ - 38600, 2, 2, 8, 14, 31, 31, 31 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ - 49800, 3, 3, 8, 15, 32, 32, 32 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ - 72200, 4, 4, 8, 16, 33, 33, 33 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ - 92900, 5, 5, 8, 17, 34, 34, 34 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ - 102700, 6, 6, 8, 18, 35, 35, 35 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ - 112000, 7, 7, 8, 19, 36, 37, 37 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ - 122000, 7, 7, 8, 19, 36, 37, 37 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ - 25800, 8, 8, 8, 20, 38, 38, 38 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ - 49800, 9, 9, 8, 21, 39, 39, 39 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ - 71900, 10, 10, 8, 22, 40, 40, 40 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ - 92500, 11, 11, 8, 23, 41, 41, 41 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ - 130300, 12, 12, 8, 24, 42, 42, 42 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ - 162800, 13, 13, 8, 25, 43, 43, 43 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ - 178200, 14, 14, 8, 26, 44, 44, 44 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ - 192100, 15, 15, 8, 27, 45, 46, 46 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ - 207000, 15, 15, 8, 27, 45, 46, 46 }, + [0] = { RC_ALL, WLAN_RC_PHY_CCK, 1000, + 900, 0, 2, 0, 0, 0, 0 }, /* 1 Mb */ + [1] = { RC_ALL, WLAN_RC_PHY_CCK, 2000, + 1900, 1, 4, 1, 1, 1, 1 }, /* 2 Mb */ + [2] = { RC_ALL, WLAN_RC_PHY_CCK, 5500, + 4900, 2, 11, 2, 2, 2, 2 }, /* 5.5 Mb */ + [3] = { RC_ALL, WLAN_RC_PHY_CCK, 11000, + 8100, 3, 22, 3, 3, 3, 3 }, /* 11 Mb */ + [4] = { RC_INVALID, WLAN_RC_PHY_OFDM, 6000, + 5400, 4, 12, 4, 4, 4, 4 }, /* 6 Mb */ + [5] = { RC_INVALID, WLAN_RC_PHY_OFDM, 9000, + 7800, 5, 18, 4, 5, 5, 5 }, /* 9 Mb */ + [6] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, + 10100, 6, 24, 6, 6, 6, 6 }, /* 12 Mb */ + [7] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, + 14100, 7, 36, 6, 7, 7, 7 }, /* 18 Mb */ + [8] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, + 17700, 8, 48, 8, 8, 8, 8 }, /* 24 Mb */ + [9] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, + 23700, 9, 72, 8, 9, 9, 9 }, /* 36 Mb */ + [10] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, + 27400, 10, 96, 8, 10, 10, 10 }, /* 48 Mb */ + [11] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, + 30900, 11, 108, 8, 11, 11, 11 }, /* 54 Mb */ + [12] = { RC_INVALID, WLAN_RC_PHY_HT_20_SS, 6500, + 6400, 0, 0, 4, 42, 12, 42 }, /* 6.5 Mb */ + [13] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 13000, + 12700, 1, 1, 6, 43, 13, 43 }, /* 13 Mb */ + [14] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 19500, + 18800, 2, 2, 6, 44, 14, 44 }, /* 19.5 Mb*/ + [15] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 26000, + 25000, 3, 3, 8, 45, 15, 45 }, /* 26 Mb */ + [16] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 39000, + 36700, 4, 4, 8, 46, 16, 46 }, /* 39 Mb */ + [17] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 52000, + 48100, 5, 5, 8, 47, 17, 47 }, /* 52 Mb */ + [18] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 58500, + 53500, 6, 6, 8, 48, 18, 48 }, /* 58.5 Mb */ + [19] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 65000, + 59000, 7, 7, 8, 49, 20, 50 }, /* 65 Mb */ + [20] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS_HGI, 72200, + 65400, 7, 7, 8, 49, 20, 50 }, /* 65 Mb*/ + [21] = { RC_INVALID, WLAN_RC_PHY_HT_20_DS, 13000, + 12700, 8, 8, 4, 51, 21, 51 }, /* 13 Mb */ + [22] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 26000, + 24800, 9, 9, 6, 52, 22, 52 }, /* 26 Mb */ + [23] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 39000, + 36600, 10, 10, 6, 53, 23, 53 }, /* 39 Mb */ + [24] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 52000, + 48100, 11, 11, 8, 54, 24, 54 }, /* 52 Mb */ + [25] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 78000, + 69500, 12, 12, 8, 55, 25, 55 }, /* 78 Mb */ + [26] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 104000, + 89500, 13, 13, 8, 56, 26, 56 }, /* 104 Mb */ + [27] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 117000, + 98900, 14, 14, 8, 57, 27, 57 }, /* 117 Mb */ + [28] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 130000, + 108300, 15, 15, 8, 58, 29, 59 }, /* 130 Mb */ + [29] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS_HGI, 144400, + 120000, 15, 15, 8, 58, 29, 59 }, /* 144.4 Mb */ + [30] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 19500, + 17400, 16, 16, 4, 60, 30, 60 }, /* 19.5 Mb */ + [31] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 39000, + 35100, 17, 17, 6, 61, 31, 61 }, /* 39 Mb */ + [32] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 58500, + 52600, 18, 18, 6, 62, 32, 62 }, /* 58.5 Mb */ + [33] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 78000, + 70400, 19, 19, 8, 63, 33, 63 }, /* 78 Mb */ + [34] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 117000, + 104900, 20, 20, 8, 64, 35, 65 }, /* 117 Mb */ + [35] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS_HGI, 130000, + 115800, 20, 20, 8, 64, 35, 65 }, /* 130 Mb */ + [36] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 156000, + 137200, 21, 21, 8, 66, 37, 67 }, /* 156 Mb */ + [37] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 173300, + 151100, 21, 21, 8, 66, 37, 67 }, /* 173.3 Mb */ + [38] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 175500, + 152800, 22, 22, 8, 68, 39, 69 }, /* 175.5 Mb */ + [39] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 195000, + 168400, 22, 22, 8, 68, 39, 69 }, /* 195 Mb */ + [40] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 195000, + 168400, 23, 23, 8, 70, 41, 71 }, /* 195 Mb */ + [41] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 216700, + 185000, 23, 23, 8, 70, 41, 71 }, /* 216.7 Mb */ + [42] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 13500, + 13200, 0, 0, 8, 42, 42, 42 }, /* 13.5 Mb */ + [43] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 27500, + 25900, 1, 1, 8, 43, 43, 43 }, /* 27.0 Mb */ + [44] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 40500, + 38600, 2, 2, 8, 44, 44, 44 }, /* 40.5 Mb */ + [45] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 54000, + 49800, 3, 3, 8, 45, 45, 45 }, /* 54 Mb */ + [46] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 81500, + 72200, 4, 4, 8, 46, 46, 46 }, /* 81 Mb */ + [47] = { RC_HT_S_40 , WLAN_RC_PHY_HT_40_SS, 108000, + 92900, 5, 5, 8, 47, 47, 47 }, /* 108 Mb */ + [48] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 121500, + 102700, 6, 6, 8, 48, 48, 48 }, /* 121.5 Mb */ + [49] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 135000, + 112000, 7, 7, 8, 49, 50, 50 }, /* 135 Mb */ + [50] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, + 122000, 7, 7, 8, 49, 50, 50 }, /* 150 Mb */ + [51] = { RC_INVALID, WLAN_RC_PHY_HT_40_DS, 27000, + 25800, 8, 8, 8, 51, 51, 51 }, /* 27 Mb */ + [52] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 54000, + 49800, 9, 9, 8, 52, 52, 52 }, /* 54 Mb */ + [53] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 81000, + 71900, 10, 10, 8, 53, 53, 53 }, /* 81 Mb */ + [54] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 108000, + 92500, 11, 11, 8, 54, 54, 54 }, /* 108 Mb */ + [55] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 162000, + 130300, 12, 12, 8, 55, 55, 55 }, /* 162 Mb */ + [56] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 216000, + 162800, 13, 13, 8, 56, 56, 56 }, /* 216 Mb */ + [57] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 243000, + 178200, 14, 14, 8, 57, 57, 57 }, /* 243 Mb */ + [58] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 270000, + 192100, 15, 15, 8, 58, 59, 59 }, /* 270 Mb */ + [59] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS_HGI, 300000, + 207000, 15, 15, 8, 58, 59, 59 }, /* 300 Mb */ + [60] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 40500, + 36100, 16, 16, 8, 60, 60, 60 }, /* 40.5 Mb */ + [61] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 81000, + 72900, 17, 17, 8, 61, 61, 61 }, /* 81 Mb */ + [62] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 121500, + 108300, 18, 18, 8, 62, 62, 62 }, /* 121.5 Mb */ + [63] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 162000, + 142000, 19, 19, 8, 63, 63, 63 }, /* 162 Mb */ + [64] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000, + 205100, 20, 20, 8, 64, 65, 65 }, /* 243 Mb */ + [65] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000, + 224700, 20, 20, 8, 64, 65, 65 }, /* 170 Mb */ + [66] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000, + 263100, 21, 21, 8, 66, 67, 67 }, /* 324 Mb */ + [67] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000, + 288000, 21, 21, 8, 66, 67, 67 }, /* 360 Mb */ + [68] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 364500, + 290700, 22, 22, 8, 68, 69, 69 }, /* 364.5 Mb */ + [69] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 405000, + 317200, 22, 22, 8, 68, 69, 69 }, /* 405 Mb */ + [70] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 405000, + 317200, 23, 23, 8, 70, 71, 71 }, /* 405 Mb */ + [71] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 450000, + 346400, 23, 23, 8, 70, 71, 71 }, /* 450 Mb */ }, 50, /* probe interval */ WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ @@ -224,22 +324,22 @@ static const struct ath_rate_table ar5416_11a_ratetable = { 8, 0, { - { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ - 5400, 0, 12, 0, 0, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ - 7800, 1, 18, 0, 1, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ - 10000, 2, 24, 2, 2, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ - 13900, 3, 36, 2, 3, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ - 17300, 4, 48, 4, 4, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ - 23000, 5, 72, 4, 5, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ - 27400, 6, 96, 4, 6, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ - 29300, 7, 108, 4, 7, 0 }, + { RC_L_SDT, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ + 5400, 0, 12, 0}, + { RC_L_SDT, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ + 7800, 1, 18, 0}, + { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ + 10000, 2, 24, 2}, + { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ + 13900, 3, 36, 2}, + { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ + 17300, 4, 48, 4}, + { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ + 23000, 5, 72, 4}, + { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ + 27400, 6, 96, 4}, + { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ + 29300, 7, 108, 4}, }, 50, /* probe interval */ 0, /* Phy rates allowed initially */ @@ -249,30 +349,30 @@ static const struct ath_rate_table ar5416_11g_ratetable = { 12, 0, { - { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ - 900, 0, 2, 0, 0, 0 }, - { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ - 1900, 1, 4, 1, 1, 0 }, - { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ - 4900, 2, 11, 2, 2, 0 }, - { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ - 8100, 3, 22, 3, 3, 0 }, - { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ - 5400, 4, 12, 4, 4, 0 }, - { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ - 7800, 5, 18, 4, 5, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ - 10000, 6, 24, 6, 6, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ - 13900, 7, 36, 6, 7, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ - 17300, 8, 48, 8, 8, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ - 23000, 9, 72, 8, 9, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ - 27400, 10, 96, 8, 10, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ - 29300, 11, 108, 8, 11, 0 }, + { RC_L_SDT, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ + 900, 0, 2, 0}, + { RC_L_SDT, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ + 1900, 1, 4, 1}, + { RC_L_SDT, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ + 4900, 2, 11, 2}, + { RC_L_SDT, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ + 8100, 3, 22, 3}, + { RC_INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ + 5400, 4, 12, 4}, + { RC_INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ + 7800, 5, 18, 4}, + { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ + 10000, 6, 24, 6}, + { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ + 13900, 7, 36, 6}, + { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ + 17300, 8, 48, 8}, + { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ + 23000, 9, 72, 8}, + { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ + 27400, 10, 96, 8}, + { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ + 29300, 11, 108, 8}, }, 50, /* probe interval */ 0, /* Phy rates allowed initially */ @@ -342,7 +442,7 @@ static inline void ath_rc_set_valid_txmask(struct ath_rate_priv *ath_rc_priv, u8 index, int valid_tx_rate) { BUG_ON(index > ath_rc_priv->rate_table_size); - ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? 1 : 0; + ath_rc_priv->valid_rate_index[index] = !!valid_tx_rate; } static inline @@ -374,6 +474,8 @@ static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw) return 0; if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG)) return 0; + if (WLAN_RC_PHY_TS(phy) && !(capflag & WLAN_RC_TS_FLAG)) + return 0; if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG)) return 0; if (!ignore_cw && WLAN_RC_PHY_HT(phy)) @@ -404,13 +506,9 @@ static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv, u32 capflag) { u8 i, hi = 0; - u32 valid; for (i = 0; i < rate_table->rate_cnt; i++) { - valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? - rate_table->info[i].valid_single_stream : - rate_table->info[i].valid); - if (valid == 1) { + if (rate_table->info[i].rate_flags & RC_LEGACY) { u32 phy = rate_table->info[i].phy; u8 valid_rate_count = 0; @@ -422,7 +520,7 @@ static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv, ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i; ath_rc_priv->valid_phy_ratecnt[phy] += 1; ath_rc_set_valid_txmask(ath_rc_priv, i, 1); - hi = A_MAX(hi, i); + hi = i; } } @@ -440,9 +538,7 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, for (i = 0; i < rateset->rs_nrates; i++) { for (j = 0; j < rate_table->rate_cnt; j++) { u32 phy = rate_table->info[j].phy; - u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? - rate_table->info[j].valid_single_stream : - rate_table->info[j].valid); + u16 rate_flags = rate_table->info[i].rate_flags; u8 rate = rateset->rs_rates[i]; u8 dot11rate = rate_table->info[j].dot11rate; @@ -451,8 +547,9 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, * (VALID/VALID_20/VALID_40) flags */ if ((rate == dot11rate) && - ((valid & WLAN_RC_CAP_MODE(capflag)) == - WLAN_RC_CAP_MODE(capflag)) && + (rate_flags & WLAN_RC_CAP_MODE(capflag)) == + WLAN_RC_CAP_MODE(capflag) && + (rate_flags & WLAN_RC_CAP_STREAM(capflag)) && !WLAN_RC_PHY_HT(phy)) { u8 valid_rate_count = 0; @@ -486,14 +583,13 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv, for (i = 0; i < rateset->rs_nrates; i++) { for (j = 0; j < rate_table->rate_cnt; j++) { u32 phy = rate_table->info[j].phy; - u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? - rate_table->info[j].valid_single_stream : - rate_table->info[j].valid); + u16 rate_flags = rate_table->info[j].rate_flags; u8 rate = rateset->rs_rates[i]; u8 dot11rate = rate_table->info[j].dot11rate; if ((rate != dot11rate) || !WLAN_RC_PHY_HT(phy) || - !WLAN_RC_PHY_HT_VALID(valid, capflag)) + !(rate_flags & WLAN_RC_CAP_STREAM(capflag)) || + !WLAN_RC_PHY_HT_VALID(rate_flags, capflag)) continue; if (!ath_rc_valid_phyrate(phy, capflag, 0)) @@ -589,12 +685,15 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc, if (rate > (ath_rc_priv->rate_table_size - 1)) rate = ath_rc_priv->rate_table_size - 1; - if (rate_table->info[rate].valid && - (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)) + if (RC_TS_ONLY(rate_table->info[rate].rate_flags) && + (ath_rc_priv->ht_cap & WLAN_RC_TS_FLAG)) + return rate; + + if (RC_DS_OR_LATER(rate_table->info[rate].rate_flags) && + (ath_rc_priv->ht_cap & (WLAN_RC_DS_FLAG | WLAN_RC_TS_FLAG))) return rate; - if (rate_table->info[rate].valid_single_stream && - !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)) + if (RC_SS_OR_LEGACY(rate_table->info[rate].rate_flags)) return rate; /* This should not happen */ @@ -1007,12 +1106,19 @@ static void ath_rc_update_ht(struct ath_softc *sc, static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, struct ieee80211_tx_rate *rate) { - int rix; + int rix = 0, i = 0; + int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 }; if (!(rate->flags & IEEE80211_TX_RC_MCS)) return rate->idx; - rix = rate->idx + rate_table->mcs_start; + while (rate->idx > mcs_rix_off[i] && + i < sizeof(mcs_rix_off)/sizeof(int)) { + rix++; i++; + } + + rix += rate->idx + rate_table->mcs_start; + if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && (rate->flags & IEEE80211_TX_RC_SHORT_GI)) rix = rate_table->info[rix].ht_index; @@ -1020,8 +1126,6 @@ static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, rix = rate_table->info[rix].sgi_index; else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) rix = rate_table->info[rix].cw40index; - else - rix = rate_table->info[rix].base_index; return rix; } @@ -1203,13 +1307,14 @@ static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta, if (sta->ht_cap.ht_supported) { caps = WLAN_RC_HT_FLAG; - if (sta->ht_cap.mcs.rx_mask[1]) + if (sta->ht_cap.mcs.rx_mask[1] && sta->ht_cap.mcs.rx_mask[2]) + caps |= WLAN_RC_TS_FLAG | WLAN_RC_DS_FLAG; + else if (sta->ht_cap.mcs.rx_mask[1]) caps |= WLAN_RC_DS_FLAG; if (is_cw40) caps |= WLAN_RC_40_FLAG; if (is_sgi) caps |= WLAN_RC_SGI_FLAG; - } return caps; diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index 3d8d40cdc99..dc108265450 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h @@ -24,32 +24,63 @@ struct ath_softc; #define ATH_RATE_MAX 30 -#define RATE_TABLE_SIZE 64 +#define RATE_TABLE_SIZE 72 #define MAX_TX_RATE_PHY 48 -/* VALID_ALL - valid for 20/40/Legacy, - * VALID - Legacy only, - * VALID_20 - HT 20 only, - * VALID_40 - HT 40 only */ -#define INVALID 0x0 -#define VALID 0x1 -#define VALID_20 0x2 -#define VALID_40 0x4 -#define VALID_2040 (VALID_20|VALID_40) -#define VALID_ALL (VALID_2040|VALID) +#define RC_INVALID 0x0000 +#define RC_LEGACY 0x0001 +#define RC_SS 0x0002 +#define RC_DS 0x0004 +#define RC_TS 0x0008 +#define RC_HT_20 0x0010 +#define RC_HT_40 0x0020 + +#define RC_STREAM_MASK 0xe +#define RC_DS_OR_LATER(f) ((((f) & RC_STREAM_MASK) == RC_DS) || \ + (((f) & RC_STREAM_MASK) == (RC_DS | RC_TS))) +#define RC_TS_ONLY(f) (((f) & RC_STREAM_MASK) == RC_TS) +#define RC_SS_OR_LEGACY(f) ((f) & (RC_SS | RC_LEGACY)) + +#define RC_HT_2040 (RC_HT_20 | RC_HT_40) +#define RC_ALL_STREAM (RC_SS | RC_DS | RC_TS) +#define RC_L_SD (RC_LEGACY | RC_SS | RC_DS) +#define RC_L_SDT (RC_LEGACY | RC_SS | RC_DS | RC_TS) +#define RC_HT_S_20 (RC_HT_20 | RC_SS) +#define RC_HT_D_20 (RC_HT_20 | RC_DS) +#define RC_HT_T_20 (RC_HT_20 | RC_TS) +#define RC_HT_S_40 (RC_HT_40 | RC_SS) +#define RC_HT_D_40 (RC_HT_40 | RC_DS) +#define RC_HT_T_40 (RC_HT_40 | RC_TS) + +#define RC_HT_SD_20 (RC_HT_20 | RC_SS | RC_DS) +#define RC_HT_DT_20 (RC_HT_20 | RC_DS | RC_TS) +#define RC_HT_SD_40 (RC_HT_40 | RC_SS | RC_DS) +#define RC_HT_DT_40 (RC_HT_40 | RC_DS | RC_TS) + +#define RC_HT_SD_2040 (RC_HT_2040 | RC_SS | RC_DS) +#define RC_HT_SDT_2040 (RC_HT_2040 | RC_SS | RC_DS | RC_TS) + +#define RC_HT_SDT_20 (RC_HT_20 | RC_SS | RC_DS | RC_TS) +#define RC_HT_SDT_40 (RC_HT_40 | RC_SS | RC_DS | RC_TS) + +#define RC_ALL (RC_LEGACY | RC_HT_2040 | RC_ALL_STREAM) enum { WLAN_RC_PHY_OFDM, WLAN_RC_PHY_CCK, WLAN_RC_PHY_HT_20_SS, WLAN_RC_PHY_HT_20_DS, + WLAN_RC_PHY_HT_20_TS, WLAN_RC_PHY_HT_40_SS, WLAN_RC_PHY_HT_40_DS, + WLAN_RC_PHY_HT_40_TS, WLAN_RC_PHY_HT_20_SS_HGI, WLAN_RC_PHY_HT_20_DS_HGI, + WLAN_RC_PHY_HT_20_TS_HGI, WLAN_RC_PHY_HT_40_SS_HGI, WLAN_RC_PHY_HT_40_DS_HGI, + WLAN_RC_PHY_HT_40_TS_HGI, WLAN_RC_PHY_MAX }; @@ -57,36 +88,50 @@ enum { || (_phy == WLAN_RC_PHY_HT_40_DS) \ || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) +#define WLAN_RC_PHY_TS(_phy) ((_phy == WLAN_RC_PHY_HT_20_TS) \ + || (_phy == WLAN_RC_PHY_HT_40_TS) \ + || (_phy == WLAN_RC_PHY_HT_20_TS_HGI) \ + || (_phy == WLAN_RC_PHY_HT_40_TS_HGI)) #define WLAN_RC_PHY_20(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS) \ || (_phy == WLAN_RC_PHY_HT_20_DS) \ + || (_phy == WLAN_RC_PHY_HT_20_TS) \ || (_phy == WLAN_RC_PHY_HT_20_SS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_20_DS_HGI)) + || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ + || (_phy == WLAN_RC_PHY_HT_20_TS_HGI)) #define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \ || (_phy == WLAN_RC_PHY_HT_40_DS) \ + || (_phy == WLAN_RC_PHY_HT_40_TS) \ || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) + || (_phy == WLAN_RC_PHY_HT_40_DS_HGI) \ + || (_phy == WLAN_RC_PHY_HT_40_TS_HGI)) #define WLAN_RC_PHY_SGI(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS_HGI) \ || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ + || (_phy == WLAN_RC_PHY_HT_20_TS_HGI) \ || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) + || (_phy == WLAN_RC_PHY_HT_40_DS_HGI) \ + || (_phy == WLAN_RC_PHY_HT_40_TS_HGI)) #define WLAN_RC_PHY_HT(_phy) (_phy >= WLAN_RC_PHY_HT_20_SS) #define WLAN_RC_CAP_MODE(capflag) (((capflag & WLAN_RC_HT_FLAG) ? \ - (capflag & WLAN_RC_40_FLAG) ? VALID_40 : VALID_20 : VALID)) + ((capflag & WLAN_RC_40_FLAG) ? RC_HT_40 : RC_HT_20) : RC_LEGACY)) + +#define WLAN_RC_CAP_STREAM(capflag) (((capflag & WLAN_RC_TS_FLAG) ? \ + (RC_TS) : ((capflag & WLAN_RC_DS_FLAG) ? RC_DS : RC_SS))) /* Return TRUE if flag supports HT20 && client supports HT20 or * return TRUE if flag supports HT40 && client supports HT40. * This is used becos some rates overlap between HT20/HT40. */ #define WLAN_RC_PHY_HT_VALID(flag, capflag) \ - (((flag & VALID_20) && !(capflag & WLAN_RC_40_FLAG)) || \ - ((flag & VALID_40) && (capflag & WLAN_RC_40_FLAG))) + (((flag & RC_HT_20) && !(capflag & WLAN_RC_40_FLAG)) || \ + ((flag & RC_HT_40) && (capflag & WLAN_RC_40_FLAG))) #define WLAN_RC_DS_FLAG (0x01) -#define WLAN_RC_40_FLAG (0x02) -#define WLAN_RC_SGI_FLAG (0x04) -#define WLAN_RC_HT_FLAG (0x08) +#define WLAN_RC_TS_FLAG (0x02) +#define WLAN_RC_40_FLAG (0x04) +#define WLAN_RC_SGI_FLAG (0x08) +#define WLAN_RC_HT_FLAG (0x10) /** * struct ath_rate_table - Rate Control table @@ -110,15 +155,13 @@ struct ath_rate_table { int rate_cnt; int mcs_start; struct { - u8 valid; - u8 valid_single_stream; + u16 rate_flags; u8 phy; u32 ratekbps; u32 user_ratekbps; u8 ratecode; u8 dot11rate; u8 ctrl_rate; - u8 base_index; u8 cw40index; u8 sgi_index; u8 ht_index; diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c index 89423ca23d2..fd20241f57d 100644 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ b/drivers/net/wireless/ath/ath9k/virtual.c @@ -695,16 +695,18 @@ void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle) idle ? "idle" : "not-idle"); } /* Only bother starting a queue on an active virtual wiphy */ -void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue) +bool ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue) { struct ieee80211_hw *hw = sc->pri_wiphy->hw; unsigned int i; + bool txq_started = false; spin_lock_bh(&sc->wiphy_lock); /* Start the primary wiphy */ if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) { ieee80211_wake_queue(hw, skb_queue); + txq_started = true; goto unlock; } @@ -718,11 +720,13 @@ void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue) hw = aphy->hw; ieee80211_wake_queue(hw, skb_queue); + txq_started = true; break; } unlock: spin_unlock_bh(&sc->wiphy_lock); + return txq_started; } /* Go ahead and propagate information to all virtual wiphys, it won't hurt */ diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index bd52ac11179..501b72821b4 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -329,7 +329,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; bool rc_update = true; struct ieee80211_tx_rate rates[4]; - unsigned long flags; skb = bf->bf_mpdu; hdr = (struct ieee80211_hdr *)skb->data; @@ -346,9 +345,21 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, if (!sta) { rcu_read_unlock(); - spin_lock_irqsave(&sc->tx.txbuflock, flags); - list_splice_tail_init(bf_q, &sc->tx.txbuf); - spin_unlock_irqrestore(&sc->tx.txbuflock, flags); + INIT_LIST_HEAD(&bf_head); + while (bf) { + bf_next = bf->bf_next; + + bf->bf_state.bf_type |= BUF_XRETRY; + if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) || + !bf->bf_stale || bf_next != NULL) + list_move_tail(&bf->list, &bf_head); + + ath_tx_rc_status(bf, ts, 0, 0, false); + ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, + 0, 0); + + bf = bf_next; + } return; } @@ -507,6 +518,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, bf = bf_next; } + /* prepend un-acked frames to the beginning of the pending frame queue */ + if (!list_empty(&bf_pending)) { + spin_lock_bh(&txq->axq_lock); + list_splice(&bf_pending, &tid->buf_q); + ath_tx_queue_tid(txq, tid); + spin_unlock_bh(&txq->axq_lock); + } + if (tid->state & AGGR_CLEANUP) { if (tid->baw_head == tid->baw_tail) { tid->state &= ~AGGR_ADDBA_COMPLETE; @@ -519,14 +538,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, return; } - /* prepend un-acked frames to the beginning of the pending frame queue */ - if (!list_empty(&bf_pending)) { - spin_lock_bh(&txq->axq_lock); - list_splice(&bf_pending, &tid->buf_q); - ath_tx_queue_tid(txq, tid); - spin_unlock_bh(&txq->axq_lock); - } - rcu_read_unlock(); if (needreset) @@ -2066,8 +2077,8 @@ static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) spin_lock_bh(&txq->axq_lock); if (txq->stopped && sc->tx.pending_frames[qnum] < ATH_MAX_QDEPTH) { - ath_mac80211_start_queue(sc, qnum); - txq->stopped = 0; + if (ath_mac80211_start_queue(sc, qnum)) + txq->stopped = 0; } spin_unlock_bh(&txq->axq_lock); } diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 8e243798ae9..20631ae2ddd 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -108,7 +108,7 @@ int b43_modparam_verbose = B43_VERBOSITY_DEFAULT; module_param_named(verbose, b43_modparam_verbose, int, 0644); MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug"); -int b43_modparam_pio = B43_PIO_DEFAULT; +static int b43_modparam_pio = B43_PIO_DEFAULT; module_param_named(pio, b43_modparam_pio, int, 0644); MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO"); diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c index 29bf34ced86..0dc33b65e86 100644 --- a/drivers/net/wireless/b43/phy_g.c +++ b/drivers/net/wireless/b43/phy_g.c @@ -972,7 +972,7 @@ b43_radio_interference_mitigation_enable(struct b43_wldev *dev, int mode) b43_phy_maskset(dev, 0x04A2, 0xFFF0, 0x000B); if (phy->rev >= 3) { - b43_phy_mask(dev, 0x048A, (u16)~0x8000); + b43_phy_mask(dev, 0x048A, 0x7FFF); b43_phy_maskset(dev, 0x0415, 0x8000, 0x36D8); b43_phy_maskset(dev, 0x0416, 0x8000, 0x36D8); b43_phy_maskset(dev, 0x0417, 0xFE00, 0x016D); diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index c6afe9d9459..fd50eb11624 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -1145,7 +1145,7 @@ static void lpphy_write_tx_pctl_mode_to_hardware(struct b43_wldev *dev) B43_WARN_ON(1); } b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD, - (u16)~B43_LPPHY_TX_PWR_CTL_CMD_MODE, ctl); + ~B43_LPPHY_TX_PWR_CTL_CMD_MODE & 0xFFFF, ctl); } static void lpphy_set_tx_power_control(struct b43_wldev *dev, @@ -1522,11 +1522,11 @@ static void lpphy_tx_pctl_init_hw(struct b43_wldev *dev) b43_phy_mask(dev, B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT, 0xFF); b43_phy_write(dev, B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT, 0xA); b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD, - (u16)~B43_LPPHY_TX_PWR_CTL_CMD_MODE, + ~B43_LPPHY_TX_PWR_CTL_CMD_MODE & 0xFFFF, B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF); b43_phy_mask(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0xF8FF); b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD, - (u16)~B43_LPPHY_TX_PWR_CTL_CMD_MODE, + ~B43_LPPHY_TX_PWR_CTL_CMD_MODE & 0xFFFF, B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW); if (dev->phy.rev < 2) { @@ -2698,7 +2698,7 @@ static enum b43_txpwr_result b43_lpphy_op_recalc_txpower(struct b43_wldev *dev, return B43_TXPWR_RES_DONE; } -void b43_lpphy_op_switch_analog(struct b43_wldev *dev, bool on) +static void b43_lpphy_op_switch_analog(struct b43_wldev *dev, bool on) { if (on) { b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xfff8); diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 3d6b3377596..5a725703770 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -509,7 +509,8 @@ static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core) b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001); b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001); - b43_phy_maskset(dev, B43_NPHY_RFSEQCA, (u16)~B43_NPHY_RFSEQCA_RXDIS, + b43_phy_maskset(dev, B43_NPHY_RFSEQCA, + ~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF, ((1 - core) << B43_NPHY_RFSEQCA_RXDIS_SHIFT)); b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN, ((1 - core) << B43_NPHY_RFSEQCA_TXEN_SHIFT)); @@ -762,7 +763,7 @@ static void b43_nphy_stop_playback(struct b43_wldev *dev) if (tmp & 0x1) b43_phy_set(dev, B43_NPHY_SAMP_CMD, B43_NPHY_SAMP_CMD_STOP); else if (tmp & 0x2) - b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, (u16)~0x8000); + b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF); b43_phy_mask(dev, B43_NPHY_SAMP_CMD, ~0x0004); @@ -1009,7 +1010,7 @@ static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev) b43_nphy_set_rf_sequence(dev, 5, rfseq_events, rfseq_delays, 3); b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1, - (u16)~B43_NPHY_OVER_DGAIN_CCKDGECV, + ~B43_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF, 0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT); if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) @@ -1116,7 +1117,7 @@ static void b43_nphy_workarounds(struct b43_wldev *dev) b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20); b43_phy_mask(dev, B43_NPHY_PIL_DW1, - (u16)~B43_NPHY_PIL_DW_64QAM); + ~B43_NPHY_PIL_DW_64QAM & 0xFFFF); b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5); b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4); b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00); @@ -2455,7 +2456,8 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev) b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x0600); regs[4] = b43_phy_read(dev, B43_NPHY_BBCFG); - b43_phy_mask(dev, B43_NPHY_BBCFG, (u16)~B43_NPHY_BBCFG_RSTRX); + b43_phy_mask(dev, B43_NPHY_BBCFG, + ~B43_NPHY_BBCFG_RSTRX & 0xFFFF); tmp = b43_ntab_read(dev, B43_NTAB16(8, 3)); regs[5] = tmp; @@ -2930,7 +2932,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, tmp[5] = b43_phy_read(dev, rfctl[1]); b43_phy_maskset(dev, B43_NPHY_RFSEQCA, - (u16)~B43_NPHY_RFSEQCA_RXDIS, + ~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF, ((1 - i) << B43_NPHY_RFSEQCA_RXDIS_SHIFT)); b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN, (1 - i)); @@ -3291,7 +3293,7 @@ static void b43_nphy_chanspec_setup(struct b43_wldev *dev, b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR); b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4); - b43_phy_mask(dev, B43_PHY_B_BBCFG, (u16)~0xC000); + b43_phy_mask(dev, B43_PHY_B_BBCFG, 0x3FFF); b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32); } diff --git a/drivers/net/wireless/b43/wa.c b/drivers/net/wireless/b43/wa.c index 97c79161c20..9a335da65b4 100644 --- a/drivers/net/wireless/b43/wa.c +++ b/drivers/net/wireless/b43/wa.c @@ -382,7 +382,7 @@ static void b43_wa_altagc(struct b43_wldev *dev) b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 3, 25); } - b43_phy_maskset(dev, B43_PHY_CCKSHIFTBITS_WA, (u16)~0xFF00, 0x5700); + b43_phy_maskset(dev, B43_PHY_CCKSHIFTBITS_WA, 0x00FF, 0x5700); b43_phy_maskset(dev, B43_PHY_OFDM(0x1A), ~0x007F, 0x000F); b43_phy_maskset(dev, B43_PHY_OFDM(0x1A), ~0x3F80, 0x2B80); b43_phy_maskset(dev, B43_PHY_ANTWRSETT, 0xF0FF, 0x0300); @@ -400,9 +400,9 @@ static void b43_wa_altagc(struct b43_wldev *dev) b43_phy_maskset(dev, B43_PHY_OFDM(0x89), ~0x00FF, 0x0020); b43_phy_maskset(dev, B43_PHY_OFDM(0x89), ~0x3F00, 0x0200); b43_phy_maskset(dev, B43_PHY_OFDM(0x82), ~0x00FF, 0x002E); - b43_phy_maskset(dev, B43_PHY_OFDM(0x96), (u16)~0xFF00, 0x1A00); + b43_phy_maskset(dev, B43_PHY_OFDM(0x96), 0x00FF, 0x1A00); b43_phy_maskset(dev, B43_PHY_OFDM(0x81), ~0x00FF, 0x0028); - b43_phy_maskset(dev, B43_PHY_OFDM(0x81), (u16)~0xFF00, 0x2C00); + b43_phy_maskset(dev, B43_PHY_OFDM(0x81), 0x00FF, 0x2C00); if (phy->rev == 1) { b43_phy_write(dev, B43_PHY_PEAK_COUNT, 0x092B); b43_phy_maskset(dev, B43_PHY_OFDM(0x1B), ~0x001E, 0x0002); @@ -412,7 +412,7 @@ static void b43_wa_altagc(struct b43_wldev *dev) b43_phy_maskset(dev, B43_PHY_LPFGAINCTL, ~0x000F, 0x0004); if (phy->rev >= 6) { b43_phy_write(dev, B43_PHY_OFDM(0x22), 0x287A); - b43_phy_maskset(dev, B43_PHY_LPFGAINCTL, (u16)~0xF000, 0x3000); + b43_phy_maskset(dev, B43_PHY_LPFGAINCTL, 0x0FFF, 0x3000); } } b43_phy_maskset(dev, B43_PHY_DIVSRCHIDX, 0x8080, 0x7874); diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 56350d57196..5bbff4c5a48 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -174,7 +174,7 @@ that only one external action is invoked at a time. #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2100 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation" -struct pm_qos_request_list *ipw2100_pm_qos_req; +static struct pm_qos_request_list *ipw2100_pm_qos_req; /* Debugging stuff */ #ifdef CONFIG_IPW2100_DEBUG diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h index 4736861bc4f..70f5586d96b 100644 --- a/drivers/net/wireless/ipw2x00/libipw.h +++ b/drivers/net/wireless/ipw2x00/libipw.h @@ -828,7 +828,6 @@ struct libipw_device { int host_strip_iv_icv; int host_open_frag; - int host_build_iv; int ieee802_1x; /* is IEEE 802.1X used */ /* WPA data */ diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c index 55965408ff3..32dee2ce5d3 100644 --- a/drivers/net/wireless/ipw2x00/libipw_module.c +++ b/drivers/net/wireless/ipw2x00/libipw_module.c @@ -62,8 +62,8 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_AUTHOR(DRV_COPYRIGHT); MODULE_LICENSE("GPL"); -struct cfg80211_ops libipw_config_ops = { }; -void *libipw_wiphy_privid = &libipw_wiphy_privid; +static struct cfg80211_ops libipw_config_ops = { }; +static void *libipw_wiphy_privid = &libipw_wiphy_privid; static int libipw_networks_allocate(struct libipw_device *ieee) { diff --git a/drivers/net/wireless/ipw2x00/libipw_tx.c b/drivers/net/wireless/ipw2x00/libipw_tx.c index da8beac7fcf..01c88a71abe 100644 --- a/drivers/net/wireless/ipw2x00/libipw_tx.c +++ b/drivers/net/wireless/ipw2x00/libipw_tx.c @@ -260,7 +260,7 @@ netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev) int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size, rts_required; unsigned long flags; - int encrypt, host_encrypt, host_encrypt_msdu, host_build_iv; + int encrypt, host_encrypt, host_encrypt_msdu; __be16 ether_type; int bytes, fc, hdr_len; struct sk_buff *skb_frag; @@ -301,7 +301,6 @@ netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev) host_encrypt = ieee->host_encrypt && encrypt && crypt; host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt && crypt; - host_build_iv = ieee->host_build_iv && encrypt && crypt; if (!encrypt && ieee->ieee802_1x && ieee->drop_unencrypted && ether_type != htons(ETH_P_PAE)) { @@ -313,7 +312,7 @@ netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev) skb_copy_from_linear_data(skb, dest, ETH_ALEN); skb_copy_from_linear_data_offset(skb, ETH_ALEN, src, ETH_ALEN); - if (host_encrypt || host_build_iv) + if (host_encrypt) fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA | IEEE80211_FCTL_PROTECTED; else @@ -467,7 +466,7 @@ netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev) for (; i < nr_frags; i++) { skb_frag = txb->fragments[i]; - if (host_encrypt || host_build_iv) + if (host_encrypt) skb_reserve(skb_frag, crypt->ops->extra_mpdu_prefix_len); @@ -502,15 +501,6 @@ netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev) * to insert the IV between the header and the payload */ if (host_encrypt) libipw_encrypt_fragment(ieee, skb_frag, hdr_len); - else if (host_build_iv) { - atomic_inc(&crypt->refcnt); - if (crypt->ops->build_iv) - crypt->ops->build_iv(skb_frag, hdr_len, - ieee->sec.keys[ieee->sec.active_key], - ieee->sec.key_sizes[ieee->sec.active_key], - crypt->priv); - atomic_dec(&crypt->refcnt); - } if (ieee->config & (CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS)) diff --git a/drivers/net/wireless/ipw2x00/libipw_wx.c b/drivers/net/wireless/ipw2x00/libipw_wx.c index 3633c6682e4..d7bd6cf00a8 100644 --- a/drivers/net/wireless/ipw2x00/libipw_wx.c +++ b/drivers/net/wireless/ipw2x00/libipw_wx.c @@ -320,7 +320,7 @@ int libipw_wx_set_encode(struct libipw_device *ieee, }; int i, key, key_provided, len; struct lib80211_crypt_data **crypt; - int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv; + int host_crypto = ieee->host_encrypt || ieee->host_decrypt; DECLARE_SSID_BUF(ssid); LIBIPW_DEBUG_WX("SET_ENCODE\n"); @@ -411,10 +411,6 @@ int libipw_wx_set_encode(struct libipw_device *ieee, /* If a new key was provided, set it up */ if (erq->length > 0) { -#ifdef CONFIG_LIBIPW_DEBUG - DECLARE_SSID_BUF(ssid); -#endif - len = erq->length <= 5 ? 5 : 13; memcpy(sec.keys[key], keybuf, erq->length); if (len > erq->length) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index c281d07ec5e..8848333bc3a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -222,6 +222,7 @@ static struct iwl_lib_ops iwl1000_lib = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, .general_stats_read = iwl_ucode_general_stats_read, + .bt_stats_read = iwl_ucode_bt_stats_read, }, .recover_from_tx_stall = iwl_bg_monitor_recover, .check_plcp_health = iwl_good_plcp_health, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 1dd3bc4c107..d6531ad3906 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1605,8 +1605,8 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv) if (!test_bit(STATUS_TEMPERATURE, &priv->status)) vt = sign_extend(R4, 23); else - vt = sign_extend(le32_to_cpu( - priv->_agn.statistics.general.temperature), 23); + vt = sign_extend(le32_to_cpu(priv->_agn.statistics. + general.common.temperature), 23); IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt); @@ -2285,7 +2285,9 @@ static struct iwl_lib_ops iwl4965_lib = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, .general_stats_read = iwl_ucode_general_stats_read, + .bt_stats_read = iwl_ucode_bt_stats_read, }, + .recover_from_tx_stall = iwl_bg_monitor_recover, .check_plcp_health = iwl_good_plcp_health, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 7d89d99ce19..8093ce2804f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -265,7 +265,7 @@ static void iwl5150_temperature(struct iwl_priv *priv) u32 vt = 0; s32 offset = iwl_temp_calib_to_offset(priv); - vt = le32_to_cpu(priv->_agn.statistics.general.temperature); + vt = le32_to_cpu(priv->_agn.statistics.general.common.temperature); vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset; /* now vt hold the temperature in Kelvin */ priv->temperature = KELVIN_TO_CELSIUS(vt); @@ -398,6 +398,7 @@ static struct iwl_lib_ops iwl5000_lib = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, .general_stats_read = iwl_ucode_general_stats_read, + .bt_stats_read = iwl_ucode_bt_stats_read, }, .recover_from_tx_stall = iwl_bg_monitor_recover, .check_plcp_health = iwl_good_plcp_health, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 095521952bb..58270529a0e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -323,6 +323,7 @@ static struct iwl_lib_ops iwl6000_lib = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, .general_stats_read = iwl_ucode_general_stats_read, + .bt_stats_read = iwl_ucode_bt_stats_read, }, .recover_from_tx_stall = iwl_bg_monitor_recover, .check_plcp_health = iwl_good_plcp_health, @@ -500,6 +501,7 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = { .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, .need_dc_calib = true, + .bt_statistics = true, }; struct iwl_cfg iwl6000g2b_2abg_cfg = { @@ -535,6 +537,7 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = { .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, .need_dc_calib = true, + .bt_statistics = true, }; struct iwl_cfg iwl6000g2b_2bgn_cfg = { @@ -572,6 +575,7 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = { .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, .need_dc_calib = true, + .bt_statistics = true, }; struct iwl_cfg iwl6000g2b_2bg_cfg = { @@ -607,6 +611,7 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = { .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, .need_dc_calib = true, + .bt_statistics = true, }; struct iwl_cfg iwl6000g2b_bgn_cfg = { @@ -644,6 +649,7 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = { .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, .need_dc_calib = true, + .bt_statistics = true, }; struct iwl_cfg iwl6000g2b_bg_cfg = { @@ -679,6 +685,7 @@ struct iwl_cfg iwl6000g2b_bg_cfg = { .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, .need_dc_calib = true, + .bt_statistics = true, }; /* diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 90033e8752b..c4c5691032a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -605,8 +605,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv) IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret); } -void iwl_sensitivity_calibration(struct iwl_priv *priv, - struct iwl_notif_statistics *resp) +void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp) { u32 rx_enable_time; u32 fa_cck; @@ -616,8 +615,8 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, u32 norm_fa_ofdm; u32 norm_fa_cck; struct iwl_sensitivity_data *data = NULL; - struct statistics_rx_non_phy *rx_info = &(resp->rx.general); - struct statistics_rx *statistics = &(resp->rx); + struct statistics_rx_non_phy *rx_info; + struct statistics_rx_phy *ofdm, *cck; unsigned long flags; struct statistics_general_data statis; @@ -632,6 +631,16 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, } spin_lock_irqsave(&priv->lock, flags); + if (priv->cfg->bt_statistics) { + rx_info = &(((struct iwl_bt_notif_statistics *)resp)-> + rx.general.common); + ofdm = &(((struct iwl_bt_notif_statistics *)resp)->rx.ofdm); + cck = &(((struct iwl_bt_notif_statistics *)resp)->rx.cck); + } else { + rx_info = &(((struct iwl_notif_statistics *)resp)->rx.general); + ofdm = &(((struct iwl_notif_statistics *)resp)->rx.ofdm); + cck = &(((struct iwl_notif_statistics *)resp)->rx.cck); + } if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { IWL_DEBUG_CALIB(priv, "<< invalid data.\n"); spin_unlock_irqrestore(&priv->lock, flags); @@ -640,23 +649,23 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, /* Extract Statistics: */ rx_enable_time = le32_to_cpu(rx_info->channel_load); - fa_cck = le32_to_cpu(statistics->cck.false_alarm_cnt); - fa_ofdm = le32_to_cpu(statistics->ofdm.false_alarm_cnt); - bad_plcp_cck = le32_to_cpu(statistics->cck.plcp_err); - bad_plcp_ofdm = le32_to_cpu(statistics->ofdm.plcp_err); + fa_cck = le32_to_cpu(cck->false_alarm_cnt); + fa_ofdm = le32_to_cpu(ofdm->false_alarm_cnt); + bad_plcp_cck = le32_to_cpu(cck->plcp_err); + bad_plcp_ofdm = le32_to_cpu(ofdm->plcp_err); statis.beacon_silence_rssi_a = - le32_to_cpu(statistics->general.beacon_silence_rssi_a); + le32_to_cpu(rx_info->beacon_silence_rssi_a); statis.beacon_silence_rssi_b = - le32_to_cpu(statistics->general.beacon_silence_rssi_b); + le32_to_cpu(rx_info->beacon_silence_rssi_b); statis.beacon_silence_rssi_c = - le32_to_cpu(statistics->general.beacon_silence_rssi_c); + le32_to_cpu(rx_info->beacon_silence_rssi_c); statis.beacon_energy_a = - le32_to_cpu(statistics->general.beacon_energy_a); + le32_to_cpu(rx_info->beacon_energy_a); statis.beacon_energy_b = - le32_to_cpu(statistics->general.beacon_energy_b); + le32_to_cpu(rx_info->beacon_energy_b); statis.beacon_energy_c = - le32_to_cpu(statistics->general.beacon_energy_c); + le32_to_cpu(rx_info->beacon_energy_c); spin_unlock_irqrestore(&priv->lock, flags); @@ -728,8 +737,7 @@ static inline u8 find_first_chain(u8 mask) * 1) Which antennas are connected. * 2) Differential rx gain settings to balance the 3 receivers. */ -void iwl_chain_noise_calibration(struct iwl_priv *priv, - struct iwl_notif_statistics *stat_resp) +void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) { struct iwl_chain_noise_data *data = NULL; @@ -753,7 +761,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, u32 active_chains = 0; u8 num_tx_chains; unsigned long flags; - struct statistics_rx_non_phy *rx_info = &(stat_resp->rx.general); + struct statistics_rx_non_phy *rx_info; u8 first_chain; if (priv->disable_chain_noise_cal) @@ -772,6 +780,13 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, } spin_lock_irqsave(&priv->lock, flags); + if (priv->cfg->bt_statistics) { + rx_info = &(((struct iwl_bt_notif_statistics *)stat_resp)-> + rx.general.common); + } else { + rx_info = &(((struct iwl_notif_statistics *)stat_resp)-> + rx.general); + } if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n"); spin_unlock_irqrestore(&priv->lock, flags); @@ -780,8 +795,19 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, rxon_band24 = !!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK); rxon_chnum = le16_to_cpu(priv->staging_rxon.channel); - stat_band24 = !!(stat_resp->flag & STATISTICS_REPLY_FLG_BAND_24G_MSK); - stat_chnum = le32_to_cpu(stat_resp->flag) >> 16; + if (priv->cfg->bt_statistics) { + stat_band24 = !!(((struct iwl_bt_notif_statistics *) + stat_resp)->flag & + STATISTICS_REPLY_FLG_BAND_24G_MSK); + stat_chnum = le32_to_cpu(((struct iwl_bt_notif_statistics *) + stat_resp)->flag) >> 16; + } else { + stat_band24 = !!(((struct iwl_notif_statistics *) + stat_resp)->flag & + STATISTICS_REPLY_FLG_BAND_24G_MSK); + stat_chnum = le32_to_cpu(((struct iwl_notif_statistics *) + stat_resp)->flag) >> 16; + } /* Make sure we accumulate data for just the associated channel * (even if scanning). */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c index 75d6bfcbc60..f052c6d09b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c @@ -31,21 +31,24 @@ static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) { int p = 0; + u32 flag; - p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", - le32_to_cpu(priv->_agn.statistics.flag)); - if (le32_to_cpu(priv->_agn.statistics.flag) & - UCODE_STATISTICS_CLEAR_MSK) + if (priv->cfg->bt_statistics) + flag = le32_to_cpu(priv->_agn.statistics_bt.flag); + else + flag = le32_to_cpu(priv->_agn.statistics.flag); + + p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag); + if (flag & UCODE_STATISTICS_CLEAR_MSK) p += scnprintf(buf + p, bufsz - p, - "\tStatistics have been cleared\n"); + "\tStatistics have been cleared\n"); p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n", - (le32_to_cpu(priv->_agn.statistics.flag) & - UCODE_STATISTICS_FREQUENCY_MSK) - ? "2.4 GHz" : "5.2 GHz"); + (flag & UCODE_STATISTICS_FREQUENCY_MSK) + ? "2.4 GHz" : "5.2 GHz"); p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n", - (le32_to_cpu(priv->_agn.statistics.flag) & - UCODE_STATISTICS_NARROW_BAND_MSK) - ? "enabled" : "disabled"); + (flag & UCODE_STATISTICS_NARROW_BAND_MSK) + ? "enabled" : "disabled"); + return p; } @@ -79,22 +82,43 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, * the last statistics notification from uCode * might not reflect the current uCode activity */ - ofdm = &priv->_agn.statistics.rx.ofdm; - cck = &priv->_agn.statistics.rx.cck; - general = &priv->_agn.statistics.rx.general; - ht = &priv->_agn.statistics.rx.ofdm_ht; - accum_ofdm = &priv->_agn.accum_statistics.rx.ofdm; - accum_cck = &priv->_agn.accum_statistics.rx.cck; - accum_general = &priv->_agn.accum_statistics.rx.general; - accum_ht = &priv->_agn.accum_statistics.rx.ofdm_ht; - delta_ofdm = &priv->_agn.delta_statistics.rx.ofdm; - delta_cck = &priv->_agn.delta_statistics.rx.cck; - delta_general = &priv->_agn.delta_statistics.rx.general; - delta_ht = &priv->_agn.delta_statistics.rx.ofdm_ht; - max_ofdm = &priv->_agn.max_delta.rx.ofdm; - max_cck = &priv->_agn.max_delta.rx.cck; - max_general = &priv->_agn.max_delta.rx.general; - max_ht = &priv->_agn.max_delta.rx.ofdm_ht; + if (priv->cfg->bt_statistics) { + ofdm = &priv->_agn.statistics_bt.rx.ofdm; + cck = &priv->_agn.statistics_bt.rx.cck; + general = &priv->_agn.statistics_bt.rx.general.common; + ht = &priv->_agn.statistics_bt.rx.ofdm_ht; + accum_ofdm = &priv->_agn.accum_statistics_bt.rx.ofdm; + accum_cck = &priv->_agn.accum_statistics_bt.rx.cck; + accum_general = + &priv->_agn.accum_statistics_bt.rx.general.common; + accum_ht = &priv->_agn.accum_statistics_bt.rx.ofdm_ht; + delta_ofdm = &priv->_agn.delta_statistics_bt.rx.ofdm; + delta_cck = &priv->_agn.delta_statistics_bt.rx.cck; + delta_general = + &priv->_agn.delta_statistics_bt.rx.general.common; + delta_ht = &priv->_agn.delta_statistics_bt.rx.ofdm_ht; + max_ofdm = &priv->_agn.max_delta_bt.rx.ofdm; + max_cck = &priv->_agn.max_delta_bt.rx.cck; + max_general = &priv->_agn.max_delta_bt.rx.general.common; + max_ht = &priv->_agn.max_delta_bt.rx.ofdm_ht; + } else { + ofdm = &priv->_agn.statistics.rx.ofdm; + cck = &priv->_agn.statistics.rx.cck; + general = &priv->_agn.statistics.rx.general; + ht = &priv->_agn.statistics.rx.ofdm_ht; + accum_ofdm = &priv->_agn.accum_statistics.rx.ofdm; + accum_cck = &priv->_agn.accum_statistics.rx.cck; + accum_general = &priv->_agn.accum_statistics.rx.general; + accum_ht = &priv->_agn.accum_statistics.rx.ofdm_ht; + delta_ofdm = &priv->_agn.delta_statistics.rx.ofdm; + delta_cck = &priv->_agn.delta_statistics.rx.cck; + delta_general = &priv->_agn.delta_statistics.rx.general; + delta_ht = &priv->_agn.delta_statistics.rx.ofdm_ht; + max_ofdm = &priv->_agn.max_delta.rx.ofdm; + max_cck = &priv->_agn.max_delta.rx.cck; + max_general = &priv->_agn.max_delta.rx.general; + max_ht = &priv->_agn.max_delta.rx.ofdm_ht; + } pos += iwl_statistics_flag(priv, buf, bufsz); pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" @@ -560,10 +584,18 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file, * the last statistics notification from uCode * might not reflect the current uCode activity */ - tx = &priv->_agn.statistics.tx; - accum_tx = &priv->_agn.accum_statistics.tx; - delta_tx = &priv->_agn.delta_statistics.tx; - max_tx = &priv->_agn.max_delta.tx; + if (priv->cfg->bt_statistics) { + tx = &priv->_agn.statistics_bt.tx; + accum_tx = &priv->_agn.accum_statistics_bt.tx; + delta_tx = &priv->_agn.delta_statistics_bt.tx; + max_tx = &priv->_agn.max_delta_bt.tx; + } else { + tx = &priv->_agn.statistics.tx; + accum_tx = &priv->_agn.accum_statistics.tx; + delta_tx = &priv->_agn.delta_statistics.tx; + max_tx = &priv->_agn.max_delta.tx; + } + pos += iwl_statistics_flag(priv, buf, bufsz); pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" "acumulative delta max\n", @@ -759,8 +791,8 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, char *buf; int bufsz = sizeof(struct statistics_general) * 10 + 300; ssize_t ret; - struct statistics_general *general, *accum_general; - struct statistics_general *delta_general, *max_general; + struct statistics_general_common *general, *accum_general; + struct statistics_general_common *delta_general, *max_general; struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; struct statistics_div *div, *accum_div, *delta_div, *max_div; @@ -777,18 +809,34 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, * the last statistics notification from uCode * might not reflect the current uCode activity */ - general = &priv->_agn.statistics.general; - dbg = &priv->_agn.statistics.general.dbg; - div = &priv->_agn.statistics.general.div; - accum_general = &priv->_agn.accum_statistics.general; - delta_general = &priv->_agn.delta_statistics.general; - max_general = &priv->_agn.max_delta.general; - accum_dbg = &priv->_agn.accum_statistics.general.dbg; - delta_dbg = &priv->_agn.delta_statistics.general.dbg; - max_dbg = &priv->_agn.max_delta.general.dbg; - accum_div = &priv->_agn.accum_statistics.general.div; - delta_div = &priv->_agn.delta_statistics.general.div; - max_div = &priv->_agn.max_delta.general.div; + if (priv->cfg->bt_statistics) { + general = &priv->_agn.statistics_bt.general.common; + dbg = &priv->_agn.statistics_bt.general.common.dbg; + div = &priv->_agn.statistics_bt.general.common.div; + accum_general = &priv->_agn.accum_statistics_bt.general.common; + accum_dbg = &priv->_agn.accum_statistics_bt.general.common.dbg; + accum_div = &priv->_agn.accum_statistics_bt.general.common.div; + delta_general = &priv->_agn.delta_statistics_bt.general.common; + max_general = &priv->_agn.max_delta_bt.general.common; + delta_dbg = &priv->_agn.delta_statistics_bt.general.common.dbg; + max_dbg = &priv->_agn.max_delta_bt.general.common.dbg; + delta_div = &priv->_agn.delta_statistics_bt.general.common.div; + max_div = &priv->_agn.max_delta_bt.general.common.div; + } else { + general = &priv->_agn.statistics.general.common; + dbg = &priv->_agn.statistics.general.common.dbg; + div = &priv->_agn.statistics.general.common.div; + accum_general = &priv->_agn.accum_statistics.general.common; + accum_dbg = &priv->_agn.accum_statistics.general.common.dbg; + accum_div = &priv->_agn.accum_statistics.general.common.div; + delta_general = &priv->_agn.delta_statistics.general.common; + max_general = &priv->_agn.max_delta.general.common; + delta_dbg = &priv->_agn.delta_statistics.general.common.dbg; + max_dbg = &priv->_agn.max_delta.general.common.dbg; + delta_div = &priv->_agn.delta_statistics.general.common.div; + max_div = &priv->_agn.max_delta.general.common.div; + } + pos += iwl_statistics_flag(priv, buf, bufsz); pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" "acumulative delta max\n", @@ -813,6 +861,13 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, delta_dbg->burst_count, max_dbg->burst_count); pos += scnprintf(buf + pos, bufsz - pos, " %-30s %10u %10u %10u %10u\n", + "wait_for_silence_timeout_count:", + le32_to_cpu(dbg->wait_for_silence_timeout_cnt), + accum_dbg->wait_for_silence_timeout_cnt, + delta_dbg->wait_for_silence_timeout_cnt, + max_dbg->wait_for_silence_timeout_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + " %-30s %10u %10u %10u %10u\n", "sleep_time:", le32_to_cpu(general->sleep_time), accum_general->sleep_time, @@ -869,3 +924,90 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, kfree(buf); return ret; } + +ssize_t iwl_ucode_bt_stats_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + int pos = 0; + char *buf; + int bufsz = (sizeof(struct statistics_bt_activity) * 24) + 200; + ssize_t ret; + struct statistics_bt_activity *bt, *accum_bt; + + if (!iwl_is_alive(priv)) + return -EAGAIN; + + /* make request to uCode to retrieve statistics information */ + mutex_lock(&priv->mutex); + ret = iwl_send_statistics_request(priv, CMD_SYNC, false); + mutex_unlock(&priv->mutex); + + if (ret) { + IWL_ERR(priv, + "Error sending statistics request: %zd\n", ret); + return -EAGAIN; + } + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) { + IWL_ERR(priv, "Can not allocate Buffer\n"); + return -ENOMEM; + } + + /* + * the statistic information display here is based on + * the last statistics notification from uCode + * might not reflect the current uCode activity + */ + bt = &priv->_agn.statistics_bt.general.activity; + accum_bt = &priv->_agn.accum_statistics_bt.general.activity; + + pos += iwl_statistics_flag(priv, buf, bufsz); + pos += scnprintf(buf + pos, bufsz - pos, "Statistics_BT:\n"); + pos += scnprintf(buf + pos, bufsz - pos, + "\t\t\tcurrent\t\t\taccumulative\n"); + pos += scnprintf(buf + pos, bufsz - pos, + "hi_priority_tx_req_cnt:\t\t%u\t\t\t%u\n", + le32_to_cpu(bt->hi_priority_tx_req_cnt), + accum_bt->hi_priority_tx_req_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + "hi_priority_tx_denied_cnt:\t%u\t\t\t%u\n", + le32_to_cpu(bt->hi_priority_tx_denied_cnt), + accum_bt->hi_priority_tx_denied_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + "lo_priority_tx_req_cnt:\t\t%u\t\t\t%u\n", + le32_to_cpu(bt->lo_priority_tx_req_cnt), + accum_bt->lo_priority_tx_req_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + "lo_priority_rx_denied_cnt:\t%u\t\t\t%u\n", + le32_to_cpu(bt->lo_priority_tx_denied_cnt), + accum_bt->lo_priority_tx_denied_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + "hi_priority_rx_req_cnt:\t\t%u\t\t\t%u\n", + le32_to_cpu(bt->hi_priority_rx_req_cnt), + accum_bt->hi_priority_rx_req_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + "hi_priority_rx_denied_cnt:\t%u\t\t\t%u\n", + le32_to_cpu(bt->hi_priority_rx_denied_cnt), + accum_bt->hi_priority_rx_denied_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + "lo_priority_rx_req_cnt:\t\t%u\t\t\t%u\n", + le32_to_cpu(bt->lo_priority_rx_req_cnt), + accum_bt->lo_priority_rx_req_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + "lo_priority_rx_denied_cnt:\t%u\t\t\t%u\n", + le32_to_cpu(bt->lo_priority_rx_denied_cnt), + accum_bt->lo_priority_rx_denied_cnt); + + pos += scnprintf(buf + pos, bufsz - pos, + "(rx)num_bt_kills:\t\t%u\t\t\t%u\n", + le32_to_cpu(priv->_agn.statistics_bt.rx. + general.num_bt_kills), + priv->_agn.accum_statistics_bt.rx. + general.num_bt_kills); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h index 59b1f25f0d8..bbdce5913ac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h @@ -37,6 +37,8 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); +ssize_t iwl_ucode_bt_stats_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos); #else static ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -53,4 +55,9 @@ static ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user { return 0; } +static ssize_t iwl_ucode_bt_stats_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + return 0; +} #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index f06d1feedf8..a7216dda978 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -164,7 +164,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv, memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD; + cmd.hdr.op_code = priv->_agn.phy_calib_chain_noise_gain_cmd; cmd.hdr.first_group = 0; cmd.hdr.groups_num = 1; cmd.hdr.data_valid = 1; @@ -197,7 +197,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv) data->beacon_count = 0; memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD; + cmd.hdr.op_code = priv->_agn.phy_calib_chain_noise_reset_cmd; cmd.hdr.first_group = 0; cmd.hdr.groups_num = 1; cmd.hdr.data_valid = 1; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 74623e0d535..a1b6d202d57 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -364,7 +364,7 @@ void iwlagn_temperature(struct iwl_priv *priv) { /* store temperature from statistics (in Celsius) */ priv->temperature = - le32_to_cpu(priv->_agn.statistics.general.temperature); + le32_to_cpu(priv->_agn.statistics.general.common.temperature); iwl_tt_handler(priv); } @@ -1234,7 +1234,10 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); spin_lock_irqsave(&priv->lock, flags); - interval = vif ? vif->bss_conf.beacon_int : 0; + if (priv->is_internal_short_scan) + interval = 0; + else + interval = vif->bss_conf.beacon_int; spin_unlock_irqrestore(&priv->lock, flags); scan->suspend_time = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index d54edc326f8..9490eced119 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -67,17 +67,22 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, * exactly when to expect beacons, therefore only when we're associated. */ static void iwl_rx_calc_noise(struct iwl_priv *priv) { - struct statistics_rx_non_phy *rx_info - = &(priv->_agn.statistics.rx.general); + struct statistics_rx_non_phy *rx_info; int num_active_rx = 0; int total_silence = 0; - int bcn_silence_a = + int bcn_silence_a, bcn_silence_b, bcn_silence_c; + int last_rx_noise; + + if (priv->cfg->bt_statistics) + rx_info = &(priv->_agn.statistics_bt.rx.general.common); + else + rx_info = &(priv->_agn.statistics.rx.general); + bcn_silence_a = le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER; - int bcn_silence_b = + bcn_silence_b = le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER; - int bcn_silence_c = + bcn_silence_c = le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER; - int last_rx_noise; if (bcn_silence_a) { total_silence += bcn_silence_a; @@ -112,17 +117,35 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) static void iwl_accumulative_statistics(struct iwl_priv *priv, __le32 *stats) { - int i; + int i, size; __le32 *prev_stats; u32 *accum_stats; u32 *delta, *max_delta; + struct statistics_general_common *general, *accum_general; + struct statistics_tx *tx, *accum_tx; - prev_stats = (__le32 *)&priv->_agn.statistics; - accum_stats = (u32 *)&priv->_agn.accum_statistics; - delta = (u32 *)&priv->_agn.delta_statistics; - max_delta = (u32 *)&priv->_agn.max_delta; - - for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics); + if (priv->cfg->bt_statistics) { + prev_stats = (__le32 *)&priv->_agn.statistics_bt; + accum_stats = (u32 *)&priv->_agn.accum_statistics_bt; + size = sizeof(struct iwl_bt_notif_statistics); + general = &priv->_agn.statistics_bt.general.common; + accum_general = &priv->_agn.accum_statistics_bt.general.common; + tx = &priv->_agn.statistics_bt.tx; + accum_tx = &priv->_agn.accum_statistics_bt.tx; + delta = (u32 *)&priv->_agn.delta_statistics_bt; + max_delta = (u32 *)&priv->_agn.max_delta_bt; + } else { + prev_stats = (__le32 *)&priv->_agn.statistics; + accum_stats = (u32 *)&priv->_agn.accum_statistics; + size = sizeof(struct iwl_notif_statistics); + general = &priv->_agn.statistics.general.common; + accum_general = &priv->_agn.accum_statistics.general.common; + tx = &priv->_agn.statistics.tx; + accum_tx = &priv->_agn.accum_statistics.tx; + delta = (u32 *)&priv->_agn.delta_statistics; + max_delta = (u32 *)&priv->_agn.max_delta; + } + for (i = sizeof(__le32); i < size; i += sizeof(__le32), stats++, prev_stats++, delta++, max_delta++, accum_stats++) { if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) { @@ -135,18 +158,12 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, } /* reset accumulative statistics for "no-counter" type statistics */ - priv->_agn.accum_statistics.general.temperature = - priv->_agn.statistics.general.temperature; - priv->_agn.accum_statistics.general.temperature_m = - priv->_agn.statistics.general.temperature_m; - priv->_agn.accum_statistics.general.ttl_timestamp = - priv->_agn.statistics.general.ttl_timestamp; - priv->_agn.accum_statistics.tx.tx_power.ant_a = - priv->_agn.statistics.tx.tx_power.ant_a; - priv->_agn.accum_statistics.tx.tx_power.ant_b = - priv->_agn.statistics.tx.tx_power.ant_b; - priv->_agn.accum_statistics.tx.tx_power.ant_c = - priv->_agn.statistics.tx.tx_power.ant_c; + accum_general->temperature = general->temperature; + accum_general->temperature_m = general->temperature_m; + accum_general->ttl_timestamp = general->ttl_timestamp; + accum_tx->tx_power.ant_a = tx->tx_power.ant_a; + accum_tx->tx_power.ant_b = tx->tx_power.ant_b; + accum_tx->tx_power.ant_c = tx->tx_power.ant_c; } #endif @@ -185,11 +202,30 @@ bool iwl_good_plcp_health(struct iwl_priv *priv, * by zero. */ if (plcp_msec) { - combined_plcp_delta = - (le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) - - le32_to_cpu(priv->_agn.statistics.rx.ofdm.plcp_err)) + - (le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) - - le32_to_cpu(priv->_agn.statistics.rx.ofdm_ht.plcp_err)); + struct statistics_rx_phy *ofdm; + struct statistics_rx_ht_phy *ofdm_ht; + + if (priv->cfg->bt_statistics) { + ofdm = &pkt->u.stats_bt.rx.ofdm; + ofdm_ht = &pkt->u.stats_bt.rx.ofdm_ht; + combined_plcp_delta = + (le32_to_cpu(ofdm->plcp_err) - + le32_to_cpu(priv->_agn.statistics_bt. + rx.ofdm.plcp_err)) + + (le32_to_cpu(ofdm_ht->plcp_err) - + le32_to_cpu(priv->_agn.statistics_bt. + rx.ofdm_ht.plcp_err)); + } else { + ofdm = &pkt->u.stats.rx.ofdm; + ofdm_ht = &pkt->u.stats.rx.ofdm_ht; + combined_plcp_delta = + (le32_to_cpu(ofdm->plcp_err) - + le32_to_cpu(priv->_agn.statistics. + rx.ofdm.plcp_err)) + + (le32_to_cpu(ofdm_ht->plcp_err) - + le32_to_cpu(priv->_agn.statistics. + rx.ofdm_ht.plcp_err)); + } if ((combined_plcp_delta > 0) && ((combined_plcp_delta * 100) / plcp_msec) > @@ -206,15 +242,14 @@ bool iwl_good_plcp_health(struct iwl_priv *priv, * plcp_msec */ IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, " - "%u, %u, %u, %u, %d, %u mSecs\n", - priv->cfg->plcp_delta_threshold, - le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err), - le32_to_cpu( - priv->_agn.statistics.rx.ofdm.plcp_err), - le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err), - le32_to_cpu( - priv->_agn.statistics.rx.ofdm_ht.plcp_err), - combined_plcp_delta, plcp_msec); + "%u, %u, %u, %u, %d, %u mSecs\n", + priv->cfg->plcp_delta_threshold, + le32_to_cpu(ofdm->plcp_err), + le32_to_cpu(ofdm->plcp_err), + le32_to_cpu(ofdm_ht->plcp_err), + le32_to_cpu(ofdm_ht->plcp_err), + combined_plcp_delta, plcp_msec); + rc = false; } } @@ -227,24 +262,50 @@ void iwl_rx_statistics(struct iwl_priv *priv, int change; struct iwl_rx_packet *pkt = rxb_addr(rxb); + if (priv->cfg->bt_statistics) { + IWL_DEBUG_RX(priv, + "Statistics notification received (%d vs %d).\n", + (int)sizeof(struct iwl_bt_notif_statistics), + le32_to_cpu(pkt->len_n_flags) & + FH_RSCSR_FRAME_SIZE_MSK); - IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", - (int)sizeof(priv->_agn.statistics), - le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); + change = ((priv->_agn.statistics_bt.general.common.temperature != + pkt->u.stats_bt.general.common.temperature) || + ((priv->_agn.statistics_bt.flag & + STATISTICS_REPLY_FLG_HT40_MODE_MSK) != + (pkt->u.stats_bt.flag & + STATISTICS_REPLY_FLG_HT40_MODE_MSK))); +#ifdef CONFIG_IWLWIFI_DEBUGFS + iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats_bt); +#endif - change = ((priv->_agn.statistics.general.temperature != - pkt->u.stats.general.temperature) || - ((priv->_agn.statistics.flag & - STATISTICS_REPLY_FLG_HT40_MODE_MSK) != - (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK))); + } else { + IWL_DEBUG_RX(priv, + "Statistics notification received (%d vs %d).\n", + (int)sizeof(struct iwl_notif_statistics), + le32_to_cpu(pkt->len_n_flags) & + FH_RSCSR_FRAME_SIZE_MSK); + change = ((priv->_agn.statistics.general.common.temperature != + pkt->u.stats.general.common.temperature) || + ((priv->_agn.statistics.flag & + STATISTICS_REPLY_FLG_HT40_MODE_MSK) != + (pkt->u.stats.flag & + STATISTICS_REPLY_FLG_HT40_MODE_MSK))); #ifdef CONFIG_IWLWIFI_DEBUGFS - iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); + iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); #endif + + } + iwl_recover_from_statistics(priv, pkt); - memcpy(&priv->_agn.statistics, &pkt->u.stats, - sizeof(priv->_agn.statistics)); + if (priv->cfg->bt_statistics) + memcpy(&priv->_agn.statistics_bt, &pkt->u.stats_bt, + sizeof(priv->_agn.statistics_bt)); + else + memcpy(&priv->_agn.statistics, &pkt->u.stats, + sizeof(priv->_agn.statistics)); set_bit(STATUS_STATISTICS, &priv->status); @@ -277,6 +338,12 @@ void iwl_reply_statistics(struct iwl_priv *priv, sizeof(struct iwl_notif_statistics)); memset(&priv->_agn.max_delta, 0, sizeof(struct iwl_notif_statistics)); + memset(&priv->_agn.accum_statistics_bt, 0, + sizeof(struct iwl_bt_notif_statistics)); + memset(&priv->_agn.delta_statistics_bt, 0, + sizeof(struct iwl_bt_notif_statistics)); + memset(&priv->_agn.max_delta_bt, 0, + sizeof(struct iwl_bt_notif_statistics)); #endif IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 7391c63fb02..35337b1e7ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -27,6 +27,8 @@ * *****************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> @@ -292,9 +294,7 @@ static u32 iwl_fill_beacon_frame(struct iwl_priv *priv, struct ieee80211_hdr *hdr, int left) { - if (!iwl_is_associated(priv) || !priv->ibss_beacon || - ((priv->iw_mode != NL80211_IFTYPE_ADHOC) && - (priv->iw_mode != NL80211_IFTYPE_AP))) + if (!priv->ibss_beacon) return 0; if (priv->ibss_beacon->len > left) @@ -1692,6 +1692,7 @@ static void iwl_nic_start(struct iwl_priv *priv) struct iwlagn_ucode_capabilities { u32 max_probe_length; + u32 standard_phy_calibration_size; }; static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); @@ -1827,7 +1828,6 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, u32 tlv_len; enum iwl_ucode_tlv_type tlv_type; const u8 *tlv_data; - int ret = 0; if (len < sizeof(*ucode)) { IWL_ERR(priv, "uCode has invalid length: %zd\n", len); @@ -1863,9 +1863,8 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, len -= sizeof(*ucode); - while (len >= sizeof(*tlv) && !ret) { + while (len >= sizeof(*tlv)) { u16 tlv_alt; - u32 fixed_tlv_size = 4; len -= sizeof(*tlv); tlv = (void *)data; @@ -1913,59 +1912,57 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, pieces->boot_size = tlv_len; break; case IWL_UCODE_TLV_PROBE_MAX_LEN: - if (tlv_len != fixed_tlv_size) - ret = -EINVAL; - else - capa->max_probe_length = + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + capa->max_probe_length = le32_to_cpup((__le32 *)tlv_data); break; case IWL_UCODE_TLV_INIT_EVTLOG_PTR: - if (tlv_len != fixed_tlv_size) - ret = -EINVAL; - else - pieces->init_evtlog_ptr = + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->init_evtlog_ptr = le32_to_cpup((__le32 *)tlv_data); break; case IWL_UCODE_TLV_INIT_EVTLOG_SIZE: - if (tlv_len != fixed_tlv_size) - ret = -EINVAL; - else - pieces->init_evtlog_size = + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->init_evtlog_size = le32_to_cpup((__le32 *)tlv_data); break; case IWL_UCODE_TLV_INIT_ERRLOG_PTR: - if (tlv_len != fixed_tlv_size) - ret = -EINVAL; - else - pieces->init_errlog_ptr = + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->init_errlog_ptr = le32_to_cpup((__le32 *)tlv_data); break; case IWL_UCODE_TLV_RUNT_EVTLOG_PTR: - if (tlv_len != fixed_tlv_size) - ret = -EINVAL; - else - pieces->inst_evtlog_ptr = + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->inst_evtlog_ptr = le32_to_cpup((__le32 *)tlv_data); break; case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE: - if (tlv_len != fixed_tlv_size) - ret = -EINVAL; - else - pieces->inst_evtlog_size = + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->inst_evtlog_size = le32_to_cpup((__le32 *)tlv_data); break; case IWL_UCODE_TLV_RUNT_ERRLOG_PTR: - if (tlv_len != fixed_tlv_size) - ret = -EINVAL; - else - pieces->inst_errlog_ptr = + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->inst_errlog_ptr = le32_to_cpup((__le32 *)tlv_data); break; case IWL_UCODE_TLV_ENHANCE_SENS_TBL: if (tlv_len) - ret = -EINVAL; - else - priv->enhance_sensitivity_table = true; + goto invalid_tlv_len; + priv->enhance_sensitivity_table = true; + break; + case IWL_UCODE_TLV_PHY_CALIBRATION_SIZE: + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + capa->standard_phy_calibration_size = + le32_to_cpup((__le32 *)tlv_data); break; default: IWL_WARN(priv, "unknown TLV: %d\n", tlv_type); @@ -1976,14 +1973,16 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, if (len) { IWL_ERR(priv, "invalid TLV after parsing: %zd\n", len); iwl_print_hex_dump(priv, IWL_DL_FW, (u8 *)data, len); - ret = -EINVAL; - } else if (ret) { - IWL_ERR(priv, "TLV %d has invalid size: %u\n", - tlv_type, tlv_len); - iwl_print_hex_dump(priv, IWL_DL_FW, (u8 *)tlv_data, tlv_len); + return -EINVAL; } - return ret; + return 0; + + invalid_tlv_len: + IWL_ERR(priv, "TLV %d has invalid size: %u\n", tlv_type, tlv_len); + iwl_print_hex_dump(priv, IWL_DL_FW, tlv_data, tlv_len); + + return -EINVAL; } /** @@ -2005,6 +2004,8 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) u32 build; struct iwlagn_ucode_capabilities ucode_capa = { .max_probe_length = 200, + .standard_phy_calibration_size = + IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE, }; memset(&pieces, 0, sizeof(pieces)); @@ -2226,6 +2227,20 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) pieces.boot_size); memcpy(priv->ucode_boot.v_addr, pieces.boot, pieces.boot_size); + /* + * figure out the offset of chain noise reset and gain commands + * base on the size of standard phy calibration commands table size + */ + if (ucode_capa.standard_phy_calibration_size > + IWL_MAX_PHY_CALIBRATE_TBL_SIZE) + ucode_capa.standard_phy_calibration_size = + IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE; + + priv->_agn.phy_calib_chain_noise_reset_cmd = + ucode_capa.standard_phy_calibration_size; + priv->_agn.phy_calib_chain_noise_gain_cmd = + ucode_capa.standard_phy_calibration_size + 1; + /************************************************** * This is still part of probe() in a sense... * @@ -3008,9 +3023,17 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) } if (priv->start_calib) { - iwl_chain_noise_calibration(priv, &priv->_agn.statistics); - - iwl_sensitivity_calibration(priv, &priv->_agn.statistics); + if (priv->cfg->bt_statistics) { + iwl_chain_noise_calibration(priv, + (void *)&priv->_agn.statistics_bt); + iwl_sensitivity_calibration(priv, + (void *)&priv->_agn.statistics_bt); + } else { + iwl_chain_noise_calibration(priv, + (void *)&priv->_agn.statistics); + iwl_sensitivity_calibration(priv, + (void *)&priv->_agn.statistics); + } } mutex_unlock(&priv->mutex); @@ -3909,8 +3932,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct ieee80211_hw *hw; struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); unsigned long flags; - u16 pci_cmd; - u8 perm_addr[ETH_ALEN]; + u16 pci_cmd, num_mac; /************************ * 1. Allocating HW data @@ -4028,9 +4050,17 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_free_eeprom; /* extract MAC Address */ - iwl_eeprom_get_mac(priv, perm_addr); - IWL_DEBUG_INFO(priv, "MAC address: %pM\n", perm_addr); - SET_IEEE80211_PERM_ADDR(priv->hw, perm_addr); + iwl_eeprom_get_mac(priv, priv->addresses[0].addr); + IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr); + priv->hw->wiphy->addresses = priv->addresses; + priv->hw->wiphy->n_addresses = 1; + num_mac = iwl_eeprom_query16(priv, EEPROM_NUM_MAC_ADDRESS); + if (num_mac > 1) { + memcpy(priv->addresses[1].addr, priv->addresses[0].addr, + ETH_ALEN); + priv->addresses[1].addr[5]++; + priv->hw->wiphy->n_addresses++; + } /************************ * 5. Setup HW constants @@ -4389,19 +4419,18 @@ static int __init iwl_init(void) { int ret; - printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); - printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); + pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n"); + pr_info(DRV_COPYRIGHT "\n"); ret = iwlagn_rate_control_register(); if (ret) { - printk(KERN_ERR DRV_NAME - "Unable to register rate control algorithm: %d\n", ret); + pr_err("Unable to register rate control algorithm: %d\n", ret); return ret; } ret = pci_register_driver(&iwl_driver); if (ret) { - printk(KERN_ERR DRV_NAME "Unable to initialize PCI module\n"); + pr_err("Unable to initialize PCI module\n"); goto error_register; } diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.h b/drivers/net/wireless/iwlwifi/iwl-calib.h index 2b7b1df83ba..ba9523fbb30 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.h +++ b/drivers/net/wireless/iwlwifi/iwl-calib.h @@ -66,10 +66,8 @@ #include "iwl-core.h" #include "iwl-commands.h" -void iwl_chain_noise_calibration(struct iwl_priv *priv, - struct iwl_notif_statistics *stat_resp); -void iwl_sensitivity_calibration(struct iwl_priv *priv, - struct iwl_notif_statistics *resp); +void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp); +void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp); void iwl_init_sensitivity(struct iwl_priv *priv); void iwl_reset_run_time_calib(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 8d2db9d2204..60725a5c1b6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -964,8 +964,8 @@ struct iwl_qosparam_cmd { #define IWL_STATION_COUNT 32 /* MAX(3945,4965)*/ #define IWL_INVALID_STATION 255 -#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2); -#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8); +#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2) +#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8) #define STA_FLG_RTS_MIMO_PROT_MSK cpu_to_le32(1 << 17) #define STA_FLG_AGG_MPDU_8US_MSK cpu_to_le32(1 << 18) #define STA_FLG_MAX_AGG_SIZE_POS (19) @@ -1245,7 +1245,7 @@ struct iwl_txfifo_flush_cmd { __le32 fifo_control; __le16 flush_control; __le16 reserved; -} __attribute__ ((packed)); +} __packed; /* * REPLY_WEP_KEY = 0x20 @@ -3035,7 +3035,8 @@ struct iwl39_statistics_tx { struct statistics_dbg { __le32 burst_check; __le32 burst_count; - __le32 reserved[4]; + __le32 wait_for_silence_timeout_cnt; + __le32 reserved[3]; } __packed; struct iwl39_statistics_div { @@ -3126,6 +3127,13 @@ struct statistics_rx_non_phy { __le32 beacon_energy_c; } __packed; +struct statistics_rx_non_phy_bt { + struct statistics_rx_non_phy common; + /* additional stats for bt */ + __le32 num_bt_kills; + __le32 reserved[2]; +} __packed; + struct statistics_rx { struct statistics_rx_phy ofdm; struct statistics_rx_phy cck; @@ -3133,6 +3141,13 @@ struct statistics_rx { struct statistics_rx_ht_phy ofdm_ht; } __packed; +struct statistics_rx_bt { + struct statistics_rx_phy ofdm; + struct statistics_rx_phy cck; + struct statistics_rx_non_phy_bt general; + struct statistics_rx_ht_phy ofdm_ht; +} __packed; + /** * struct statistics_tx_power - current tx power * @@ -3195,7 +3210,7 @@ struct statistics_div { __le32 reserved2; } __packed; -struct statistics_general { +struct statistics_general_common { __le32 temperature; /* radio temperature */ __le32 temperature_m; /* for 5000 and up, this is radio voltage */ struct statistics_dbg dbg; @@ -3211,6 +3226,30 @@ struct statistics_general { * in order to get out of bad PHY status */ __le32 num_of_sos_states; +} __packed; + +struct statistics_bt_activity { + /* Tx statistics */ + __le32 hi_priority_tx_req_cnt; + __le32 hi_priority_tx_denied_cnt; + __le32 lo_priority_tx_req_cnt; + __le32 lo_priority_tx_denied_cnt; + /* Rx statistics */ + __le32 hi_priority_rx_req_cnt; + __le32 hi_priority_rx_denied_cnt; + __le32 lo_priority_rx_req_cnt; + __le32 lo_priority_rx_denied_cnt; +} __packed; + +struct statistics_general { + struct statistics_general_common common; + __le32 reserved2; + __le32 reserved3; +} __packed; + +struct statistics_general_bt { + struct statistics_general_common common; + struct statistics_bt_activity activity; __le32 reserved2; __le32 reserved3; } __packed; @@ -3272,6 +3311,12 @@ struct iwl_notif_statistics { struct statistics_general general; } __packed; +struct iwl_bt_notif_statistics { + __le32 flag; + struct statistics_rx_bt rx; + struct statistics_tx tx; + struct statistics_general_bt general; +} __packed; /* * MISSED_BEACONS_NOTIFICATION = 0xa2 (notification only, not a command) @@ -3547,7 +3592,7 @@ struct iwl_sensitivity_cmd { struct iwl_enhance_sensitivity_cmd { __le16 control; /* always use "1" */ __le16 enhance_table[ENHANCE_HD_TABLE_SIZE]; /* use HD_* as index */ -} __attribute__ ((packed)); +} __packed; /** @@ -3615,10 +3660,10 @@ enum { IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15, IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16, IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17, - IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD = 18, - IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD = 19, + IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE = 18, }; +#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE (253) #define IWL_CALIB_INIT_CFG_ALL cpu_to_le32(0xffffffff) @@ -3943,6 +3988,7 @@ struct iwl_rx_packet { struct iwl_sleep_notification sleep_notif; struct iwl_spectrum_resp spectrum; struct iwl_notif_statistics stats; + struct iwl_bt_notif_statistics stats_bt; struct iwl_compressed_ba_resp compressed_ba; struct iwl_missed_beacon_notif missed_beacon; struct iwl_coex_medium_notification coex_medium_notif; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index f73eb08a949..8024d44ce4b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -170,7 +170,7 @@ struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, struct ieee80211_hw *hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), hw_ops); if (hw == NULL) { - printk(KERN_ERR "%s: Can not allocate network device\n", + pr_err("%s: Can not allocate network device\n", cfg->name); goto out; } @@ -1748,6 +1748,37 @@ static inline void iwl_set_no_assoc(struct iwl_priv *priv) iwlcore_commit_rxon(priv); } +static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct iwl_priv *priv = hw->priv; + unsigned long flags; + __le64 timestamp; + + IWL_DEBUG_MAC80211(priv, "enter\n"); + + if (!iwl_is_ready_rf(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); + return -EIO; + } + + spin_lock_irqsave(&priv->lock, flags); + + if (priv->ibss_beacon) + dev_kfree_skb(priv->ibss_beacon); + + priv->ibss_beacon = skb; + + timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; + priv->timestamp = le64_to_cpu(timestamp); + + IWL_DEBUG_MAC80211(priv, "leave\n"); + spin_unlock_irqrestore(&priv->lock, flags); + + priv->cfg->ops->lib->post_associate(priv, priv->vif); + + return 0; +} + void iwl_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, @@ -1763,6 +1794,15 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); + if (changes & BSS_CHANGED_QOS) { + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + priv->qos_data.qos_active = bss_conf->qos; + iwl_update_qos(priv); + spin_unlock_irqrestore(&priv->lock, flags); + } + if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) { dev_kfree_skb(priv->ibss_beacon); priv->ibss_beacon = ieee80211_beacon_get(hw, vif); @@ -1905,38 +1945,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, } EXPORT_SYMBOL(iwl_bss_info_changed); -int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - __le64 timestamp; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); - return -EIO; - } - - spin_lock_irqsave(&priv->lock, flags); - - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - - priv->ibss_beacon = skb; - - timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; - priv->timestamp = le64_to_cpu(timestamp); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - spin_unlock_irqrestore(&priv->lock, flags); - - priv->cfg->ops->lib->post_associate(priv, priv->vif); - - return 0; -} -EXPORT_SYMBOL(iwl_mac_beacon_update); - static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif) { iwl_connection_init_rx_config(priv, vif); @@ -2134,15 +2142,6 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) iwl_set_tx_power(priv, conf->power_level, false); } - if (changed & IEEE80211_CONF_CHANGE_QOS) { - bool qos_active = !!(conf->flags & IEEE80211_CONF_QOS); - - spin_lock_irqsave(&priv->lock, flags); - priv->qos_data.qos_active = qos_active; - iwl_update_qos(priv); - spin_unlock_irqrestore(&priv->lock, flags); - } - if (!iwl_is_ready(priv)) { IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); goto out; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index fcbba3d604d..e9d23f2f869 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -125,6 +125,8 @@ struct iwl_debugfs_ops { size_t count, loff_t *ppos); ssize_t (*general_stats_read)(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); + ssize_t (*bt_stats_read)(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos); }; struct iwl_temp_ops { @@ -335,6 +337,7 @@ struct iwl_cfg { u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; const bool need_dc_calib; + const bool bt_statistics; }; /*************************** @@ -377,7 +380,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, u32 changes); -int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); int iwl_commit_rxon(struct iwl_priv *priv); int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 088a2c13f59..e96a1bb1278 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1267,7 +1267,7 @@ static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; int pos = 0; char buf[128]; const size_t bufsz = sizeof(buf); @@ -1317,7 +1317,7 @@ static ssize_t iwl_dbgfs_rxon_flags_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; int len = 0; char buf[20]; @@ -1329,7 +1329,7 @@ static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; int len = 0; char buf[20]; @@ -1342,7 +1342,7 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; char *buf; int pos = 0; ssize_t ret = -EFAULT; @@ -1404,7 +1404,7 @@ static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; int pos = 0; char buf[12]; const size_t bufsz = sizeof(buf); @@ -1519,6 +1519,16 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file, return count; } +static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + + return priv->cfg->ops->lib->debugfs_ops.bt_stats_read(file, + user_buf, count, ppos); +} + DEBUGFS_READ_FILE_OPS(rx_statistics); DEBUGFS_READ_FILE_OPS(tx_statistics); DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); @@ -1541,6 +1551,7 @@ DEBUGFS_READ_WRITE_FILE_OPS(force_reset); DEBUGFS_READ_FILE_OPS(rxon_flags); DEBUGFS_READ_FILE_OPS(rxon_filter_flags); DEBUGFS_WRITE_FILE_OPS(txfifo_flush); +DEBUGFS_READ_FILE_OPS(ucode_bt_stats); /* * Create the debugfs files and directories @@ -1608,6 +1619,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); if (priv->cfg->ucode_tracing) DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); + if (priv->cfg->bt_statistics) + DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); if (priv->cfg->sensitivity_calib_by_driver) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index c4dba62b74a..f35bcad56e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -571,6 +571,7 @@ enum iwl_ucode_tlv_type { IWL_UCODE_TLV_INIT_EVTLOG_SIZE = 12, IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13, IWL_UCODE_TLV_ENHANCE_SENS_TBL = 14, + IWL_UCODE_TLV_PHY_CALIBRATION_SIZE = 15, }; struct iwl_ucode_tlv { @@ -1153,6 +1154,9 @@ struct iwl_priv { u32 hw_wa_rev; u8 rev_id; + /* EEPROM MAC addresses */ + struct mac_address addresses[2]; + /* uCode images, save to reload in case of failure */ int fw_index; /* firmware we're trying to load */ u32 ucode_ver; /* version of ucode, copy of @@ -1321,11 +1325,23 @@ struct iwl_priv { u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; + /* + * chain noise reset and gain commands are the + * two extra calibration commands follows the standard + * phy calibration commands + */ + u8 phy_calib_chain_noise_reset_cmd; + u8 phy_calib_chain_noise_gain_cmd; + struct iwl_notif_statistics statistics; + struct iwl_bt_notif_statistics statistics_bt; #ifdef CONFIG_IWLWIFI_DEBUGFS struct iwl_notif_statistics accum_statistics; struct iwl_notif_statistics delta_statistics; struct iwl_notif_statistics max_delta; + struct iwl_bt_notif_statistics accum_statistics_bt; + struct iwl_bt_notif_statistics delta_statistics_bt; + struct iwl_bt_notif_statistics max_delta_bt; #endif } _agn; #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 3452dfa7b57..a4772aff51f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -402,6 +402,7 @@ struct iwl_eeprom_calib_info { #define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */ #define EEPROM_RADIO_CONFIG (2*0x48) /* 2 bytes */ #define EEPROM_3945_M_VERSION (2*0x4A) /* 1 bytes */ +#define EEPROM_NUM_MAC_ADDRESS (2*0x4C) /* 2 bytes */ /* The following masks are to be applied on EEPROM_RADIO_CONFIG */ #define EEPROM_RF_CFG_TYPE_MSK(x) (x & 0x3) /* bits 0-1 */ diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 2a7c399fee1..b0c6b047390 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -429,11 +429,10 @@ void iwl_bg_scan_check(struct work_struct *data) return; mutex_lock(&priv->mutex); - if (test_bit(STATUS_SCANNING, &priv->status) || - test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_SCAN(priv, "Scan completion watchdog resetting " - "adapter (%dms)\n", - jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG)); + if (test_bit(STATUS_SCANNING, &priv->status) && + !test_bit(STATUS_SCAN_ABORTING, &priv->status)) { + IWL_DEBUG_SCAN(priv, "Scan completion watchdog (%dms)\n", + jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG)); if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) iwl_send_scan_abort(priv); @@ -498,12 +497,11 @@ void iwl_bg_abort_scan(struct work_struct *work) !test_bit(STATUS_GEO_CONFIGURED, &priv->status)) return; - mutex_lock(&priv->mutex); - - cancel_delayed_work_sync(&priv->scan_check); - set_bit(STATUS_SCAN_ABORTING, &priv->status); - iwl_send_scan_abort(priv); + cancel_delayed_work(&priv->scan_check); + mutex_lock(&priv->mutex); + if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) + iwl_send_scan_abort(priv); mutex_unlock(&priv->mutex); } EXPORT_SYMBOL(iwl_bg_abort_scan); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 8eb34710690..d24eb47d370 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -27,6 +27,8 @@ * *****************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> @@ -311,9 +313,7 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, int left) { - if (!iwl_is_associated(priv) || !priv->ibss_beacon || - ((priv->iw_mode != NL80211_IFTYPE_ADHOC) && - (priv->iw_mode != NL80211_IFTYPE_AP))) + if (!iwl_is_associated(priv) || !priv->ibss_beacon) return 0; if (priv->ibss_beacon->len > left) @@ -2883,7 +2883,10 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); spin_lock_irqsave(&priv->lock, flags); - interval = vif ? vif->bss_conf.beacon_int : 0; + if (priv->is_internal_short_scan) + interval = 0; + else + interval = vif->bss_conf.beacon_int; spin_unlock_irqrestore(&priv->lock, flags); scan->suspend_time = 0; @@ -3932,7 +3935,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e * space for this driver's private structure */ hw = iwl_alloc_all(cfg, &iwl3945_hw_ops); if (hw == NULL) { - printk(KERN_ERR DRV_NAME "Can not allocate network device\n"); + pr_err("Can not allocate network device\n"); err = -ENOMEM; goto out; } @@ -4224,19 +4227,18 @@ static int __init iwl3945_init(void) { int ret; - printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); - printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); + pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n"); + pr_info(DRV_COPYRIGHT "\n"); ret = iwl3945_rate_control_register(); if (ret) { - printk(KERN_ERR DRV_NAME - "Unable to register rate control algorithm: %d\n", ret); + pr_err("Unable to register rate control algorithm: %d\n", ret); return ret; } ret = pci_register_driver(&iwl3945_driver); if (ret) { - printk(KERN_ERR DRV_NAME "Unable to initialize PCI module\n"); + pr_err("Unable to initialize PCI module\n"); goto error_register; } diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index f36cc970ad1..25f90276098 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -7,7 +7,6 @@ */ #include <linux/slab.h> -#include <linux/if_arp.h> #include <linux/ieee80211.h> #include <net/cfg80211.h> #include <asm/unaligned.h> @@ -891,7 +890,7 @@ struct cmd_key_material { __le16 action; struct MrvlIEtype_keyParamSet param; -} __attribute__ ((packed)); +} __packed; static int lbs_set_key_material(struct lbs_private *priv, int key_type, @@ -1383,93 +1382,10 @@ static int lbs_cfg_del_key(struct wiphy *wiphy, struct net_device *netdev, } - -/*************************************************************************** - * Monitor mode - */ - -/* like "struct cmd_ds_802_11_monitor_mode", but with cmd_header. Once we - * get rid of WEXT, this should go into host.h */ -struct cmd_monitor_mode { - struct cmd_header hdr; - - __le16 action; - __le16 mode; -} __attribute__ ((packed)); - -static int lbs_enable_monitor_mode(struct lbs_private *priv, int mode) -{ - struct cmd_monitor_mode cmd; - int ret; - - lbs_deb_enter(LBS_DEB_CFG80211); - - /* - * cmd 98 00 - * size 0c 00 - * sequence xx xx - * result 00 00 - * action 01 00 ACT_SET - * enable 01 00 - */ - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(CMD_ACT_SET); - cmd.mode = cpu_to_le16(mode); - - ret = lbs_cmd_with_response(priv, CMD_802_11_MONITOR_MODE, &cmd); - - if (ret == 0) - priv->dev->type = ARPHRD_IEEE80211_RADIOTAP; - else - priv->dev->type = ARPHRD_ETHER; - - lbs_deb_leave(LBS_DEB_CFG80211); - return ret; -} - - - - - - /*************************************************************************** * Get station */ -/* - * Returns the signal or 0 in case of an error. - */ - -/* like "struct cmd_ds_802_11_rssi", but with cmd_header. Once we get rid - * of WEXT, this should go into host.h */ -struct cmd_rssi { - struct cmd_header hdr; - - __le16 n_or_snr; - __le16 nf; - __le16 avg_snr; - __le16 avg_nf; -} __attribute__ ((packed)); - -static int lbs_get_signal(struct lbs_private *priv, s8 *signal, s8 *noise) -{ - struct cmd_rssi cmd; - int ret; - - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.n_or_snr = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR); - ret = lbs_cmd_with_response(priv, CMD_802_11_RSSI, &cmd); - - if (ret == 0) { - *signal = CAL_RSSI(le16_to_cpu(cmd.n_or_snr), - le16_to_cpu(cmd.nf)); - *noise = CAL_NF(le16_to_cpu(cmd.nf)); - } - return ret; -} - - static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev, u8 *mac, struct station_info *sinfo) { @@ -1490,7 +1406,7 @@ static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev, sinfo->rx_packets = priv->dev->stats.rx_packets; /* Get current RSSI */ - ret = lbs_get_signal(priv, &signal, &noise); + ret = lbs_get_rssi(priv, &signal, &noise); if (ret == 0) { sinfo->signal = signal; sinfo->filled |= STATION_INFO_SIGNAL; @@ -1530,7 +1446,7 @@ static int lbs_get_survey(struct wiphy *wiphy, struct net_device *dev, survey->channel = ieee80211_get_channel(wiphy, ieee80211_channel_to_frequency(priv->channel)); - ret = lbs_get_signal(priv, &signal, &noise); + ret = lbs_get_rssi(priv, &signal, &noise); if (ret == 0) { survey->filled = SURVEY_INFO_NOISE_DBM; survey->noise = noise; @@ -1558,17 +1474,17 @@ static int lbs_change_intf(struct wiphy *wiphy, struct net_device *dev, switch (type) { case NL80211_IFTYPE_MONITOR: - ret = lbs_enable_monitor_mode(priv, 1); + ret = lbs_set_monitor_mode(priv, 1); break; case NL80211_IFTYPE_STATION: if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) - ret = lbs_enable_monitor_mode(priv, 0); + ret = lbs_set_monitor_mode(priv, 0); if (!ret) ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 1); break; case NL80211_IFTYPE_ADHOC: if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) - ret = lbs_enable_monitor_mode(priv, 0); + ret = lbs_set_monitor_mode(priv, 0); if (!ret) ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 2); break; @@ -2063,113 +1979,20 @@ int lbs_cfg_register(struct lbs_private *priv) return ret; } -/** - * @brief This function sets DOMAIN INFO to FW - * @param priv pointer to struct lbs_private - * @return 0; -1 -*/ -static int lbs_11d_set_domain_info(struct lbs_private *priv) -{ - int ret; - - ret = lbs_prepare_and_send_command(priv, CMD_802_11D_DOMAIN_INFO, - CMD_ACT_SET, - CMD_OPTION_WAITFORRSP, 0, NULL); - if (ret) - lbs_deb_11d("fail to dnld domain info\n"); - - return ret; -} - -static void lbs_send_domain_info_cmd_fw(struct wiphy *wiphy, - struct regulatory_request *request) -{ - u8 no_of_triplet = 0; - u8 no_of_parsed_chan = 0; - u8 first_channel = 0, next_chan = 0, max_pwr = 0; - u8 i, flag = 0; - enum ieee80211_band band; - struct ieee80211_supported_band *sband; - struct ieee80211_channel *ch; - struct lbs_private *priv = wiphy_priv(wiphy); - struct lbs_802_11d_domain_reg *domain_info = &priv->domain_reg; - int ret = 0; - - lbs_deb_enter(LBS_DEB_CFG80211); - - /* Set country code */ - domain_info->country_code[0] = request->alpha2[0]; - domain_info->country_code[1] = request->alpha2[1]; - domain_info->country_code[2] = ' '; - - for (band = 0; band < IEEE80211_NUM_BANDS ; band++) { - - if (!wiphy->bands[band]) - continue; - - sband = wiphy->bands[band]; - - for (i = 0; i < sband->n_channels ; i++) { - ch = &sband->channels[i]; - if (ch->flags & IEEE80211_CHAN_DISABLED) - continue; - - if (!flag) { - flag = 1; - next_chan = first_channel = (u32) ch->hw_value; - max_pwr = ch->max_power; - no_of_parsed_chan = 1; - continue; - } - - if (ch->hw_value == next_chan + 1 && - ch->max_power == max_pwr) { - next_chan++; - no_of_parsed_chan++; - } else { - domain_info->triplet[no_of_triplet] - .chans.first_channel = first_channel; - domain_info->triplet[no_of_triplet] - .chans.num_channels = no_of_parsed_chan; - domain_info->triplet[no_of_triplet] - .chans.max_power = max_pwr; - no_of_triplet++; - flag = 0; - } - } - if (flag) { - domain_info->triplet[no_of_triplet] - .chans.first_channel = first_channel; - domain_info->triplet[no_of_triplet] - .chans.num_channels = no_of_parsed_chan; - domain_info->triplet[no_of_triplet] - .chans.max_power = max_pwr; - no_of_triplet++; - } - } - - domain_info->no_triplet = no_of_triplet; - - /* Set domain info */ - ret = lbs_11d_set_domain_info(priv); - if (ret) - lbs_pr_err("11D: error setting domain info in FW\n"); - - lbs_deb_leave(LBS_DEB_CFG80211); -} - int lbs_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) { + struct lbs_private *priv = wiphy_priv(wiphy); + int ret; + lbs_deb_enter_args(LBS_DEB_CFG80211, "cfg80211 regulatory domain " "callback for domain %c%c\n", request->alpha2[0], request->alpha2[1]); - lbs_send_domain_info_cmd_fw(wiphy, request); + ret = lbs_set_11d_domain_info(priv, request, wiphy->bands); lbs_deb_leave(LBS_DEB_CFG80211); - - return 0; + return ret; } void lbs_scan_deinit(struct lbs_private *priv) diff --git a/drivers/net/wireless/libertas/cfg.h b/drivers/net/wireless/libertas/cfg.h index 756fb98f9f0..4f46bb744be 100644 --- a/drivers/net/wireless/libertas/cfg.h +++ b/drivers/net/wireless/libertas/cfg.h @@ -13,12 +13,6 @@ void lbs_cfg_free(struct lbs_private *priv); int lbs_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request); -/* All of those are TODOs: */ -#define lbs_cmd_802_11_rssi(priv, cmdptr) (0) -#define lbs_ret_802_11_rssi(priv, resp) (0) -#define lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action) (0) -#define lbs_ret_802_11_bcn_ctrl(priv, resp) (0) - void lbs_send_disconnect_notification(struct lbs_private *priv); void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event); diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 749fbde4fd5..70745928f3f 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -6,13 +6,14 @@ #include <linux/kfifo.h> #include <linux/sched.h> #include <linux/slab.h> +#include <linux/if_arp.h> #include "decl.h" #include "cfg.h" #include "cmd.h" - -static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv); +#define CAL_NF(nf) ((s32)(-(s32)(nf))) +#define CAL_RSSI(snr, nf) ((s32)((s32)(snr) + CAL_NF(nf))) /** * @brief Simple callback that copies response back into command @@ -74,30 +75,6 @@ static u8 is_command_allowed_in_ps(u16 cmd) } /** - * @brief This function checks if the command is allowed. - * - * @param priv A pointer to lbs_private structure - * @return allowed or not allowed. - */ - -static int lbs_is_cmd_allowed(struct lbs_private *priv) -{ - int ret = 1; - - lbs_deb_enter(LBS_DEB_CMD); - - if (!priv->is_auto_deep_sleep_enabled) { - if (priv->is_deep_sleep) { - lbs_deb_cmd("command not allowed in deep sleep\n"); - ret = 0; - } - } - - lbs_deb_leave(LBS_DEB_CMD); - return ret; -} - -/** * @brief Updates the hardware details like MAC address and regulatory region * * @param priv A pointer to struct lbs_private structure @@ -227,42 +204,49 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, } EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg); -static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd, - u16 cmd_action) +/** + * @brief Sets the Power Save mode + * + * @param priv A pointer to struct lbs_private structure + * @param cmd_action The Power Save operation (PS_MODE_ACTION_ENTER_PS or + * PS_MODE_ACTION_EXIT_PS) + * @param block Whether to block on a response or not + * + * @return 0 on success, error on failure + */ +int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block) { - struct cmd_ds_802_11_ps_mode *psm = &cmd->params.psmode; + struct cmd_ds_802_11_ps_mode cmd; + int ret = 0; lbs_deb_enter(LBS_DEB_CMD); - cmd->command = cpu_to_le16(CMD_802_11_PS_MODE); - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) + - sizeof(struct cmd_header)); - psm->action = cpu_to_le16(cmd_action); - psm->multipledtim = 0; - switch (cmd_action) { - case CMD_SUBCMD_ENTER_PS: - lbs_deb_cmd("PS command:" "SubCode- Enter PS\n"); - - psm->locallisteninterval = 0; - psm->nullpktinterval = 0; - psm->multipledtim = - cpu_to_le16(MRVDRV_DEFAULT_MULTIPLE_DTIM); - break; - - case CMD_SUBCMD_EXIT_PS: - lbs_deb_cmd("PS command:" "SubCode- Exit PS\n"); - break; - - case CMD_SUBCMD_SLEEP_CONFIRMED: - lbs_deb_cmd("PS command: SubCode- sleep confirm\n"); - break; + memset(&cmd, 0, sizeof(cmd)); + cmd.hdr.size = cpu_to_le16(sizeof(cmd)); + cmd.action = cpu_to_le16(cmd_action); - default: - break; + if (cmd_action == PS_MODE_ACTION_ENTER_PS) { + lbs_deb_cmd("PS_MODE: action ENTER_PS\n"); + cmd.multipledtim = cpu_to_le16(1); /* Default DTIM multiple */ + } else if (cmd_action == PS_MODE_ACTION_EXIT_PS) { + lbs_deb_cmd("PS_MODE: action EXIT_PS\n"); + } else { + /* We don't handle CONFIRM_SLEEP here because it needs to + * be fastpathed to the firmware. + */ + lbs_deb_cmd("PS_MODE: unknown action 0x%X\n", cmd_action); + ret = -EOPNOTSUPP; + goto out; } - lbs_deb_leave(LBS_DEB_CMD); - return 0; + if (block) + ret = lbs_cmd_with_response(priv, CMD_802_11_PS_MODE, &cmd); + else + lbs_cmd_async(priv, CMD_802_11_PS_MODE, &cmd.hdr, sizeof (cmd)); + +out: + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); + return ret; } int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, @@ -576,23 +560,35 @@ int lbs_set_tx_power(struct lbs_private *priv, s16 dbm) return ret; } -static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd, - u16 cmd_action, void *pdata_buf) +/** + * @brief Enable or disable monitor mode (only implemented on OLPC usb8388 FW) + * + * @param priv A pointer to struct lbs_private structure + * @param enable 1 to enable monitor mode, 0 to disable + * + * @return 0 on success, error on failure + */ +int lbs_set_monitor_mode(struct lbs_private *priv, int enable) { - struct cmd_ds_802_11_monitor_mode *monitor = &cmd->params.monitor; + struct cmd_ds_802_11_monitor_mode cmd; + int ret; - cmd->command = cpu_to_le16(CMD_802_11_MONITOR_MODE); - cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode) + - sizeof(struct cmd_header)); + memset(&cmd, 0, sizeof(cmd)); + cmd.hdr.size = cpu_to_le16(sizeof(cmd)); + cmd.action = cpu_to_le16(CMD_ACT_SET); + if (enable) + cmd.mode = cpu_to_le16(0x1); + + lbs_deb_cmd("SET_MONITOR_MODE: %d\n", enable); - monitor->action = cpu_to_le16(cmd_action); - if (cmd_action == CMD_ACT_SET) { - monitor->mode = - cpu_to_le16((u16) (*(u32 *) pdata_buf)); + ret = lbs_cmd_with_response(priv, CMD_802_11_MONITOR_MODE, &cmd); + if (ret == 0) { + priv->dev->type = enable ? ARPHRD_IEEE80211_RADIOTAP : + ARPHRD_ETHER; } - return 0; + lbs_deb_leave(LBS_DEB_CMD); + return ret; } /** @@ -677,78 +673,242 @@ out: return ret; } -static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, - u8 cmd_action, void *pdata_buf) +/** + * @brief Get current RSSI and noise floor + * + * @param priv A pointer to struct lbs_private structure + * @param rssi On successful return, signal level in mBm + * + * @return The channel on success, error on failure + */ +int lbs_get_rssi(struct lbs_private *priv, s8 *rssi, s8 *nf) { - struct lbs_offset_value *offval; + struct cmd_ds_802_11_rssi cmd; + int ret = 0; lbs_deb_enter(LBS_DEB_CMD); - offval = (struct lbs_offset_value *)pdata_buf; + BUG_ON(rssi == NULL); + BUG_ON(nf == NULL); - switch (le16_to_cpu(cmdptr->command)) { - case CMD_MAC_REG_ACCESS: - { - struct cmd_ds_mac_reg_access *macreg; + memset(&cmd, 0, sizeof(cmd)); + cmd.hdr.size = cpu_to_le16(sizeof(cmd)); + /* Average SNR over last 8 beacons */ + cmd.n_or_snr = cpu_to_le16(8); - cmdptr->size = - cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access) - + sizeof(struct cmd_header)); - macreg = - (struct cmd_ds_mac_reg_access *)&cmdptr->params. - macreg; + ret = lbs_cmd_with_response(priv, CMD_802_11_RSSI, &cmd); + if (ret == 0) { + *nf = CAL_NF(le16_to_cpu(cmd.nf)); + *rssi = CAL_RSSI(le16_to_cpu(cmd.n_or_snr), le16_to_cpu(cmd.nf)); + } - macreg->action = cpu_to_le16(cmd_action); - macreg->offset = cpu_to_le16((u16) offval->offset); - macreg->value = cpu_to_le32(offval->value); + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); + return ret; +} - break; - } +/** + * @brief Send regulatory and 802.11d domain information to the firmware + * + * @param priv pointer to struct lbs_private + * @param request cfg80211 regulatory request structure + * @param bands the device's supported bands and channels + * + * @return 0 on success, error code on failure +*/ +int lbs_set_11d_domain_info(struct lbs_private *priv, + struct regulatory_request *request, + struct ieee80211_supported_band **bands) +{ + struct cmd_ds_802_11d_domain_info cmd; + struct mrvl_ie_domain_param_set *domain = &cmd.domain; + struct ieee80211_country_ie_triplet *t; + enum ieee80211_band band; + struct ieee80211_channel *ch; + u8 num_triplet = 0; + u8 num_parsed_chan = 0; + u8 first_channel = 0, next_chan = 0, max_pwr = 0; + u8 i, flag = 0; + size_t triplet_size; + int ret; - case CMD_BBP_REG_ACCESS: - { - struct cmd_ds_bbp_reg_access *bbpreg; + lbs_deb_enter(LBS_DEB_11D); - cmdptr->size = - cpu_to_le16(sizeof - (struct cmd_ds_bbp_reg_access) - + sizeof(struct cmd_header)); - bbpreg = - (struct cmd_ds_bbp_reg_access *)&cmdptr->params. - bbpreg; + memset(&cmd, 0, sizeof(cmd)); + cmd.action = cpu_to_le16(CMD_ACT_SET); - bbpreg->action = cpu_to_le16(cmd_action); - bbpreg->offset = cpu_to_le16((u16) offval->offset); - bbpreg->value = (u8) offval->value; + lbs_deb_11d("Setting country code '%c%c'\n", + request->alpha2[0], request->alpha2[1]); - break; + domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN); + + /* Set country code */ + domain->country_code[0] = request->alpha2[0]; + domain->country_code[1] = request->alpha2[1]; + domain->country_code[2] = ' '; + + /* Now set up the channel triplets; firmware is somewhat picky here + * and doesn't validate channel numbers and spans; hence it would + * interpret a triplet of (36, 4, 20) as channels 36, 37, 38, 39. Since + * the last 3 aren't valid channels, the driver is responsible for + * splitting that up into 4 triplet pairs of (36, 1, 20) + (40, 1, 20) + * etc. + */ + for (band = 0; + (band < IEEE80211_NUM_BANDS) && (num_triplet < MAX_11D_TRIPLETS); + band++) { + + if (!bands[band]) + continue; + + for (i = 0; + (i < bands[band]->n_channels) && (num_triplet < MAX_11D_TRIPLETS); + i++) { + ch = &bands[band]->channels[i]; + if (ch->flags & IEEE80211_CHAN_DISABLED) + continue; + + if (!flag) { + flag = 1; + next_chan = first_channel = (u32) ch->hw_value; + max_pwr = ch->max_power; + num_parsed_chan = 1; + continue; + } + + if ((ch->hw_value == next_chan + 1) && + (ch->max_power == max_pwr)) { + /* Consolidate adjacent channels */ + next_chan++; + num_parsed_chan++; + } else { + /* Add this triplet */ + lbs_deb_11d("11D triplet (%d, %d, %d)\n", + first_channel, num_parsed_chan, + max_pwr); + t = &domain->triplet[num_triplet]; + t->chans.first_channel = first_channel; + t->chans.num_channels = num_parsed_chan; + t->chans.max_power = max_pwr; + num_triplet++; + flag = 0; + } } - case CMD_RF_REG_ACCESS: - { - struct cmd_ds_rf_reg_access *rfreg; + if (flag) { + /* Add last triplet */ + lbs_deb_11d("11D triplet (%d, %d, %d)\n", first_channel, + num_parsed_chan, max_pwr); + t = &domain->triplet[num_triplet]; + t->chans.first_channel = first_channel; + t->chans.num_channels = num_parsed_chan; + t->chans.max_power = max_pwr; + num_triplet++; + } + } - cmdptr->size = - cpu_to_le16(sizeof - (struct cmd_ds_rf_reg_access) + - sizeof(struct cmd_header)); - rfreg = - (struct cmd_ds_rf_reg_access *)&cmdptr->params. - rfreg; + lbs_deb_11d("# triplets %d\n", num_triplet); - rfreg->action = cpu_to_le16(cmd_action); - rfreg->offset = cpu_to_le16((u16) offval->offset); - rfreg->value = (u8) offval->value; + /* Set command header sizes */ + triplet_size = num_triplet * sizeof(struct ieee80211_country_ie_triplet); + domain->header.len = cpu_to_le16(sizeof(domain->country_code) + + triplet_size); - break; - } + lbs_deb_hex(LBS_DEB_11D, "802.11D domain param set", + (u8 *) &cmd.domain.country_code, + le16_to_cpu(domain->header.len)); - default: - break; + cmd.hdr.size = cpu_to_le16(sizeof(cmd.hdr) + + sizeof(cmd.action) + + sizeof(cmd.domain.header) + + sizeof(cmd.domain.country_code) + + triplet_size); + + ret = lbs_cmd_with_response(priv, CMD_802_11D_DOMAIN_INFO, &cmd); + + lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret); + return ret; +} + +/** + * @brief Read a MAC, Baseband, or RF register + * + * @param priv pointer to struct lbs_private + * @param cmd register command, one of CMD_MAC_REG_ACCESS, + * CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS + * @param offset byte offset of the register to get + * @param value on success, the value of the register at 'offset' + * + * @return 0 on success, error code on failure +*/ +int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value) +{ + struct cmd_ds_reg_access cmd; + int ret = 0; + + lbs_deb_enter(LBS_DEB_CMD); + + BUG_ON(value == NULL); + + memset(&cmd, 0, sizeof(cmd)); + cmd.hdr.size = cpu_to_le16(sizeof(cmd)); + cmd.action = cpu_to_le16(CMD_ACT_GET); + + if (reg != CMD_MAC_REG_ACCESS && + reg != CMD_BBP_REG_ACCESS && + reg != CMD_RF_REG_ACCESS) { + ret = -EINVAL; + goto out; } - lbs_deb_leave(LBS_DEB_CMD); - return 0; + ret = lbs_cmd_with_response(priv, reg, &cmd); + if (ret) { + if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS) + *value = cmd.value.bbp_rf; + else if (reg == CMD_MAC_REG_ACCESS) + *value = le32_to_cpu(cmd.value.mac); + } + +out: + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); + return ret; +} + +/** + * @brief Write a MAC, Baseband, or RF register + * + * @param priv pointer to struct lbs_private + * @param cmd register command, one of CMD_MAC_REG_ACCESS, + * CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS + * @param offset byte offset of the register to set + * @param value the value to write to the register at 'offset' + * + * @return 0 on success, error code on failure +*/ +int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value) +{ + struct cmd_ds_reg_access cmd; + int ret = 0; + + lbs_deb_enter(LBS_DEB_CMD); + + memset(&cmd, 0, sizeof(cmd)); + cmd.hdr.size = cpu_to_le16(sizeof(cmd)); + cmd.action = cpu_to_le16(CMD_ACT_SET); + + if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS) + cmd.value.bbp_rf = (u8) (value & 0xFF); + else if (reg == CMD_MAC_REG_ACCESS) + cmd.value.mac = cpu_to_le32(value); + else { + ret = -EINVAL; + goto out; + } + + ret = lbs_cmd_with_response(priv, reg, &cmd); + +out: + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); + return ret; } static void lbs_queue_cmd(struct lbs_private *priv, @@ -771,16 +931,15 @@ static void lbs_queue_cmd(struct lbs_private *priv, /* Exit_PS command needs to be queued in the header always. */ if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_PS_MODE) { - struct cmd_ds_802_11_ps_mode *psm = (void *) &cmdnode->cmdbuf[1]; + struct cmd_ds_802_11_ps_mode *psm = (void *) &cmdnode->cmdbuf; - if (psm->action == cpu_to_le16(CMD_SUBCMD_EXIT_PS)) { + if (psm->action == cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) { if (priv->psstate != PS_STATE_FULL_POWER) addtail = 0; } } - if (le16_to_cpu(cmdnode->cmdbuf->command) == - CMD_802_11_WAKEUP_CONFIRM) + if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_WAKEUP_CONFIRM) addtail = 0; spin_lock_irqsave(&priv->driver_lock, flags); @@ -815,7 +974,6 @@ static void lbs_submit_command(struct lbs_private *priv, spin_lock_irqsave(&priv->driver_lock, flags); priv->cur_cmd = cmdnode; - priv->cur_cmd_retcode = 0; spin_unlock_irqrestore(&priv->driver_lock, flags); cmdsize = le16_to_cpu(cmd->size); @@ -888,9 +1046,6 @@ static void lbs_cleanup_and_insert_cmd(struct lbs_private *priv, void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, int result) { - if (cmd == priv->cur_cmd) - priv->cur_cmd_retcode = result; - cmd->result = result; cmd->cmdwaitqwoken = 1; wake_up_interruptible(&cmd->cmdwait_q); @@ -958,240 +1113,6 @@ void lbs_set_mac_control(struct lbs_private *priv) } /** - * @brief This function implements command CMD_802_11D_DOMAIN_INFO - * @param priv pointer to struct lbs_private - * @param cmd pointer to cmd buffer - * @param cmdno cmd ID - * @param cmdOption cmd action - * @return 0 -*/ -int lbs_cmd_802_11d_domain_info(struct lbs_private *priv, - struct cmd_ds_command *cmd, - u16 cmdoption) -{ - struct cmd_ds_802_11d_domain_info *pdomaininfo = - &cmd->params.domaininfo; - struct mrvl_ie_domain_param_set *domain = &pdomaininfo->domain; - u8 nr_triplet = priv->domain_reg.no_triplet; - - lbs_deb_enter(LBS_DEB_11D); - - lbs_deb_11d("nr_triplet=%x\n", nr_triplet); - - pdomaininfo->action = cpu_to_le16(cmdoption); - if (cmdoption == CMD_ACT_GET) { - cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) + - sizeof(struct cmd_header)); - lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd, - le16_to_cpu(cmd->size)); - goto done; - } - - domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN); - memcpy(domain->countrycode, priv->domain_reg.country_code, - sizeof(domain->countrycode)); - - domain->header.len = cpu_to_le16(nr_triplet - * sizeof(struct ieee80211_country_ie_triplet) - + sizeof(domain->countrycode)); - - if (nr_triplet) { - memcpy(domain->triplet, priv->domain_reg.triplet, - nr_triplet * - sizeof(struct ieee80211_country_ie_triplet)); - - cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) + - le16_to_cpu(domain->header.len) + - sizeof(struct mrvl_ie_header) + - sizeof(struct cmd_header)); - } else { - cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) + - sizeof(struct cmd_header)); - } - - lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd, - le16_to_cpu(cmd->size)); - -done: - lbs_deb_enter(LBS_DEB_11D); - return 0; -} - -/** - * @brief This function prepare the command before send to firmware. - * - * @param priv A pointer to struct lbs_private structure - * @param cmd_no command number - * @param cmd_action command action: GET or SET - * @param wait_option wait option: wait response or not - * @param cmd_oid cmd oid: treated as sub command - * @param pdata_buf A pointer to informaion buffer - * @return 0 or -1 - */ -int lbs_prepare_and_send_command(struct lbs_private *priv, - u16 cmd_no, - u16 cmd_action, - u16 wait_option, u32 cmd_oid, void *pdata_buf) -{ - int ret = 0; - struct cmd_ctrl_node *cmdnode; - struct cmd_ds_command *cmdptr; - unsigned long flags; - - lbs_deb_enter(LBS_DEB_HOST); - - if (!priv) { - lbs_deb_host("PREP_CMD: priv is NULL\n"); - ret = -1; - goto done; - } - - if (priv->surpriseremoved) { - lbs_deb_host("PREP_CMD: card removed\n"); - ret = -1; - goto done; - } - - if (!lbs_is_cmd_allowed(priv)) { - ret = -EBUSY; - goto done; - } - - cmdnode = lbs_get_cmd_ctrl_node(priv); - - if (cmdnode == NULL) { - lbs_deb_host("PREP_CMD: cmdnode is NULL\n"); - - /* Wake up main thread to execute next command */ - wake_up_interruptible(&priv->waitq); - ret = -1; - goto done; - } - - cmdnode->callback = NULL; - cmdnode->callback_arg = (unsigned long)pdata_buf; - - cmdptr = (struct cmd_ds_command *)cmdnode->cmdbuf; - - lbs_deb_host("PREP_CMD: command 0x%04x\n", cmd_no); - - /* Set sequence number, command and INT option */ - priv->seqnum++; - cmdptr->seqnum = cpu_to_le16(priv->seqnum); - - cmdptr->command = cpu_to_le16(cmd_no); - cmdptr->result = 0; - - switch (cmd_no) { - case CMD_802_11_PS_MODE: - ret = lbs_cmd_802_11_ps_mode(cmdptr, cmd_action); - break; - - case CMD_MAC_REG_ACCESS: - case CMD_BBP_REG_ACCESS: - case CMD_RF_REG_ACCESS: - ret = lbs_cmd_reg_access(cmdptr, cmd_action, pdata_buf); - break; - - case CMD_802_11_MONITOR_MODE: - ret = lbs_cmd_802_11_monitor_mode(cmdptr, - cmd_action, pdata_buf); - break; - - case CMD_802_11_RSSI: - ret = lbs_cmd_802_11_rssi(priv, cmdptr); - break; - - case CMD_802_11_SET_AFC: - case CMD_802_11_GET_AFC: - - cmdptr->command = cpu_to_le16(cmd_no); - cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) + - sizeof(struct cmd_header)); - - memmove(&cmdptr->params.afc, - pdata_buf, sizeof(struct cmd_ds_802_11_afc)); - - ret = 0; - goto done; - - case CMD_802_11D_DOMAIN_INFO: - cmdptr->command = cpu_to_le16(cmd_no); - ret = lbs_cmd_802_11d_domain_info(priv, cmdptr, cmd_action); - break; - - case CMD_802_11_TPC_CFG: - cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG); - cmdptr->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg) + - sizeof(struct cmd_header)); - - memmove(&cmdptr->params.tpccfg, - pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg)); - - ret = 0; - break; - -#ifdef CONFIG_LIBERTAS_MESH - - case CMD_BT_ACCESS: - ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf); - break; - - case CMD_FWT_ACCESS: - ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf); - break; - -#endif - - case CMD_802_11_BEACON_CTRL: - ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); - break; - case CMD_802_11_DEEP_SLEEP: - cmdptr->command = cpu_to_le16(CMD_802_11_DEEP_SLEEP); - cmdptr->size = cpu_to_le16(sizeof(struct cmd_header)); - break; - default: - lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no); - ret = -1; - break; - } - - /* return error, since the command preparation failed */ - if (ret != 0) { - lbs_deb_host("PREP_CMD: command preparation failed\n"); - lbs_cleanup_and_insert_cmd(priv, cmdnode); - ret = -1; - goto done; - } - - cmdnode->cmdwaitqwoken = 0; - - lbs_queue_cmd(priv, cmdnode); - wake_up_interruptible(&priv->waitq); - - if (wait_option & CMD_OPTION_WAITFORRSP) { - lbs_deb_host("PREP_CMD: wait for response\n"); - might_sleep(); - wait_event_interruptible(cmdnode->cmdwait_q, - cmdnode->cmdwaitqwoken); - } - - spin_lock_irqsave(&priv->driver_lock, flags); - if (priv->cur_cmd_retcode) { - lbs_deb_host("PREP_CMD: command failed with return code %d\n", - priv->cur_cmd_retcode); - priv->cur_cmd_retcode = 0; - ret = -1; - } - spin_unlock_irqrestore(&priv->driver_lock, flags); - -done: - lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret); - return ret; -} - -/** * @brief This function allocates the command buffer and link * it to command free queue. * @@ -1284,7 +1205,7 @@ done: * @param priv A pointer to struct lbs_private structure * @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL */ -static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv) +static struct cmd_ctrl_node *lbs_get_free_cmd_node(struct lbs_private *priv) { struct cmd_ctrl_node *tempnode; unsigned long flags; @@ -1367,10 +1288,10 @@ int lbs_execute_next_command(struct lbs_private *priv) /* * 1. Non-PS command: * Queue it. set needtowakeup to TRUE if current state - * is SLEEP, otherwise call lbs_ps_wakeup to send Exit_PS. - * 2. PS command but not Exit_PS: + * is SLEEP, otherwise call send EXIT_PS. + * 2. PS command but not EXIT_PS: * Ignore it. - * 3. PS command Exit_PS: + * 3. PS command EXIT_PS: * Set needtowakeup to TRUE if current state is SLEEP, * otherwise send this command down to firmware * immediately. @@ -1384,8 +1305,11 @@ int lbs_execute_next_command(struct lbs_private *priv) /* w/ new scheme, it will not reach here. since it is blocked in main_thread. */ priv->needtowakeup = 1; - } else - lbs_ps_wakeup(priv, 0); + } else { + lbs_set_ps_mode(priv, + PS_MODE_ACTION_EXIT_PS, + false); + } ret = 0; goto done; @@ -1400,7 +1324,7 @@ int lbs_execute_next_command(struct lbs_private *priv) "EXEC_NEXT_CMD: PS cmd, action 0x%02x\n", psm->action); if (psm->action != - cpu_to_le16(CMD_SUBCMD_EXIT_PS)) { + cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) { lbs_deb_host( "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n"); list_del(&cmdnode->list); @@ -1460,13 +1384,16 @@ int lbs_execute_next_command(struct lbs_private *priv) lbs_deb_host( "EXEC_NEXT_CMD: WPA enabled and GTK_SET" " go back to PS_SLEEP"); - lbs_ps_sleep(priv, 0); + lbs_set_ps_mode(priv, + PS_MODE_ACTION_ENTER_PS, + false); } } else { lbs_deb_host( "EXEC_NEXT_CMD: cmdpendingq empty, " "go back to PS_SLEEP"); - lbs_ps_sleep(priv, 0); + lbs_set_ps_mode(priv, PS_MODE_ACTION_ENTER_PS, + false); } } #endif @@ -1514,43 +1441,6 @@ out: lbs_deb_leave(LBS_DEB_HOST); } -void lbs_ps_sleep(struct lbs_private *priv, int wait_option) -{ - lbs_deb_enter(LBS_DEB_HOST); - - /* - * PS is currently supported only in Infrastructure mode - * Remove this check if it is to be supported in IBSS mode also - */ - - lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE, - CMD_SUBCMD_ENTER_PS, wait_option, 0, NULL); - - lbs_deb_leave(LBS_DEB_HOST); -} - -/** - * @brief This function sends Exit_PS command to firmware. - * - * @param priv A pointer to struct lbs_private structure - * @param wait_option wait response or not - * @return n/a - */ -void lbs_ps_wakeup(struct lbs_private *priv, int wait_option) -{ - __le32 Localpsmode; - - lbs_deb_enter(LBS_DEB_HOST); - - Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM); - - lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE, - CMD_SUBCMD_EXIT_PS, - wait_option, 0, &Localpsmode); - - lbs_deb_leave(LBS_DEB_HOST); -} - /** * @brief This function checks condition and prepares to * send sleep confirm command to firmware if ok. @@ -1675,12 +1565,18 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, goto done; } - if (!lbs_is_cmd_allowed(priv)) { - cmdnode = ERR_PTR(-EBUSY); - goto done; + /* No commands are allowed in Deep Sleep until we toggle the GPIO + * to wake up the card and it has signaled that it's ready. + */ + if (!priv->is_auto_deep_sleep_enabled) { + if (priv->is_deep_sleep) { + lbs_deb_cmd("command not allowed in deep sleep\n"); + cmdnode = ERR_PTR(-EBUSY); + goto done; + } } - cmdnode = lbs_get_cmd_ctrl_node(priv); + cmdnode = lbs_get_free_cmd_node(priv); if (cmdnode == NULL) { lbs_deb_host("PREP_CMD: cmdnode is NULL\n"); diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h index 386e565d99a..7109d6b717e 100644 --- a/drivers/net/wireless/libertas/cmd.h +++ b/drivers/net/wireless/libertas/cmd.h @@ -3,6 +3,8 @@ #ifndef _LBS_CMD_H_ #define _LBS_CMD_H_ +#include <net/cfg80211.h> + #include "host.h" #include "dev.h" @@ -37,11 +39,6 @@ struct cmd_ctrl_node { #define lbs_cmd_with_response(priv, cmdnr, cmd) \ lbs_cmd(priv, cmdnr, cmd, lbs_cmd_copyback, (unsigned long) (cmd)) -int lbs_prepare_and_send_command(struct lbs_private *priv, - u16 cmd_no, - u16 cmd_action, - u16 wait_option, u32 cmd_oid, void *pdata_buf); - void lbs_cmd_async(struct lbs_private *priv, uint16_t command, struct cmd_header *in_cmd, int in_cmd_size); @@ -92,10 +89,6 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, struct sleep_params *sp); -void lbs_ps_sleep(struct lbs_private *priv, int wait_option); - -void lbs_ps_wakeup(struct lbs_private *priv, int wait_option); - void lbs_ps_confirm_sleep(struct lbs_private *priv); int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on); @@ -129,4 +122,18 @@ int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep); int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep); +int lbs_set_monitor_mode(struct lbs_private *priv, int enable); + +int lbs_get_rssi(struct lbs_private *priv, s8 *snr, s8 *nf); + +int lbs_set_11d_domain_info(struct lbs_private *priv, + struct regulatory_request *request, + struct ieee80211_supported_band **bands); + +int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value); + +int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value); + +int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block); + #endif /* _LBS_CMD_H */ diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index a0d9482ef5e..5e95da9dcc2 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -49,171 +49,11 @@ void lbs_mac_event_disconnected(struct lbs_private *priv) if (priv->psstate != PS_STATE_FULL_POWER) { /* make firmware to exit PS mode */ lbs_deb_cmd("disconnected, so exit PS mode\n"); - lbs_ps_wakeup(priv, 0); + lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, false); } lbs_deb_leave(LBS_DEB_ASSOC); } -static int lbs_ret_reg_access(struct lbs_private *priv, - u16 type, struct cmd_ds_command *resp) -{ - int ret = 0; - - lbs_deb_enter(LBS_DEB_CMD); - - switch (type) { - case CMD_RET(CMD_MAC_REG_ACCESS): - { - struct cmd_ds_mac_reg_access *reg = &resp->params.macreg; - - priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset); - priv->offsetvalue.value = le32_to_cpu(reg->value); - break; - } - - case CMD_RET(CMD_BBP_REG_ACCESS): - { - struct cmd_ds_bbp_reg_access *reg = &resp->params.bbpreg; - - priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset); - priv->offsetvalue.value = reg->value; - break; - } - - case CMD_RET(CMD_RF_REG_ACCESS): - { - struct cmd_ds_rf_reg_access *reg = &resp->params.rfreg; - - priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset); - priv->offsetvalue.value = reg->value; - break; - } - - default: - ret = -1; - } - - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} - -/** - * @brief This function parses countryinfo from AP and download country info to FW - * @param priv pointer to struct lbs_private - * @param resp pointer to command response buffer - * @return 0; -1 - */ -static int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp) -{ - struct cmd_ds_802_11d_domain_info *domaininfo = - &resp->params.domaininforesp; - struct mrvl_ie_domain_param_set *domain = &domaininfo->domain; - u16 action = le16_to_cpu(domaininfo->action); - s16 ret = 0; - u8 nr_triplet = 0; - - lbs_deb_enter(LBS_DEB_11D); - - lbs_deb_hex(LBS_DEB_11D, "domain info resp", (u8 *) resp, - (int)le16_to_cpu(resp->size)); - - nr_triplet = (le16_to_cpu(domain->header.len) - COUNTRY_CODE_LEN) / - sizeof(struct ieee80211_country_ie_triplet); - - lbs_deb_11d("domain info resp: nr_triplet %d\n", nr_triplet); - - if (nr_triplet > MRVDRV_MAX_TRIPLET_802_11D) { - lbs_deb_11d("invalid number of triplets returned!!\n"); - return -1; - } - - switch (action) { - case CMD_ACT_SET: /*Proc set action */ - break; - - case CMD_ACT_GET: - break; - default: - lbs_deb_11d("invalid action:%d\n", domaininfo->action); - ret = -1; - break; - } - - lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret); - return ret; -} - -static inline int handle_cmd_response(struct lbs_private *priv, - struct cmd_header *cmd_response) -{ - struct cmd_ds_command *resp = (struct cmd_ds_command *) cmd_response; - int ret = 0; - unsigned long flags; - uint16_t respcmd = le16_to_cpu(resp->command); - - lbs_deb_enter(LBS_DEB_HOST); - - switch (respcmd) { - case CMD_RET(CMD_MAC_REG_ACCESS): - case CMD_RET(CMD_BBP_REG_ACCESS): - case CMD_RET(CMD_RF_REG_ACCESS): - ret = lbs_ret_reg_access(priv, respcmd, resp); - break; - - case CMD_RET(CMD_802_11_SET_AFC): - case CMD_RET(CMD_802_11_GET_AFC): - spin_lock_irqsave(&priv->driver_lock, flags); - memmove((void *)priv->cur_cmd->callback_arg, &resp->params.afc, - sizeof(struct cmd_ds_802_11_afc)); - spin_unlock_irqrestore(&priv->driver_lock, flags); - - break; - - case CMD_RET(CMD_802_11_BEACON_STOP): - break; - - case CMD_RET(CMD_802_11_RSSI): - ret = lbs_ret_802_11_rssi(priv, resp); - break; - - case CMD_RET(CMD_802_11D_DOMAIN_INFO): - ret = lbs_ret_802_11d_domain_info(resp); - break; - - case CMD_RET(CMD_802_11_TPC_CFG): - spin_lock_irqsave(&priv->driver_lock, flags); - memmove((void *)priv->cur_cmd->callback_arg, &resp->params.tpccfg, - sizeof(struct cmd_ds_802_11_tpc_cfg)); - spin_unlock_irqrestore(&priv->driver_lock, flags); - break; - - case CMD_RET(CMD_BT_ACCESS): - spin_lock_irqsave(&priv->driver_lock, flags); - if (priv->cur_cmd->callback_arg) - memcpy((void *)priv->cur_cmd->callback_arg, - &resp->params.bt.addr1, 2 * ETH_ALEN); - spin_unlock_irqrestore(&priv->driver_lock, flags); - break; - case CMD_RET(CMD_FWT_ACCESS): - spin_lock_irqsave(&priv->driver_lock, flags); - if (priv->cur_cmd->callback_arg) - memcpy((void *)priv->cur_cmd->callback_arg, &resp->params.fwt, - sizeof(resp->params.fwt)); - spin_unlock_irqrestore(&priv->driver_lock, flags); - break; - case CMD_RET(CMD_802_11_BEACON_CTRL): - ret = lbs_ret_802_11_bcn_ctrl(priv, resp); - break; - - default: - lbs_pr_err("CMD_RESP: unknown cmd response 0x%04x\n", - le16_to_cpu(resp->command)); - break; - } - lbs_deb_leave(LBS_DEB_HOST); - return ret; -} - int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) { uint16_t respcmd, curcmd; @@ -272,9 +112,6 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) del_timer(&priv->command_timer); priv->cmd_timed_out = 0; - /* Store the response code to cur_cmd_retcode. */ - priv->cur_cmd_retcode = result; - if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) { struct cmd_ds_802_11_ps_mode *psmode = (void *) &resp[1]; u16 action = le16_to_cpu(psmode->action); @@ -292,9 +129,9 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) * lbs_execute_next_command(). */ if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR && - action == CMD_SUBCMD_ENTER_PS) + action == PS_MODE_ACTION_ENTER_PS) priv->psmode = LBS802_11POWERMODECAM; - } else if (action == CMD_SUBCMD_ENTER_PS) { + } else if (action == PS_MODE_ACTION_ENTER_PS) { priv->needtowakeup = 0; priv->psstate = PS_STATE_AWAKE; @@ -309,11 +146,12 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) spin_unlock_irqrestore(&priv->driver_lock, flags); mutex_unlock(&priv->lock); - lbs_ps_wakeup(priv, 0); + lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, + false); mutex_lock(&priv->lock); spin_lock_irqsave(&priv->driver_lock, flags); } - } else if (action == CMD_SUBCMD_EXIT_PS) { + } else if (action == PS_MODE_ACTION_EXIT_PS) { priv->needtowakeup = 0; priv->psstate = PS_STATE_FULL_POWER; lbs_deb_host("CMD_RESP: EXIT_PS command response\n"); @@ -354,8 +192,7 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) if (priv->cur_cmd && priv->cur_cmd->callback) { ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg, resp); - } else - ret = handle_cmd_response(priv, resp); + } spin_lock_irqsave(&priv->driver_lock, flags); @@ -452,7 +289,7 @@ int lbs_process_event(struct lbs_private *priv, u32 event) * in lbs_ps_wakeup() */ lbs_deb_cmd("waking up ...\n"); - lbs_ps_wakeup(priv, 0); + lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, false); } break; diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index acaf8116462..651a79c8de8 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -446,30 +446,24 @@ static ssize_t lbs_bcnmiss_write(struct file *file, const char __user *userbuf, } - static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { struct lbs_private *priv = file->private_data; - struct lbs_offset_value offval; ssize_t pos = 0; int ret; unsigned long addr = get_zeroed_page(GFP_KERNEL); char *buf = (char *)addr; + u32 val = 0; + if (!buf) return -ENOMEM; - offval.offset = priv->mac_offset; - offval.value = 0; - - ret = lbs_prepare_and_send_command(priv, - CMD_MAC_REG_ACCESS, 0, - CMD_OPTION_WAITFORRSP, 0, &offval); + ret = lbs_get_reg(priv, CMD_MAC_REG_ACCESS, priv->mac_offset, &val); mdelay(10); if (!ret) { - pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n", - priv->mac_offset, priv->offsetvalue.value); - + pos = snprintf(buf, len, "MAC[0x%x] = 0x%08x\n", + priv->mac_offset, val); ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); } free_page(addr); @@ -507,7 +501,6 @@ static ssize_t lbs_wrmac_write(struct file *file, struct lbs_private *priv = file->private_data; ssize_t res, buf_size; u32 offset, value; - struct lbs_offset_value offval; unsigned long addr = get_zeroed_page(GFP_KERNEL); char *buf = (char *)addr; if (!buf) @@ -524,11 +517,7 @@ static ssize_t lbs_wrmac_write(struct file *file, goto out_unlock; } - offval.offset = offset; - offval.value = value; - res = lbs_prepare_and_send_command(priv, - CMD_MAC_REG_ACCESS, 1, - CMD_OPTION_WAITFORRSP, 0, &offval); + res = lbs_set_reg(priv, CMD_MAC_REG_ACCESS, offset, value); mdelay(10); if (!res) @@ -542,25 +531,20 @@ static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { struct lbs_private *priv = file->private_data; - struct lbs_offset_value offval; ssize_t pos = 0; int ret; unsigned long addr = get_zeroed_page(GFP_KERNEL); char *buf = (char *)addr; + u32 val; + if (!buf) return -ENOMEM; - offval.offset = priv->bbp_offset; - offval.value = 0; - - ret = lbs_prepare_and_send_command(priv, - CMD_BBP_REG_ACCESS, 0, - CMD_OPTION_WAITFORRSP, 0, &offval); + ret = lbs_get_reg(priv, CMD_BBP_REG_ACCESS, priv->bbp_offset, &val); mdelay(10); if (!ret) { - pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n", - priv->bbp_offset, priv->offsetvalue.value); - + pos = snprintf(buf, len, "BBP[0x%x] = 0x%08x\n", + priv->bbp_offset, val); ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); } free_page(addr); @@ -599,7 +583,6 @@ static ssize_t lbs_wrbbp_write(struct file *file, struct lbs_private *priv = file->private_data; ssize_t res, buf_size; u32 offset, value; - struct lbs_offset_value offval; unsigned long addr = get_zeroed_page(GFP_KERNEL); char *buf = (char *)addr; if (!buf) @@ -616,11 +599,7 @@ static ssize_t lbs_wrbbp_write(struct file *file, goto out_unlock; } - offval.offset = offset; - offval.value = value; - res = lbs_prepare_and_send_command(priv, - CMD_BBP_REG_ACCESS, 1, - CMD_OPTION_WAITFORRSP, 0, &offval); + res = lbs_set_reg(priv, CMD_BBP_REG_ACCESS, offset, value); mdelay(10); if (!res) @@ -634,25 +613,20 @@ static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { struct lbs_private *priv = file->private_data; - struct lbs_offset_value offval; ssize_t pos = 0; int ret; unsigned long addr = get_zeroed_page(GFP_KERNEL); char *buf = (char *)addr; + u32 val; + if (!buf) return -ENOMEM; - offval.offset = priv->rf_offset; - offval.value = 0; - - ret = lbs_prepare_and_send_command(priv, - CMD_RF_REG_ACCESS, 0, - CMD_OPTION_WAITFORRSP, 0, &offval); + ret = lbs_get_reg(priv, CMD_RF_REG_ACCESS, priv->rf_offset, &val); mdelay(10); if (!ret) { - pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n", - priv->rf_offset, priv->offsetvalue.value); - + pos = snprintf(buf, len, "RF[0x%x] = 0x%08x\n", + priv->rf_offset, val); ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); } free_page(addr); @@ -691,7 +665,6 @@ static ssize_t lbs_wrrf_write(struct file *file, struct lbs_private *priv = file->private_data; ssize_t res, buf_size; u32 offset, value; - struct lbs_offset_value offval; unsigned long addr = get_zeroed_page(GFP_KERNEL); char *buf = (char *)addr; if (!buf) @@ -708,11 +681,7 @@ static ssize_t lbs_wrrf_write(struct file *file, goto out_unlock; } - offval.offset = offset; - offval.value = value; - res = lbs_prepare_and_send_command(priv, - CMD_RF_REG_ACCESS, 1, - CMD_OPTION_WAITFORRSP, 0, &offval); + res = lbs_set_reg(priv, CMD_RF_REG_ACCESS, offset, value); mdelay(10); if (!res) @@ -905,7 +874,7 @@ static ssize_t lbs_debugfs_read(struct file *file, char __user *userbuf, p = buf; - d = (struct debug_data *)file->private_data; + d = file->private_data; for (i = 0; i < num_of_items; i++) { if (d[i].size == 1) @@ -944,7 +913,7 @@ static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf, char *p0; char *p1; char *p2; - struct debug_data *d = (struct debug_data *)f->private_data; + struct debug_data *d = f->private_data; pdata = kmalloc(cnt, GFP_KERNEL); if (pdata == NULL) diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index ba5438a7ba1..1d141fefd76 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h @@ -53,9 +53,4 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv); u32 lbs_fw_index_to_data_rate(u8 index); u8 lbs_data_rate_to_fw_index(u32 rate); -int lbs_cmd_802_11d_domain_info(struct lbs_private *priv, - struct cmd_ds_command *cmd, u16 cmdoption); - -int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp); - #endif diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index ea3f10ef4e0..d00c728cec4 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h @@ -172,11 +172,6 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in #define MRVDRV_MAX_BSS_DESCRIPTS 16 #define MRVDRV_MAX_REGION_CODE 6 -#define MRVDRV_IGNORE_MULTIPLE_DTIM 0xfffe -#define MRVDRV_MIN_MULTIPLE_DTIM 1 -#define MRVDRV_MAX_MULTIPLE_DTIM 5 -#define MRVDRV_DEFAULT_MULTIPLE_DTIM 1 - #define MRVDRV_DEFAULT_LISTEN_INTERVAL 10 #define MRVDRV_CHANNELS_PER_SCAN 4 @@ -301,19 +296,6 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in #define BAND_G (0x02) #define ALL_802_11_BANDS (BAND_B | BAND_G) -/** MACRO DEFINITIONS */ -#define CAL_NF(NF) ((s32)(-(s32)(NF))) -#define CAL_RSSI(SNR, NF) ((s32)((s32)(SNR) + CAL_NF(NF))) -#define SCAN_RSSI(RSSI) (0x100 - ((u8)(RSSI))) - -#define DEFAULT_BCN_AVG_FACTOR 8 -#define DEFAULT_DATA_AVG_FACTOR 8 -#define AVG_SCALE 100 -#define CAL_AVG_SNR_NF(AVG, SNRNF, N) \ - (((AVG) == 0) ? ((u16)(SNRNF) * AVG_SCALE) : \ - ((((int)(AVG) * (N -1)) + ((u16)(SNRNF) * \ - AVG_SCALE)) / N)) - #define MAX_RATES 14 #define MAX_LEDS 8 diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 4536d9c0ad8..3c7e255e18c 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -60,14 +60,10 @@ struct lbs_private { struct dentry *regs_dir; struct dentry *debugfs_regs_files[6]; - /** 11D and domain regulatory data */ - struct lbs_802_11d_domain_reg domain_reg; - /* Hardware debugging */ u32 mac_offset; u32 bbp_offset; u32 rf_offset; - struct lbs_offset_value offsetvalue; /* Power management */ u16 psmode; @@ -115,12 +111,10 @@ struct lbs_private { struct cmd_ctrl_node *cur_cmd; struct list_head cmdfreeq; /* free command buffers */ struct list_head cmdpendingq; /* pending command buffers */ - wait_queue_head_t cmd_pending; struct timer_list command_timer; int cmd_timed_out; /* Command responses sent from the hardware to the driver */ - int cur_cmd_retcode; u8 resp_idx; u8 resp_buf[2][LBS_UPLD_SIZE]; u32 resp_len[2]; diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h index db8e209878c..5eac1351a02 100644 --- a/drivers/net/wireless/libertas/host.h +++ b/drivers/net/wireless/libertas/host.h @@ -94,11 +94,9 @@ #define CMD_802_11_BEACON_CTRL 0x00b0 /* For the IEEE Power Save */ -#define CMD_SUBCMD_ENTER_PS 0x0030 -#define CMD_SUBCMD_EXIT_PS 0x0031 -#define CMD_SUBCMD_SLEEP_CONFIRMED 0x0034 -#define CMD_SUBCMD_FULL_POWERDOWN 0x0035 -#define CMD_SUBCMD_FULL_POWERUP 0x0036 +#define PS_MODE_ACTION_ENTER_PS 0x0030 +#define PS_MODE_ACTION_EXIT_PS 0x0031 +#define PS_MODE_ACTION_SLEEP_CONFIRMED 0x0034 #define CMD_ENABLE_RSN 0x0001 #define CMD_DISABLE_RSN 0x0000 @@ -163,11 +161,6 @@ #define CMD_ACT_SET_TX_FIX_RATE 0x0001 #define CMD_ACT_GET_TX_RATE 0x0002 -/* Define action or option for CMD_802_11_PS_MODE */ -#define CMD_TYPE_CAM 0x0000 -#define CMD_TYPE_MAX_PSP 0x0001 -#define CMD_TYPE_FAST_PSP 0x0002 - /* Options for CMD_802_11_FW_WAKE_METHOD */ #define CMD_WAKE_METHOD_UNCHANGED 0x0000 #define CMD_WAKE_METHOD_COMMAND_INT 0x0001 @@ -389,29 +382,21 @@ struct lbs_offset_value { u32 value; } __packed; -#define MRVDRV_MAX_TRIPLET_802_11D 83 - -#define COUNTRY_CODE_LEN 3 +#define MAX_11D_TRIPLETS 83 struct mrvl_ie_domain_param_set { struct mrvl_ie_header header; - u8 countrycode[COUNTRY_CODE_LEN]; - struct ieee80211_country_ie_triplet triplet[1]; -} __attribute__ ((packed)); + u8 country_code[3]; + struct ieee80211_country_ie_triplet triplet[MAX_11D_TRIPLETS]; +} __packed; struct cmd_ds_802_11d_domain_info { + struct cmd_header hdr; + __le16 action; struct mrvl_ie_domain_param_set domain; -} __attribute__ ((packed)); - -struct lbs_802_11d_domain_reg { - /** Country code*/ - u8 country_code[COUNTRY_CODE_LEN]; - /** No. of triplet*/ - u8 no_triplet; - struct ieee80211_country_ie_triplet triplet[MRVDRV_MAX_TRIPLET_802_11D]; -} __attribute__ ((packed)); +} __packed; /* * Define data structure for CMD_GET_HW_SPEC @@ -575,24 +560,15 @@ struct cmd_ds_802_11_snmp_mib { u8 value[128]; } __packed; -struct cmd_ds_mac_reg_access { - __le16 action; - __le16 offset; - __le32 value; -} __packed; - -struct cmd_ds_bbp_reg_access { - __le16 action; - __le16 offset; - u8 value; - u8 reserved[3]; -} __packed; +struct cmd_ds_reg_access { + struct cmd_header hdr; -struct cmd_ds_rf_reg_access { __le16 action; __le16 offset; - u8 value; - u8 reserved[3]; + union { + u8 bbp_rf; /* for BBP and RF registers */ + __le32 mac; /* for MAC registers */ + } value; } __packed; struct cmd_ds_802_11_radio_control { @@ -603,6 +579,8 @@ struct cmd_ds_802_11_radio_control { } __packed; struct cmd_ds_802_11_beacon_control { + struct cmd_header hdr; + __le16 action; __le16 beacon_enable; __le16 beacon_period; @@ -644,19 +622,19 @@ struct cmd_ds_802_11_rf_channel { } __packed; struct cmd_ds_802_11_rssi { - /* weighting factor */ - __le16 N; + struct cmd_header hdr; - __le16 reserved_0; - __le16 reserved_1; - __le16 reserved_2; -} __packed; + /* request: number of beacons (N) to average the SNR and NF over + * response: SNR of most recent beacon + */ + __le16 n_or_snr; -struct cmd_ds_802_11_rssi_rsp { - __le16 SNR; - __le16 noisefloor; - __le16 avgSNR; - __le16 avgnoisefloor; + /* The following fields are only set in the response. + * In the request these are reserved and should be set to 0. + */ + __le16 nf; /* most recent beacon noise floor */ + __le16 avg_snr; /* average SNR weighted by N from request */ + __le16 avg_nf; /* average noise floor weighted by N from request */ } __packed; struct cmd_ds_802_11_mac_address { @@ -675,7 +653,10 @@ struct cmd_ds_802_11_rf_tx_power { s8 minlevel; } __packed; +/* MONITOR_MODE only exists in OLPC v5 firmware */ struct cmd_ds_802_11_monitor_mode { + struct cmd_header hdr; + __le16 action; __le16 mode; } __packed; @@ -695,11 +676,35 @@ struct cmd_ds_802_11_fw_wake_method { } __packed; struct cmd_ds_802_11_ps_mode { + struct cmd_header hdr; + __le16 action; + + /* Interval for keepalive in PS mode: + * 0x0000 = don't change + * 0x001E = firmware default + * 0xFFFF = disable + */ __le16 nullpktinterval; + + /* Number of DTIM intervals to wake up for: + * 0 = don't change + * 1 = firmware default + * 5 = max + */ __le16 multipledtim; + __le16 reserved; __le16 locallisteninterval; + + /* AdHoc awake period (FW v9+ only): + * 0 = don't change + * 1 = always awake (IEEE standard behavior) + * 2 - 31 = sleep for (n - 1) periods and awake for 1 period + * 32 - 254 = invalid + * 255 = sleep at each ATIM + */ + __le16 adhoc_awake_period; } __packed; struct cmd_confirm_sleep { @@ -882,12 +887,17 @@ struct cmd_ds_802_11_pa_cfg { struct cmd_ds_802_11_led_ctrl { + struct cmd_header hdr; + __le16 action; __le16 numled; u8 data[256]; } __packed; +/* Automatic Frequency Control */ struct cmd_ds_802_11_afc { + struct cmd_header hdr; + __le16 afc_auto; union { struct { @@ -910,6 +920,8 @@ struct cmd_ds_get_tsf { } __packed; struct cmd_ds_bt_access { + struct cmd_header hdr; + __le16 action; __le32 id; u8 addr1[ETH_ALEN]; @@ -917,6 +929,8 @@ struct cmd_ds_bt_access { } __packed; struct cmd_ds_fwt_access { + struct cmd_header hdr; + __le16 action; __le32 id; u8 valid; @@ -955,34 +969,4 @@ struct cmd_ds_mesh_access { /* Number of stats counters returned by the firmware */ #define MESH_STATS_NUM 8 - -struct cmd_ds_command { - /* command header */ - __le16 command; - __le16 size; - __le16 seqnum; - __le16 result; - - /* command Body */ - union { - struct cmd_ds_802_11_ps_mode psmode; - struct cmd_ds_802_11_monitor_mode monitor; - struct cmd_ds_802_11_rssi rssi; - struct cmd_ds_802_11_rssi_rsp rssirsp; - struct cmd_ds_mac_reg_access macreg; - struct cmd_ds_bbp_reg_access bbpreg; - struct cmd_ds_rf_reg_access rfreg; - - struct cmd_ds_802_11d_domain_info domaininfo; - struct cmd_ds_802_11d_domain_info domaininforesp; - - struct cmd_ds_802_11_tpc_cfg tpccfg; - struct cmd_ds_802_11_afc afc; - struct cmd_ds_802_11_led_ctrl ledgpio; - - struct cmd_ds_bt_access bt; - struct cmd_ds_fwt_access fwt; - struct cmd_ds_802_11_beacon_control bcn_ctrl; - } params; -} __packed; #endif diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 3678e532874..07ece9d26c6 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -433,7 +433,7 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp) static int if_usb_reset_device(struct if_usb_card *cardp) { - struct cmd_ds_command *cmd = cardp->ep_out_buf + 4; + struct cmd_header *cmd = cardp->ep_out_buf + 4; int ret; lbs_deb_enter(LBS_DEB_USB); @@ -441,7 +441,7 @@ static int if_usb_reset_device(struct if_usb_card *cardp) *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST); cmd->command = cpu_to_le16(CMD_802_11_RESET); - cmd->size = cpu_to_le16(sizeof(struct cmd_header)); + cmd->size = cpu_to_le16(sizeof(cmd)); cmd->result = cpu_to_le16(0); cmd->seqnum = cpu_to_le16(0x5a5a); usb_tx_block(cardp, cardp->ep_out_buf, 4 + sizeof(struct cmd_header)); diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 2a0b590a93f..258967144b9 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -157,12 +157,7 @@ static void lbs_tx_timeout(struct net_device *dev) to kick it somehow? */ lbs_host_to_card_done(priv); - /* More often than not, this actually happens because the - firmware has crapped itself -- rather than just a very - busy medium. So send a harmless command, and if/when - _that_ times out, we'll kick it in the head. */ - lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, - 0, 0, NULL); + /* FIXME: reset the card */ lbs_deb_leave(LBS_DEB_TX); } @@ -507,12 +502,6 @@ static int lbs_thread(void *data) if (!priv->dnld_sent && !priv->cur_cmd) lbs_execute_next_command(priv); - /* Wake-up command waiters which can't sleep in - * lbs_prepare_and_send_command - */ - if (!list_empty(&priv->cmdpendingq)) - wake_up_all(&priv->cmd_pending); - spin_lock_irq(&priv->driver_lock); if (!priv->dnld_sent && priv->tx_pending_len > 0) { int ret = priv->hw_host_to_card(priv, MVMS_DAT, @@ -538,7 +527,6 @@ static int lbs_thread(void *data) del_timer(&priv->command_timer); del_timer(&priv->auto_deepsleep_timer); - wake_up_all(&priv->cmd_pending); lbs_deb_leave(LBS_DEB_THREAD); return 0; @@ -663,7 +651,6 @@ out: static void auto_deepsleep_timer_fn(unsigned long data) { struct lbs_private *priv = (struct lbs_private *)data; - int ret; lbs_deb_enter(LBS_DEB_CMD); @@ -671,14 +658,15 @@ static void auto_deepsleep_timer_fn(unsigned long data) priv->is_activity_detected = 0; } else { if (priv->is_auto_deep_sleep_enabled && - (!priv->wakeup_dev_required) && - (priv->connect_status != LBS_CONNECTED)) { + (!priv->wakeup_dev_required) && + (priv->connect_status != LBS_CONNECTED)) { + struct cmd_header cmd; + lbs_deb_main("Entering auto deep sleep mode...\n"); - ret = lbs_prepare_and_send_command(priv, - CMD_802_11_DEEP_SLEEP, 0, - 0, 0, NULL); - if (ret) - lbs_pr_err("Enter Deep Sleep command failed\n"); + memset(&cmd, 0, sizeof(cmd)); + cmd.size = cpu_to_le16(sizeof(cmd)); + lbs_cmd_async(priv, CMD_802_11_DEEP_SLEEP, &cmd, + sizeof(cmd)); } } mod_timer(&priv->auto_deepsleep_timer , jiffies + @@ -746,7 +734,6 @@ static int lbs_init_adapter(struct lbs_private *priv) INIT_LIST_HEAD(&priv->cmdpendingq); spin_lock_init(&priv->driver_lock); - init_waitqueue_head(&priv->cmd_pending); /* Allocate the command buffers */ if (lbs_allocate_cmd_buffer(priv)) { @@ -902,7 +889,7 @@ void lbs_remove_card(struct lbs_private *priv) if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { priv->psmode = LBS802_11POWERMODECAM; - lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP); + lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, true); } if (priv->is_deep_sleep) { @@ -1065,7 +1052,7 @@ static int __init lbs_init_module(void) memset(&confirm_sleep, 0, sizeof(confirm_sleep)); confirm_sleep.hdr.command = cpu_to_le16(CMD_802_11_PS_MODE); confirm_sleep.hdr.size = cpu_to_le16(sizeof(confirm_sleep)); - confirm_sleep.action = cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED); + confirm_sleep.action = cpu_to_le16(PS_MODE_ACTION_SLEEP_CONFIRMED); lbs_debugfs_init(); lbs_deb_leave(LBS_DEB_MAIN); return 0; diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index bc5bc1384c3..194762ab014 100644 --- a/drivers/net/wireless/libertas/mesh.c +++ b/drivers/net/wireless/libertas/mesh.c @@ -455,65 +455,189 @@ void lbs_mesh_set_txpd(struct lbs_private *priv, * Mesh command handling */ -int lbs_cmd_bt_access(struct cmd_ds_command *cmd, - u16 cmd_action, void *pdata_buf) +/** + * @brief Add or delete Mesh Blinding Table entries + * + * @param priv A pointer to struct lbs_private structure + * @param add TRUE to add the entry, FALSE to delete it + * @param addr1 Destination address to blind or unblind + * + * @return 0 on success, error on failure + */ +int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1) { - struct cmd_ds_bt_access *bt_access = &cmd->params.bt; - lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); + struct cmd_ds_bt_access cmd; + int ret = 0; - cmd->command = cpu_to_le16(CMD_BT_ACCESS); - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + - sizeof(struct cmd_header)); - cmd->result = 0; - bt_access->action = cpu_to_le16(cmd_action); + lbs_deb_enter(LBS_DEB_CMD); - switch (cmd_action) { - case CMD_ACT_BT_ACCESS_ADD: - memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN); + BUG_ON(addr1 == NULL); + + memset(&cmd, 0, sizeof(cmd)); + cmd.hdr.size = cpu_to_le16(sizeof(cmd)); + memcpy(cmd.addr1, addr1, ETH_ALEN); + if (add) { + cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_ADD); lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr", - bt_access->addr1, 6); - break; - case CMD_ACT_BT_ACCESS_DEL: - memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN); + addr1, ETH_ALEN); + } else { + cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_DEL); lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr", - bt_access->addr1, 6); - break; - case CMD_ACT_BT_ACCESS_LIST: - bt_access->id = cpu_to_le32(*(u32 *) pdata_buf); - break; - case CMD_ACT_BT_ACCESS_RESET: - break; - case CMD_ACT_BT_ACCESS_SET_INVERT: - bt_access->id = cpu_to_le32(*(u32 *) pdata_buf); - break; - case CMD_ACT_BT_ACCESS_GET_INVERT: - break; - default: - break; + addr1, ETH_ALEN); } - lbs_deb_leave(LBS_DEB_CMD); - return 0; + + ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd); + + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); + return ret; } -int lbs_cmd_fwt_access(struct cmd_ds_command *cmd, - u16 cmd_action, void *pdata_buf) +/** + * @brief Reset/clear the mesh blinding table + * + * @param priv A pointer to struct lbs_private structure + * + * @return 0 on success, error on failure + */ +int lbs_mesh_bt_reset(struct lbs_private *priv) { - struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt; - lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); + struct cmd_ds_bt_access cmd; + int ret = 0; - cmd->command = cpu_to_le16(CMD_FWT_ACCESS); - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) + - sizeof(struct cmd_header)); - cmd->result = 0; + lbs_deb_enter(LBS_DEB_CMD); - if (pdata_buf) - memcpy(fwt_access, pdata_buf, sizeof(*fwt_access)); - else - memset(fwt_access, 0, sizeof(*fwt_access)); + memset(&cmd, 0, sizeof(cmd)); + cmd.hdr.size = cpu_to_le16(sizeof(cmd)); + cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_RESET); - fwt_access->action = cpu_to_le16(cmd_action); + ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd); - lbs_deb_leave(LBS_DEB_CMD); + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); + return ret; +} + +/** + * @brief Gets the inverted status of the mesh blinding table + * + * Normally the firmware "blinds" or ignores traffic from mesh nodes in the + * table, but an inverted table allows *only* traffic from nodes listed in + * the table. + * + * @param priv A pointer to struct lbs_private structure + * @param invert On success, TRUE if the blinding table is inverted, + * FALSE if it is not inverted + * + * @return 0 on success, error on failure + */ +int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted) +{ + struct cmd_ds_bt_access cmd; + int ret = 0; + + lbs_deb_enter(LBS_DEB_CMD); + + BUG_ON(inverted == NULL); + + memset(&cmd, 0, sizeof(cmd)); + cmd.hdr.size = cpu_to_le16(sizeof(cmd)); + cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_GET_INVERT); + + ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd); + if (ret == 0) + *inverted = !!cmd.id; + + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); + return ret; +} + +/** + * @brief Sets the inverted status of the mesh blinding table + * + * Normally the firmware "blinds" or ignores traffic from mesh nodes in the + * table, but an inverted table allows *only* traffic from nodes listed in + * the table. + * + * @param priv A pointer to struct lbs_private structure + * @param invert TRUE to invert the blinding table (only traffic from + * listed nodes allowed), FALSE to return it + * to normal state (listed nodes ignored) + * + * @return 0 on success, error on failure + */ +int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted) +{ + struct cmd_ds_bt_access cmd; + int ret = 0; + + lbs_deb_enter(LBS_DEB_CMD); + + memset(&cmd, 0, sizeof(cmd)); + cmd.hdr.size = cpu_to_le16(sizeof(cmd)); + cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT); + cmd.id = !!inverted; + + ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd); + + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); + return ret; +} + +/** + * @brief List an entry in the mesh blinding table + * + * @param priv A pointer to struct lbs_private structure + * @param id The ID of the entry to list + * @param addr1 MAC address associated with the table entry + * + * @return 0 on success, error on failure + */ +int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1) +{ + struct cmd_ds_bt_access cmd; + int ret = 0; + + lbs_deb_enter(LBS_DEB_CMD); + + BUG_ON(addr1 == NULL); + + memset(&cmd, 0, sizeof(cmd)); + cmd.hdr.size = cpu_to_le16(sizeof(cmd)); + cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT); + cmd.id = cpu_to_le32(id); + + ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd); + if (ret == 0) + memcpy(addr1, cmd.addr1, sizeof(cmd.addr1)); + + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); + return ret; +} + +/** + * @brief Access the mesh forwarding table + * + * @param priv A pointer to struct lbs_private structure + * @param cmd_action The forwarding table action to perform + * @param cmd The pre-filled FWT_ACCESS command + * + * @return 0 on success and 'cmd' will be filled with the + * firmware's response + */ +int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action, + struct cmd_ds_fwt_access *cmd) +{ + int ret; + + lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); + + cmd->hdr.command = cpu_to_le16(CMD_FWT_ACCESS); + cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access)); + cmd->hdr.result = 0; + cmd->action = cpu_to_le16(cmd_action); + + ret = lbs_cmd_with_response(priv, CMD_FWT_ACCESS, cmd); + + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return 0; } diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h index 84ea2481ff2..afb2e8dead3 100644 --- a/drivers/net/wireless/libertas/mesh.h +++ b/drivers/net/wireless/libertas/mesh.h @@ -8,6 +8,7 @@ #include <net/iw_handler.h> #include <net/lib80211.h> +#include "host.h" #ifdef CONFIG_LIBERTAS_MESH @@ -51,10 +52,15 @@ struct cmd_ds_command; struct cmd_ds_mesh_access; struct cmd_ds_mesh_config; -int lbs_cmd_bt_access(struct cmd_ds_command *cmd, - u16 cmd_action, void *pdata_buf); -int lbs_cmd_fwt_access(struct cmd_ds_command *cmd, - u16 cmd_action, void *pdata_buf); +int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1); +int lbs_mesh_bt_reset(struct lbs_private *priv); +int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted); +int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted); +int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1); + +int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action, + struct cmd_ds_fwt_access *cmd); + int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, struct cmd_ds_mesh_access *cmd); int lbs_mesh_config_send(struct lbs_private *priv, diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index 411a3bbf035..8000ca6165d 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c @@ -180,7 +180,7 @@ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count) { struct tx_radiotap_hdr *radiotap_hdr; - if (!priv->wdev->iftype == NL80211_IFTYPE_MONITOR || + if (priv->wdev->iftype != NL80211_IFTYPE_MONITOR || priv->currenttxskb == NULL) return; diff --git a/drivers/net/wireless/libertas_tf/libertas_tf.h b/drivers/net/wireless/libertas_tf/libertas_tf.h index 737eac92ef7..ad77b92d0b4 100644 --- a/drivers/net/wireless/libertas_tf/libertas_tf.h +++ b/drivers/net/wireless/libertas_tf/libertas_tf.h @@ -253,6 +253,9 @@ struct lbtf_private { u8 fw_ready; u8 surpriseremoved; struct sk_buff_head bc_ps_buf; + + /* Most recently reported noise in dBm */ + s8 noise; }; /* 802.11-related definitions */ diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 817fffc0de4..9278b3c8ee3 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -525,6 +525,22 @@ static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw, lbtf_deb_leave(LBTF_DEB_MACOPS); } +static int lbtf_op_get_survey(struct ieee80211_hw *hw, int idx, + struct survey_info *survey) +{ + struct lbtf_private *priv = hw->priv; + struct ieee80211_conf *conf = &hw->conf; + + if (idx != 0) + return -ENOENT; + + survey->channel = conf->channel; + survey->filled = SURVEY_INFO_NOISE_DBM; + survey->noise = priv->noise; + + return 0; +} + static const struct ieee80211_ops lbtf_ops = { .tx = lbtf_op_tx, .start = lbtf_op_start, @@ -535,6 +551,7 @@ static const struct ieee80211_ops lbtf_ops = { .prepare_multicast = lbtf_op_prepare_multicast, .configure_filter = lbtf_op_configure_filter, .bss_info_changed = lbtf_op_bss_info_changed, + .get_survey = lbtf_op_get_survey, }; int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb) @@ -555,6 +572,7 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb) stats.freq = priv->cur_freq; stats.band = IEEE80211_BAND_2GHZ; stats.signal = prxpd->snr; + priv->noise = prxpd->nf; /* Marvell rate index has a hole at value 4 */ if (prxpd->rx_rate > 4) --prxpd->rx_rate; diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index e7f299dc9ef..01ad7f77383 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -486,8 +486,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, struct ieee80211_rx_status rx_status; if (data->idle) { - printk(KERN_DEBUG "%s: Trying to TX when idle - reject\n", - wiphy_name(hw->wiphy)); + wiphy_debug(hw->wiphy, "trying to tx when idle - reject\n"); return false; } @@ -576,7 +575,7 @@ static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) static int mac80211_hwsim_start(struct ieee80211_hw *hw) { struct mac80211_hwsim_data *data = hw->priv; - printk(KERN_DEBUG "%s:%s\n", wiphy_name(hw->wiphy), __func__); + wiphy_debug(hw->wiphy, "%s\n", __func__); data->started = 1; return 0; } @@ -587,16 +586,15 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw) struct mac80211_hwsim_data *data = hw->priv; data->started = 0; del_timer(&data->beacon_timer); - printk(KERN_DEBUG "%s:%s\n", wiphy_name(hw->wiphy), __func__); + wiphy_debug(hw->wiphy, "%s\n", __func__); } static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n", - wiphy_name(hw->wiphy), __func__, vif->type, - vif->addr); + wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n", + __func__, vif->type, vif->addr); hwsim_set_magic(vif); return 0; } @@ -605,9 +603,8 @@ static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw, static void mac80211_hwsim_remove_interface( struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n", - wiphy_name(hw->wiphy), __func__, vif->type, - vif->addr); + wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n", + __func__, vif->type, vif->addr); hwsim_check_magic(vif); hwsim_clear_magic(vif); } @@ -670,13 +667,14 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) [IEEE80211_SMPS_DYNAMIC] = "dynamic", }; - printk(KERN_DEBUG "%s:%s (freq=%d/%s idle=%d ps=%d smps=%s)\n", - wiphy_name(hw->wiphy), __func__, - conf->channel->center_freq, - hwsim_chantypes[conf->channel_type], - !!(conf->flags & IEEE80211_CONF_IDLE), - !!(conf->flags & IEEE80211_CONF_PS), - smps_modes[conf->smps_mode]); + wiphy_debug(hw->wiphy, + "%s (freq=%d/%s idle=%d ps=%d smps=%s)\n", + __func__, + conf->channel->center_freq, + hwsim_chantypes[conf->channel_type], + !!(conf->flags & IEEE80211_CONF_IDLE), + !!(conf->flags & IEEE80211_CONF_PS), + smps_modes[conf->smps_mode]); data->idle = !!(conf->flags & IEEE80211_CONF_IDLE); @@ -696,7 +694,7 @@ static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw, { struct mac80211_hwsim_data *data = hw->priv; - printk(KERN_DEBUG "%s:%s\n", wiphy_name(hw->wiphy), __func__); + wiphy_debug(hw->wiphy, "%s\n", __func__); data->rx_filter = 0; if (*total_flags & FIF_PROMISC_IN_BSS) @@ -717,26 +715,23 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, hwsim_check_magic(vif); - printk(KERN_DEBUG "%s:%s(changed=0x%x)\n", - wiphy_name(hw->wiphy), __func__, changed); + wiphy_debug(hw->wiphy, "%s(changed=0x%x)\n", __func__, changed); if (changed & BSS_CHANGED_BSSID) { - printk(KERN_DEBUG "%s:%s: BSSID changed: %pM\n", - wiphy_name(hw->wiphy), __func__, - info->bssid); + wiphy_debug(hw->wiphy, "%s: BSSID changed: %pM\n", + __func__, info->bssid); memcpy(vp->bssid, info->bssid, ETH_ALEN); } if (changed & BSS_CHANGED_ASSOC) { - printk(KERN_DEBUG " %s: ASSOC: assoc=%d aid=%d\n", - wiphy_name(hw->wiphy), info->assoc, info->aid); + wiphy_debug(hw->wiphy, " ASSOC: assoc=%d aid=%d\n", + info->assoc, info->aid); vp->assoc = info->assoc; vp->aid = info->aid; } if (changed & BSS_CHANGED_BEACON_INT) { - printk(KERN_DEBUG " %s: BCNINT: %d\n", - wiphy_name(hw->wiphy), info->beacon_int); + wiphy_debug(hw->wiphy, " BCNINT: %d\n", info->beacon_int); data->beacon_int = 1024 * info->beacon_int / 1000 * HZ / 1000; if (WARN_ON(!data->beacon_int)) data->beacon_int = 1; @@ -746,31 +741,28 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_ERP_CTS_PROT) { - printk(KERN_DEBUG " %s: ERP_CTS_PROT: %d\n", - wiphy_name(hw->wiphy), info->use_cts_prot); + wiphy_debug(hw->wiphy, " ERP_CTS_PROT: %d\n", + info->use_cts_prot); } if (changed & BSS_CHANGED_ERP_PREAMBLE) { - printk(KERN_DEBUG " %s: ERP_PREAMBLE: %d\n", - wiphy_name(hw->wiphy), info->use_short_preamble); + wiphy_debug(hw->wiphy, " ERP_PREAMBLE: %d\n", + info->use_short_preamble); } if (changed & BSS_CHANGED_ERP_SLOT) { - printk(KERN_DEBUG " %s: ERP_SLOT: %d\n", - wiphy_name(hw->wiphy), info->use_short_slot); + wiphy_debug(hw->wiphy, " ERP_SLOT: %d\n", info->use_short_slot); } if (changed & BSS_CHANGED_HT) { - printk(KERN_DEBUG " %s: HT: op_mode=0x%x, chantype=%s\n", - wiphy_name(hw->wiphy), - info->ht_operation_mode, - hwsim_chantypes[info->channel_type]); + wiphy_debug(hw->wiphy, " HT: op_mode=0x%x, chantype=%s\n", + info->ht_operation_mode, + hwsim_chantypes[info->channel_type]); } if (changed & BSS_CHANGED_BASIC_RATES) { - printk(KERN_DEBUG " %s: BASIC_RATES: 0x%llx\n", - wiphy_name(hw->wiphy), - (unsigned long long) info->basic_rates); + wiphy_debug(hw->wiphy, " BASIC_RATES: 0x%llx\n", + (unsigned long long) info->basic_rates); } } @@ -824,10 +816,11 @@ static int mac80211_hwsim_conf_tx( struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { - printk(KERN_DEBUG "%s:%s (queue=%d txop=%d cw_min=%d cw_max=%d " - "aifs=%d)\n", - wiphy_name(hw->wiphy), __func__, queue, - params->txop, params->cw_min, params->cw_max, params->aifs); + wiphy_debug(hw->wiphy, + "%s (queue=%d txop=%d cw_min=%d cw_max=%d aifs=%d)\n", + __func__, queue, + params->txop, params->cw_min, + params->cw_max, params->aifs); return 0; } @@ -837,8 +830,7 @@ static int mac80211_hwsim_get_survey( { struct ieee80211_conf *conf = &hw->conf; - printk(KERN_DEBUG "%s:%s (idx=%d)\n", - wiphy_name(hw->wiphy), __func__, idx); + wiphy_debug(hw->wiphy, "%s (idx=%d)\n", __func__, idx); if (idx != 0) return -ENOENT; @@ -1108,8 +1100,9 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif) if (!vp->assoc) return; - printk(KERN_DEBUG "%s:%s: send PS-Poll to %pM for aid %d\n", - wiphy_name(data->hw->wiphy), __func__, vp->bssid, vp->aid); + wiphy_debug(data->hw->wiphy, + "%s: send PS-Poll to %pM for aid %d\n", + __func__, vp->bssid, vp->aid); skb = dev_alloc_skb(sizeof(*pspoll)); if (!skb) @@ -1137,8 +1130,9 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac, if (!vp->assoc) return; - printk(KERN_DEBUG "%s:%s: send data::nullfunc to %pM ps=%d\n", - wiphy_name(data->hw->wiphy), __func__, vp->bssid, ps); + wiphy_debug(data->hw->wiphy, + "%s: send data::nullfunc to %pM ps=%d\n", + __func__, vp->bssid, ps); skb = dev_alloc_skb(sizeof(*hdr)); if (!skb) @@ -1473,9 +1467,8 @@ static int __init init_mac80211_hwsim(void) break; } - printk(KERN_DEBUG "%s: hwaddr %pM registered\n", - wiphy_name(hw->wiphy), - hw->wiphy->perm_addr); + wiphy_debug(hw->wiphy, "hwaddr %pm registered\n", + hw->wiphy->perm_addr); data->debugfs = debugfs_create_dir("hwsim", hw->wiphy->debugfsdir); diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index c019fdc131c..d761ed2d8af 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -86,7 +86,7 @@ struct rxd_ops { void (*rxd_init)(void *rxd, dma_addr_t next_dma_addr); void (*rxd_refill)(void *rxd, dma_addr_t addr, int len); int (*rxd_process)(void *rxd, struct ieee80211_rx_status *status, - __le16 *qos); + __le16 *qos, s8 *noise); }; struct mwl8k_device_info { @@ -207,6 +207,9 @@ struct mwl8k_priv { /* Tasklet to perform RX. */ struct tasklet_struct poll_rx_task; + + /* Most recently reported noise in dBm */ + s8 noise; }; /* Per interface specific private data */ @@ -314,13 +317,15 @@ static const struct ieee80211_rate mwl8k_rates_50[] = { #define MWL8K_CMD_SET_NEW_STN 0x1111 /* per-vif */ #define MWL8K_CMD_UPDATE_STADB 0x1123 -static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) +static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize) { + u16 command = le16_to_cpu(cmd); + #define MWL8K_CMDNAME(x) case MWL8K_CMD_##x: do {\ snprintf(buf, bufsize, "%s", #x);\ return buf;\ } while (0) - switch (cmd & ~0x8000) { + switch (command & ~0x8000) { MWL8K_CMDNAME(CODE_DNLD); MWL8K_CMDNAME(GET_HW_SPEC); MWL8K_CMDNAME(SET_HW_SPEC); @@ -739,7 +744,7 @@ static void mwl8k_rxd_8366_ap_refill(void *_rxd, dma_addr_t addr, int len) static int mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status, - __le16 *qos) + __le16 *qos, s8 *noise) { struct mwl8k_rxd_8366_ap *rxd = _rxd; @@ -750,6 +755,7 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status, memset(status, 0, sizeof(*status)); status->signal = -rxd->rssi; + *noise = -rxd->noise_floor; if (rxd->rate & MWL8K_8366_AP_RATE_INFO_MCS_FORMAT) { status->flag |= RX_FLAG_HT; @@ -837,7 +843,7 @@ static void mwl8k_rxd_sta_refill(void *_rxd, dma_addr_t addr, int len) static int mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status, - __le16 *qos) + __le16 *qos, s8 *noise) { struct mwl8k_rxd_sta *rxd = _rxd; u16 rate_info; @@ -851,6 +857,7 @@ mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status, memset(status, 0, sizeof(*status)); status->signal = -rxd->rssi; + *noise = -rxd->noise_level; status->antenna = MWL8K_STA_RATE_INFO_ANTSELECT(rate_info); status->rate_idx = MWL8K_STA_RATE_INFO_RATEID(rate_info); @@ -903,16 +910,14 @@ static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index) rxq->rxd = pci_alloc_consistent(priv->pdev, size, &rxq->rxd_dma); if (rxq->rxd == NULL) { - printk(KERN_ERR "%s: failed to alloc RX descriptors\n", - wiphy_name(hw->wiphy)); + wiphy_err(hw->wiphy, "failed to alloc rx descriptors\n"); return -ENOMEM; } memset(rxq->rxd, 0, size); rxq->buf = kmalloc(MWL8K_RX_DESCS * sizeof(*rxq->buf), GFP_KERNEL); if (rxq->buf == NULL) { - printk(KERN_ERR "%s: failed to alloc RX skbuff list\n", - wiphy_name(hw->wiphy)); + wiphy_err(hw->wiphy, "failed to alloc rx skbuff list\n"); pci_free_consistent(priv->pdev, size, rxq->rxd, rxq->rxd_dma); return -ENOMEM; } @@ -1053,7 +1058,8 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) rxd = rxq->rxd + (rxq->head * priv->rxd_ops->rxd_size); - pkt_len = priv->rxd_ops->rxd_process(rxd, &status, &qos); + pkt_len = priv->rxd_ops->rxd_process(rxd, &status, &qos, + &priv->noise); if (pkt_len < 0) break; @@ -1139,16 +1145,14 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index) txq->txd = pci_alloc_consistent(priv->pdev, size, &txq->txd_dma); if (txq->txd == NULL) { - printk(KERN_ERR "%s: failed to alloc TX descriptors\n", - wiphy_name(hw->wiphy)); + wiphy_err(hw->wiphy, "failed to alloc tx descriptors\n"); return -ENOMEM; } memset(txq->txd, 0, size); txq->skb = kmalloc(MWL8K_TX_DESCS * sizeof(*txq->skb), GFP_KERNEL); if (txq->skb == NULL) { - printk(KERN_ERR "%s: failed to alloc TX skbuff list\n", - wiphy_name(hw->wiphy)); + wiphy_err(hw->wiphy, "failed to alloc tx skbuff list\n"); pci_free_consistent(priv->pdev, size, txq->txd, txq->txd_dma); return -ENOMEM; } @@ -1204,11 +1208,12 @@ static void mwl8k_dump_tx_rings(struct ieee80211_hw *hw) unused++; } - printk(KERN_ERR "%s: txq[%d] len=%d head=%d tail=%d " - "fw_owned=%d drv_owned=%d unused=%d\n", - wiphy_name(hw->wiphy), i, - txq->len, txq->head, txq->tail, - fw_owned, drv_owned, unused); + wiphy_err(hw->wiphy, + "txq[%d] len=%d head=%d tail=%d " + "fw_owned=%d drv_owned=%d unused=%d\n", + i, + txq->len, txq->head, txq->tail, + fw_owned, drv_owned, unused); } } @@ -1252,25 +1257,23 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) if (timeout) { WARN_ON(priv->pending_tx_pkts); if (retry) { - printk(KERN_NOTICE "%s: tx rings drained\n", - wiphy_name(hw->wiphy)); + wiphy_notice(hw->wiphy, "tx rings drained\n"); } break; } if (priv->pending_tx_pkts < oldcount) { - printk(KERN_NOTICE "%s: waiting for tx rings " - "to drain (%d -> %d pkts)\n", - wiphy_name(hw->wiphy), oldcount, - priv->pending_tx_pkts); + wiphy_notice(hw->wiphy, + "waiting for tx rings to drain (%d -> %d pkts)\n", + oldcount, priv->pending_tx_pkts); retry = 1; continue; } priv->tx_wait = NULL; - printk(KERN_ERR "%s: tx rings stuck for %d ms\n", - wiphy_name(hw->wiphy), MWL8K_TX_WAIT_TIMEOUT_MS); + wiphy_err(hw->wiphy, "tx rings stuck for %d ms\n", + MWL8K_TX_WAIT_TIMEOUT_MS); mwl8k_dump_tx_rings(hw); rc = -ETIMEDOUT; @@ -1421,8 +1424,8 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) skb->len, PCI_DMA_TODEVICE); if (pci_dma_mapping_error(priv->pdev, dma)) { - printk(KERN_DEBUG "%s: failed to dma map skb, " - "dropping TX frame.\n", wiphy_name(hw->wiphy)); + wiphy_debug(hw->wiphy, + "failed to dma map skb, dropping TX frame.\n"); dev_kfree_skb(skb); return NETDEV_TX_OK; } @@ -1538,7 +1541,7 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) unsigned long timeout = 0; u8 buf[32]; - cmd->result = 0xffff; + cmd->result = (__force __le16) 0xffff; dma_size = le16_to_cpu(cmd->length); dma_addr = pci_map_single(priv->pdev, cmd, dma_size, PCI_DMA_BIDIRECTIONAL); @@ -1570,10 +1573,9 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) PCI_DMA_BIDIRECTIONAL); if (!timeout) { - printk(KERN_ERR "%s: Command %s timeout after %u ms\n", - wiphy_name(hw->wiphy), - mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), - MWL8K_CMD_TIMEOUT_MS); + wiphy_err(hw->wiphy, "command %s timeout after %u ms\n", + mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), + MWL8K_CMD_TIMEOUT_MS); rc = -ETIMEDOUT; } else { int ms; @@ -1582,15 +1584,14 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) rc = cmd->result ? -EINVAL : 0; if (rc) - printk(KERN_ERR "%s: Command %s error 0x%x\n", - wiphy_name(hw->wiphy), - mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), - le16_to_cpu(cmd->result)); + wiphy_err(hw->wiphy, "command %s error 0x%x\n", + mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), + le16_to_cpu(cmd->result)); else if (ms > 2000) - printk(KERN_NOTICE "%s: Command %s took %d ms\n", - wiphy_name(hw->wiphy), - mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), - ms); + wiphy_notice(hw->wiphy, "command %s took %d ms\n", + mwl8k_cmd_name(cmd->code, + buf, sizeof(buf)), + ms); } return rc; @@ -1842,22 +1843,22 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) priv->sta_macids_supported = 0x00000000; off = le32_to_cpu(cmd->wcbbase0) & 0xffff; - iowrite32(cpu_to_le32(priv->txq[0].txd_dma), priv->sram + off); + iowrite32(priv->txq[0].txd_dma, priv->sram + off); off = le32_to_cpu(cmd->rxwrptr) & 0xffff; - iowrite32(cpu_to_le32(priv->rxq[0].rxd_dma), priv->sram + off); + iowrite32(priv->rxq[0].rxd_dma, priv->sram + off); off = le32_to_cpu(cmd->rxrdptr) & 0xffff; - iowrite32(cpu_to_le32(priv->rxq[0].rxd_dma), priv->sram + off); + iowrite32(priv->rxq[0].rxd_dma, priv->sram + off); off = le32_to_cpu(cmd->wcbbase1) & 0xffff; - iowrite32(cpu_to_le32(priv->txq[1].txd_dma), priv->sram + off); + iowrite32(priv->txq[1].txd_dma, priv->sram + off); off = le32_to_cpu(cmd->wcbbase2) & 0xffff; - iowrite32(cpu_to_le32(priv->txq[2].txd_dma), priv->sram + off); + iowrite32(priv->txq[2].txd_dma, priv->sram + off); off = le32_to_cpu(cmd->wcbbase3) & 0xffff; - iowrite32(cpu_to_le32(priv->txq[3].txd_dma), priv->sram + off); + iowrite32(priv->txq[3].txd_dma, priv->sram + off); } kfree(cmd); @@ -3052,7 +3053,7 @@ static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw, p->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; p->basic_caps = cpu_to_le16(vif->bss_conf.assoc_capability); p->ht_support = sta->ht_cap.ht_supported; - p->ht_caps = sta->ht_cap.cap; + p->ht_caps = cpu_to_le16(sta->ht_cap.cap); p->extended_ht_caps = (sta->ht_cap.ampdu_factor & 3) | ((sta->ht_cap.ampdu_density & 7) << 2); if (hw->conf.channel->band == IEEE80211_BAND_2GHZ) @@ -3190,8 +3191,8 @@ static int mwl8k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) int rc; if (!priv->radio_on) { - printk(KERN_DEBUG "%s: dropped TX frame since radio " - "disabled\n", wiphy_name(hw->wiphy)); + wiphy_debug(hw->wiphy, + "dropped TX frame since radio disabled\n"); dev_kfree_skb(skb); return NETDEV_TX_OK; } @@ -3209,8 +3210,7 @@ static int mwl8k_start(struct ieee80211_hw *hw) rc = request_irq(priv->pdev->irq, mwl8k_interrupt, IRQF_SHARED, MWL8K_NAME, hw); if (rc) { - printk(KERN_ERR "%s: failed to register IRQ handler\n", - wiphy_name(hw->wiphy)); + wiphy_err(hw->wiphy, "failed to register irq handler\n"); return -EIO; } @@ -3297,9 +3297,8 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, * mode. (Sniffer mode is only used on STA firmware.) */ if (priv->sniffer_enabled) { - printk(KERN_INFO "%s: unable to create STA " - "interface due to sniffer mode being enabled\n", - wiphy_name(hw->wiphy)); + wiphy_info(hw->wiphy, + "unable to create STA interface because sniffer mode is enabled\n"); return -EINVAL; } @@ -3581,9 +3580,8 @@ mwl8k_configure_filter_sniffer(struct ieee80211_hw *hw, */ if (!list_empty(&priv->vif_list)) { if (net_ratelimit()) - printk(KERN_INFO "%s: not enabling sniffer " - "mode because STA interface is active\n", - wiphy_name(hw->wiphy)); + wiphy_info(hw->wiphy, + "not enabling sniffer mode because STA interface is active\n"); return 0; } @@ -3763,6 +3761,22 @@ static int mwl8k_get_stats(struct ieee80211_hw *hw, return mwl8k_cmd_get_stat(hw, stats); } +static int mwl8k_get_survey(struct ieee80211_hw *hw, int idx, + struct survey_info *survey) +{ + struct mwl8k_priv *priv = hw->priv; + struct ieee80211_conf *conf = &hw->conf; + + if (idx != 0) + return -ENOENT; + + survey->channel = conf->channel; + survey->filled = SURVEY_INFO_NOISE_DBM; + survey->noise = priv->noise; + + return 0; +} + static int mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, @@ -3794,6 +3808,7 @@ static const struct ieee80211_ops mwl8k_ops = { .sta_remove = mwl8k_sta_remove, .conf_tx = mwl8k_conf_tx, .get_stats = mwl8k_get_stats, + .get_survey = mwl8k_get_survey, .ampdu_action = mwl8k_ampdu_action, }; @@ -3911,8 +3926,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, priv->sram = pci_iomap(pdev, 0, 0x10000); if (priv->sram == NULL) { - printk(KERN_ERR "%s: Cannot map device SRAM\n", - wiphy_name(hw->wiphy)); + wiphy_err(hw->wiphy, "cannot map device sram\n"); goto err_iounmap; } @@ -3924,8 +3938,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, if (priv->regs == NULL) { priv->regs = pci_iomap(pdev, 2, 0x10000); if (priv->regs == NULL) { - printk(KERN_ERR "%s: Cannot map device registers\n", - wiphy_name(hw->wiphy)); + wiphy_err(hw->wiphy, "cannot map device registers\n"); goto err_iounmap; } } @@ -3937,16 +3950,14 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, /* Ask userland hotplug daemon for the device firmware */ rc = mwl8k_request_firmware(priv); if (rc) { - printk(KERN_ERR "%s: Firmware files not found\n", - wiphy_name(hw->wiphy)); + wiphy_err(hw->wiphy, "firmware files not found\n"); goto err_stop_firmware; } /* Load firmware into hardware */ rc = mwl8k_load_firmware(hw); if (rc) { - printk(KERN_ERR "%s: Cannot start firmware\n", - wiphy_name(hw->wiphy)); + wiphy_err(hw->wiphy, "cannot start firmware\n"); goto err_stop_firmware; } @@ -3957,9 +3968,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, if (priv->ap_fw) { priv->rxd_ops = priv->device_info->ap_rxd_ops; if (priv->rxd_ops == NULL) { - printk(KERN_ERR "%s: Driver does not have AP " - "firmware image support for this hardware\n", - wiphy_name(hw->wiphy)); + wiphy_err(hw->wiphy, + "Driver does not have AP firmware image support for this hardware\n"); goto err_stop_firmware; } } else { @@ -4037,8 +4047,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, rc = request_irq(priv->pdev->irq, mwl8k_interrupt, IRQF_SHARED, MWL8K_NAME, hw); if (rc) { - printk(KERN_ERR "%s: failed to register IRQ handler\n", - wiphy_name(hw->wiphy)); + wiphy_err(hw->wiphy, "failed to register irq handler\n"); goto err_free_queues; } @@ -4058,8 +4067,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, rc = mwl8k_cmd_get_hw_spec_sta(hw); } if (rc) { - printk(KERN_ERR "%s: Cannot initialise firmware\n", - wiphy_name(hw->wiphy)); + wiphy_err(hw->wiphy, "cannot initialise firmware\n"); goto err_free_irq; } @@ -4073,15 +4081,14 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, /* Turn radio off */ rc = mwl8k_cmd_radio_disable(hw); if (rc) { - printk(KERN_ERR "%s: Cannot disable\n", wiphy_name(hw->wiphy)); + wiphy_err(hw->wiphy, "cannot disable\n"); goto err_free_irq; } /* Clear MAC address */ rc = mwl8k_cmd_set_mac_addr(hw, NULL, "\x00\x00\x00\x00\x00\x00"); if (rc) { - printk(KERN_ERR "%s: Cannot clear MAC address\n", - wiphy_name(hw->wiphy)); + wiphy_err(hw->wiphy, "cannot clear mac address\n"); goto err_free_irq; } @@ -4091,17 +4098,16 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, rc = ieee80211_register_hw(hw); if (rc) { - printk(KERN_ERR "%s: Cannot register device\n", - wiphy_name(hw->wiphy)); + wiphy_err(hw->wiphy, "cannot register device\n"); goto err_free_queues; } - printk(KERN_INFO "%s: %s v%d, %pM, %s firmware %u.%u.%u.%u\n", - wiphy_name(hw->wiphy), priv->device_info->part_name, - priv->hw_rev, hw->wiphy->perm_addr, - priv->ap_fw ? "AP" : "STA", - (priv->fw_rev >> 24) & 0xff, (priv->fw_rev >> 16) & 0xff, - (priv->fw_rev >> 8) & 0xff, priv->fw_rev & 0xff); + wiphy_info(hw->wiphy, "%s v%d, %pm, %s firmware %u.%u.%u.%u\n", + priv->device_info->part_name, + priv->hw_rev, hw->wiphy->perm_addr, + priv->ap_fw ? "AP" : "STA", + (priv->fw_rev >> 24) & 0xff, (priv->fw_rev >> 16) & 0xff, + (priv->fw_rev >> 8) & 0xff, priv->fw_rev & 0xff); return 0; diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c index 8c4169c227a..09fae2f0ea0 100644 --- a/drivers/net/wireless/orinoco/cfg.c +++ b/drivers/net/wireless/orinoco/cfg.c @@ -117,9 +117,8 @@ static int orinoco_change_vif(struct wiphy *wiphy, struct net_device *dev, case NL80211_IFTYPE_MONITOR: if (priv->broken_monitor && !force_monitor) { - printk(KERN_WARNING "%s: Monitor mode support is " - "buggy in this firmware, not enabling\n", - wiphy_name(wiphy)); + wiphy_warn(wiphy, + "Monitor mode support is buggy in this firmware, not enabling\n"); err = -EINVAL; } break; diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c index 1558381998e..a38a7bd25f1 100644 --- a/drivers/net/wireless/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/orinoco/orinoco_usb.c @@ -1502,16 +1502,16 @@ static inline void ezusb_delete(struct ezusb_priv *upriv) ezusb_ctx_complete(list_entry(item, struct request_context, list)); - if (upriv->read_urb->status == -EINPROGRESS) + if (upriv->read_urb && upriv->read_urb->status == -EINPROGRESS) printk(KERN_ERR PFX "Some URB in progress\n"); mutex_unlock(&upriv->mtx); - kfree(upriv->read_urb->transfer_buffer); - if (upriv->bap_buf != NULL) - kfree(upriv->bap_buf); - if (upriv->read_urb != NULL) + if (upriv->read_urb) { + kfree(upriv->read_urb->transfer_buffer); usb_free_urb(upriv->read_urb); + } + kfree(upriv->bap_buf); if (upriv->dev) { struct orinoco_private *priv = ndev_priv(upriv->dev); orinoco_if_del(priv); diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index e51650ed49f..d687cb7f2a5 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c @@ -149,16 +149,15 @@ static int p54_generate_band(struct ieee80211_hw *dev, continue; if (list->channels[i].data != CHAN_HAS_ALL) { - printk(KERN_ERR "%s:%s%s%s is/are missing for " - "channel:%d [%d MHz].\n", - wiphy_name(dev->wiphy), - (list->channels[i].data & CHAN_HAS_CAL ? "" : - " [iqauto calibration data]"), - (list->channels[i].data & CHAN_HAS_LIMIT ? "" : - " [output power limits]"), - (list->channels[i].data & CHAN_HAS_CURVE ? "" : - " [curve data]"), - list->channels[i].index, list->channels[i].freq); + wiphy_err(dev->wiphy, + "%s%s%s is/are missing for channel:%d [%d MHz].\n", + (list->channels[i].data & CHAN_HAS_CAL ? "" : + " [iqauto calibration data]"), + (list->channels[i].data & CHAN_HAS_LIMIT ? "" : + " [output power limits]"), + (list->channels[i].data & CHAN_HAS_CURVE ? "" : + " [curve data]"), + list->channels[i].index, list->channels[i].freq); continue; } @@ -168,9 +167,8 @@ static int p54_generate_band(struct ieee80211_hw *dev, } if (j == 0) { - printk(KERN_ERR "%s: Disabling totally damaged %s band.\n", - wiphy_name(dev->wiphy), (band == IEEE80211_BAND_2GHZ) ? - "2 GHz" : "5 GHz"); + wiphy_err(dev->wiphy, "disabling totally damaged %d GHz band\n", + (band == IEEE80211_BAND_2GHZ) ? 2 : 5); ret = -ENODATA; goto err_out; @@ -244,9 +242,9 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev) if ((priv->iq_autocal_len != priv->curve_data->entries) || (priv->iq_autocal_len != priv->output_limit->entries)) - printk(KERN_ERR "%s: Unsupported or damaged EEPROM detected. " - "You may not be able to use all channels.\n", - wiphy_name(dev->wiphy)); + wiphy_err(dev->wiphy, + "Unsupported or damaged EEPROM detected. " + "You may not be able to use all channels.\n"); max_channel_num = max_t(unsigned int, priv->output_limit->entries, priv->iq_autocal_len); @@ -419,15 +417,14 @@ static void p54_parse_rssical(struct ieee80211_hw *dev, void *data, int len, int i; if (len != (entry_size * num_entries)) { - printk(KERN_ERR "%s: unknown rssi calibration data packing " - " type:(%x) len:%d.\n", - wiphy_name(dev->wiphy), type, len); + wiphy_err(dev->wiphy, + "unknown rssi calibration data packing type:(%x) len:%d.\n", + type, len); print_hex_dump_bytes("rssical:", DUMP_PREFIX_NONE, data, len); - printk(KERN_ERR "%s: please report this issue.\n", - wiphy_name(dev->wiphy)); + wiphy_err(dev->wiphy, "please report this issue.\n"); return; } @@ -445,15 +442,14 @@ static void p54_parse_default_country(struct ieee80211_hw *dev, struct pda_country *country; if (len != sizeof(*country)) { - printk(KERN_ERR "%s: found possible invalid default country " - "eeprom entry. (entry size: %d)\n", - wiphy_name(dev->wiphy), len); + wiphy_err(dev->wiphy, + "found possible invalid default country eeprom entry. (entry size: %d)\n", + len); print_hex_dump_bytes("country:", DUMP_PREFIX_NONE, data, len); - printk(KERN_ERR "%s: please report this issue.\n", - wiphy_name(dev->wiphy)); + wiphy_err(dev->wiphy, "please report this issue.\n"); return; } @@ -478,8 +474,8 @@ static int p54_convert_output_limits(struct ieee80211_hw *dev, return -EINVAL; if (data[0] != 0) { - printk(KERN_ERR "%s: unknown output power db revision:%x\n", - wiphy_name(dev->wiphy), data[0]); + wiphy_err(dev->wiphy, "unknown output power db revision:%x\n", + data[0]); return -EINVAL; } @@ -587,10 +583,9 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) err = p54_convert_rev1(dev, curve_data); break; default: - printk(KERN_ERR "%s: unknown curve data " - "revision %d\n", - wiphy_name(dev->wiphy), - curve_data->cal_method_rev); + wiphy_err(dev->wiphy, + "unknown curve data revision %d\n", + curve_data->cal_method_rev); err = -ENODEV; break; } @@ -672,8 +667,8 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) if (!synth || !priv->iq_autocal || !priv->output_limit || !priv->curve_data) { - printk(KERN_ERR "%s: not all required entries found in eeprom!\n", - wiphy_name(dev->wiphy)); + wiphy_err(dev->wiphy, + "not all required entries found in eeprom!\n"); err = -EINVAL; goto err; } @@ -699,15 +694,15 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) if (!is_valid_ether_addr(dev->wiphy->perm_addr)) { u8 perm_addr[ETH_ALEN]; - printk(KERN_WARNING "%s: Invalid hwaddr! Using randomly generated MAC addr\n", - wiphy_name(dev->wiphy)); + wiphy_warn(dev->wiphy, + "invalid hwaddr! using randomly generated mac addr\n"); random_ether_addr(perm_addr); SET_IEEE80211_PERM_ADDR(dev, perm_addr); } - printk(KERN_INFO "%s: hwaddr %pM, MAC:isl38%02x RF:%s\n", - wiphy_name(dev->wiphy), dev->wiphy->perm_addr, priv->version, - p54_rf_chips[priv->rxhw]); + wiphy_info(dev->wiphy, "hwaddr %pm, mac:isl38%02x rf:%s\n", + dev->wiphy->perm_addr, priv->version, + p54_rf_chips[priv->rxhw]); return 0; @@ -719,8 +714,7 @@ err: priv->output_limit = NULL; priv->curve_data = NULL; - printk(KERN_ERR "%s: eeprom parse failed!\n", - wiphy_name(dev->wiphy)); + wiphy_err(dev->wiphy, "eeprom parse failed!\n"); return err; } EXPORT_SYMBOL_GPL(p54_parse_eeprom); diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c index c43a5d461ab..47006bca485 100644 --- a/drivers/net/wireless/p54/fwio.c +++ b/drivers/net/wireless/p54/fwio.c @@ -62,16 +62,15 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) case FW_LM20: case FW_LM87: { char *iftype = (char *)bootrec->data; - printk(KERN_INFO "%s: p54 detected a LM%c%c " - "firmware\n", - wiphy_name(priv->hw->wiphy), - iftype[2], iftype[3]); + wiphy_info(priv->hw->wiphy, + "p54 detected a LM%c%c firmware\n", + iftype[2], iftype[3]); break; } case FW_FMAC: default: - printk(KERN_ERR "%s: unsupported firmware\n", - wiphy_name(priv->hw->wiphy)); + wiphy_err(priv->hw->wiphy, + "unsupported firmware\n"); return -ENODEV; } break; @@ -125,15 +124,15 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) } if (fw_version) - printk(KERN_INFO "%s: FW rev %s - Softmac protocol %x.%x\n", - wiphy_name(priv->hw->wiphy), fw_version, - priv->fw_var >> 8, priv->fw_var & 0xff); + wiphy_info(priv->hw->wiphy, + "fw rev %s - softmac protocol %x.%x\n", + fw_version, priv->fw_var >> 8, priv->fw_var & 0xff); if (priv->fw_var < 0x500) - printk(KERN_INFO "%s: you are using an obsolete firmware. " - "visit http://wireless.kernel.org/en/users/Drivers/p54 " - "and grab one for \"kernel >= 2.6.28\"!\n", - wiphy_name(priv->hw->wiphy)); + wiphy_info(priv->hw->wiphy, + "you are using an obsolete firmware. " + "visit http://wireless.kernel.org/en/users/Drivers/p54 " + "and grab one for \"kernel >= 2.6.28\"!\n"); if (priv->fw_var >= 0x300) { /* Firmware supports QoS, use it! */ @@ -152,13 +151,14 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) priv->hw->queues = P54_QUEUE_AC_NUM; } - printk(KERN_INFO "%s: cryptographic accelerator " - "WEP:%s, TKIP:%s, CCMP:%s\n", wiphy_name(priv->hw->wiphy), - (priv->privacy_caps & BR_DESC_PRIV_CAP_WEP) ? "YES" : - "no", (priv->privacy_caps & (BR_DESC_PRIV_CAP_TKIP | - BR_DESC_PRIV_CAP_MICHAEL)) ? "YES" : "no", - (priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP) ? - "YES" : "no"); + wiphy_info(priv->hw->wiphy, + "cryptographic accelerator WEP:%s, TKIP:%s, CCMP:%s\n", + (priv->privacy_caps & BR_DESC_PRIV_CAP_WEP) ? "YES" : "no", + (priv->privacy_caps & + (BR_DESC_PRIV_CAP_TKIP | BR_DESC_PRIV_CAP_MICHAEL)) + ? "YES" : "no", + (priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP) + ? "YES" : "no"); if (priv->rx_keycache_size) { /* @@ -247,8 +247,7 @@ int p54_download_eeprom(struct p54_common *priv, void *buf, if (!wait_for_completion_interruptible_timeout( &priv->eeprom_comp, HZ)) { - printk(KERN_ERR "%s: device does not respond!\n", - wiphy_name(priv->hw->wiphy)); + wiphy_err(priv->hw->wiphy, "device does not respond!\n"); ret = -EBUSY; } priv->eeprom = NULL; @@ -523,9 +522,9 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell) return 0; err: - printk(KERN_ERR "%s: frequency change to channel %d failed.\n", - wiphy_name(priv->hw->wiphy), ieee80211_frequency_to_channel( - priv->hw->conf.channel->center_freq)); + wiphy_err(priv->hw->wiphy, "frequency change to channel %d failed.\n", + ieee80211_frequency_to_channel( + priv->hw->conf.channel->center_freq)); dev_kfree_skb_any(skb); return -EINVAL; @@ -676,8 +675,8 @@ int p54_upload_key(struct p54_common *priv, u8 algo, int slot, u8 idx, u8 len, break; default: - printk(KERN_ERR "%s: invalid cryptographic algorithm: %d\n", - wiphy_name(priv->hw->wiphy), algo); + wiphy_err(priv->hw->wiphy, + "invalid cryptographic algorithm: %d\n", algo); dev_kfree_skb(skb); return -EINVAL; } diff --git a/drivers/net/wireless/p54/led.c b/drivers/net/wireless/p54/led.c index 9575ac03363..ea91f5cce6b 100644 --- a/drivers/net/wireless/p54/led.c +++ b/drivers/net/wireless/p54/led.c @@ -57,8 +57,8 @@ static void p54_update_leds(struct work_struct *work) err = p54_set_leds(priv); if (err && net_ratelimit()) - printk(KERN_ERR "%s: failed to update LEDs (%d).\n", - wiphy_name(priv->hw->wiphy), err); + wiphy_err(priv->hw->wiphy, + "failed to update leds (%d).\n", err); if (rerun) ieee80211_queue_delayed_work(priv->hw, &priv->led_work, @@ -102,8 +102,8 @@ static int p54_register_led(struct p54_common *priv, err = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_dev); if (err) - printk(KERN_ERR "%s: Failed to register %s LED.\n", - wiphy_name(priv->hw->wiphy), name); + wiphy_err(priv->hw->wiphy, + "failed to register %s led.\n", name); else led->registered = 1; diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index c072f41747c..47db439b63b 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c @@ -507,6 +507,22 @@ out_unlock: return ret; } +static int p54_get_survey(struct ieee80211_hw *dev, int idx, + struct survey_info *survey) +{ + struct p54_common *priv = dev->priv; + struct ieee80211_conf *conf = &dev->conf; + + if (idx != 0) + return -ENOENT; + + survey->channel = conf->channel; + survey->filled = SURVEY_INFO_NOISE_DBM; + survey->noise = clamp_t(s8, priv->noise, -128, 127); + + return 0; +} + static const struct ieee80211_ops p54_ops = { .tx = p54_tx_80211, .start = p54_start, @@ -523,6 +539,7 @@ static const struct ieee80211_ops p54_ops = { .configure_filter = p54_configure_filter, .conf_tx = p54_conf_tx, .get_stats = p54_get_stats, + .get_survey = p54_get_survey, }; struct ieee80211_hw *p54_init_common(size_t priv_data_len) diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index a5ea89cde8c..822f8dc26e9 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -466,8 +466,7 @@ static int p54p_open(struct ieee80211_hw *dev) P54P_READ(dev_int); if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) { - printk(KERN_ERR "%s: Cannot boot firmware!\n", - wiphy_name(dev->wiphy)); + wiphy_err(dev->wiphy, "cannot boot firmware!\n"); p54p_stop(dev); return -ETIMEDOUT; } diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 4e6891099d4..427b46f558e 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -38,8 +38,8 @@ static void p54_dump_tx_queue(struct p54_common *priv) u32 largest_hole = 0, free; spin_lock_irqsave(&priv->tx_queue.lock, flags); - printk(KERN_DEBUG "%s: / --- tx queue dump (%d entries) ---\n", - wiphy_name(priv->hw->wiphy), skb_queue_len(&priv->tx_queue)); + wiphy_debug(priv->hw->wiphy, "/ --- tx queue dump (%d entries) ---\n", + skb_queue_len(&priv->tx_queue)); prev_addr = priv->rx_start; skb_queue_walk(&priv->tx_queue, skb) { @@ -48,21 +48,23 @@ static void p54_dump_tx_queue(struct p54_common *priv) hdr = (void *) skb->data; free = range->start_addr - prev_addr; - printk(KERN_DEBUG "%s: | [%02d] => [skb:%p skb_len:0x%04x " - "hdr:{flags:%02x len:%04x req_id:%04x type:%02x} " - "mem:{start:%04x end:%04x, free:%d}]\n", - wiphy_name(priv->hw->wiphy), i++, skb, skb->len, - le16_to_cpu(hdr->flags), le16_to_cpu(hdr->len), - le32_to_cpu(hdr->req_id), le16_to_cpu(hdr->type), - range->start_addr, range->end_addr, free); + wiphy_debug(priv->hw->wiphy, + "| [%02d] => [skb:%p skb_len:0x%04x " + "hdr:{flags:%02x len:%04x req_id:%04x type:%02x} " + "mem:{start:%04x end:%04x, free:%d}]\n", + i++, skb, skb->len, + le16_to_cpu(hdr->flags), le16_to_cpu(hdr->len), + le32_to_cpu(hdr->req_id), le16_to_cpu(hdr->type), + range->start_addr, range->end_addr, free); prev_addr = range->end_addr; largest_hole = max(largest_hole, free); } free = priv->rx_end - prev_addr; largest_hole = max(largest_hole, free); - printk(KERN_DEBUG "%s: \\ --- [free: %d], largest free block: %d ---\n", - wiphy_name(priv->hw->wiphy), free, largest_hole); + wiphy_debug(priv->hw->wiphy, + "\\ --- [free: %d], largest free block: %d ---\n", + free, largest_hole); spin_unlock_irqrestore(&priv->tx_queue.lock, flags); } #endif /* P54_MM_DEBUG */ @@ -538,8 +540,7 @@ static void p54_rx_trap(struct p54_common *priv, struct sk_buff *skb) case P54_TRAP_BEACON_TX: break; case P54_TRAP_RADAR: - printk(KERN_INFO "%s: radar (freq:%d MHz)\n", - wiphy_name(priv->hw->wiphy), freq); + wiphy_info(priv->hw->wiphy, "radar (freq:%d mhz)\n", freq); break; case P54_TRAP_NO_BEACON: if (priv->vif) @@ -558,8 +559,8 @@ static void p54_rx_trap(struct p54_common *priv, struct sk_buff *skb) wiphy_rfkill_set_hw_state(priv->hw->wiphy, false); break; default: - printk(KERN_INFO "%s: received event:%x freq:%d\n", - wiphy_name(priv->hw->wiphy), event, freq); + wiphy_info(priv->hw->wiphy, "received event:%x freq:%d\n", + event, freq); break; } } @@ -584,8 +585,9 @@ static int p54_rx_control(struct p54_common *priv, struct sk_buff *skb) p54_rx_eeprom_readback(priv, skb); break; default: - printk(KERN_DEBUG "%s: not handling 0x%02x type control frame\n", - wiphy_name(priv->hw->wiphy), le16_to_cpu(hdr->type)); + wiphy_debug(priv->hw->wiphy, + "not handling 0x%02x type control frame\n", + le16_to_cpu(hdr->type)); break; } return 0; diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index abff8934db1..9c38fc331dc 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -97,7 +97,6 @@ static iw_stats *ray_get_wireless_stats(struct net_device *dev); static const struct iw_handler_def ray_handler_def; /***** Prototypes for raylink functions **************************************/ -static int asc_to_int(char a); static void authenticate(ray_dev_t *local); static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type); static void authenticate_timeout(u_long); @@ -1717,24 +1716,6 @@ static void authenticate_timeout(u_long data) } /*===========================================================================*/ -static int asc_to_int(char a) -{ - if (a < '0') - return -1; - if (a <= '9') - return (a - '0'); - if (a < 'A') - return -1; - if (a <= 'F') - return (10 + a - 'A'); - if (a < 'a') - return -1; - if (a <= 'f') - return (10 + a - 'a'); - return -1; -} - -/*===========================================================================*/ static int parse_addr(char *in_str, UCHAR *out) { int len; @@ -1754,14 +1735,14 @@ static int parse_addr(char *in_str, UCHAR *out) i = 5; while (j > 0) { - if ((k = asc_to_int(in_str[j--])) != -1) + if ((k = hex_to_bin(in_str[j--])) != -1) out[i] = k; else return 0; if (j == 0) break; - if ((k = asc_to_int(in_str[j--])) != -1) + if ((k = hex_to_bin(in_str[j--])) != -1) out[i] += k << 4; else return 0; diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 242d59558b7..cdaf93f4826 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -351,6 +351,14 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, if (crypto->cmd == SET_KEY) { /* + * Disallow to set WEP key other than with index 0, + * it is known that not work at least on some hardware. + * SW crypto will be used in that case. + */ + if (key->alg == ALG_WEP && key->keyidx != 0) + return -EOPNOTSUPP; + + /* * Pairwise key will always be entry 0, but this * could collide with a shared key on the same * position... @@ -376,7 +384,7 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, if (key->hw_key_idx > 0 && crypto->cipher != curr_cipher) return -EOPNOTSUPP; - rt2500usb_register_multiwrite(rt2x00dev, reg, + rt2500usb_register_multiwrite(rt2x00dev, KEY_ENTRY(key->hw_key_idx), crypto->key, sizeof(crypto->key)); /* @@ -817,6 +825,7 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) rt2500usb_register_write(rt2x00dev, MAC_CSR8, reg); rt2500usb_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field16(®, TXRX_CSR0_ALGORITHM, CIPHER_NONE); rt2x00_set_field16(®, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER); rt2x00_set_field16(®, TXRX_CSR0_KEY_ID, 0); rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg); diff --git a/drivers/net/wireless/rt2x00/rt2x00dump.h b/drivers/net/wireless/rt2x00/rt2x00dump.h index 6df2e0b746b..5d6e0b83151 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dump.h +++ b/drivers/net/wireless/rt2x00/rt2x00dump.h @@ -116,7 +116,7 @@ struct rt2x00dump_hdr { __le16 chip_rt; __le16 chip_rf; - __le32 chip_rev; + __le16 chip_rev; __le16 type; __u8 queue_index; diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 4d8d2320c9f..235e037e650 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -273,17 +273,24 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, mutex_init(&intf->beacon_skb_mutex); intf->beacon = entry; - if (vif->type == NL80211_IFTYPE_AP) - memcpy(&intf->bssid, vif->addr, ETH_ALEN); - memcpy(&intf->mac, vif->addr, ETH_ALEN); - /* * The MAC adddress must be configured after the device * has been initialized. Otherwise the device can reset * the MAC registers. + * The BSSID address must only be configured in AP mode, + * however we should not send an empty BSSID address for + * STA interfaces at this time, since this can cause + * invalid behavior in the device. */ - rt2x00lib_config_intf(rt2x00dev, intf, vif->type, - intf->mac, intf->bssid); + memcpy(&intf->mac, vif->addr, ETH_ALEN); + if (vif->type == NL80211_IFTYPE_AP) { + memcpy(&intf->bssid, vif->addr, ETH_ALEN); + rt2x00lib_config_intf(rt2x00dev, intf, vif->type, + intf->mac, intf->bssid); + } else { + rt2x00lib_config_intf(rt2x00dev, intf, vif->type, + intf->mac, NULL); + } /* * Some filters depend on the current working mode. We can force diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 42705028751..1d8178563d7 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -103,6 +103,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) { struct rtl8180_priv *priv = dev->priv; unsigned int count = 32; + u8 signal, agc, sq; while (count--) { struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx]; @@ -130,10 +131,18 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) skb_put(skb, flags & 0xFFF); rx_status.antenna = (flags2 >> 15) & 1; - /* TODO: improve signal/rssi reporting */ - rx_status.signal = (flags2 >> 8) & 0x7F; - /* XXX: is this correct? */ rx_status.rate_idx = (flags >> 20) & 0xF; + agc = (flags2 >> 17) & 0x7F; + if (priv->r8185) { + if (rx_status.rate_idx > 3) + signal = 90 - clamp_t(u8, agc, 25, 90); + else + signal = 95 - clamp_t(u8, agc, 30, 95); + } else { + sq = flags2 & 0xff; + signal = priv->rf->calc_rssi(agc, sq); + } + rx_status.signal = signal; rx_status.freq = dev->conf.channel->center_freq; rx_status.band = dev->conf.channel->band; rx_status.mactime = le64_to_cpu(entry->tsft); @@ -352,7 +361,7 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev) /* check success of reset */ if (rtl818x_ioread8(priv, &priv->map->CMD) & RTL818X_CMD_RESET) { - printk(KERN_ERR "%s: reset timeout!\n", wiphy_name(dev->wiphy)); + wiphy_err(dev->wiphy, "reset timeout!\n"); return -ETIMEDOUT; } @@ -436,8 +445,7 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev) &priv->rx_ring_dma); if (!priv->rx_ring || (unsigned long)priv->rx_ring & 0xFF) { - printk(KERN_ERR "%s: Cannot allocate RX ring\n", - wiphy_name(dev->wiphy)); + wiphy_err(dev->wiphy, "cannot allocate rx ring\n"); return -ENOMEM; } @@ -494,8 +502,8 @@ static int rtl8180_init_tx_ring(struct ieee80211_hw *dev, ring = pci_alloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma); if (!ring || (unsigned long)ring & 0xFF) { - printk(KERN_ERR "%s: Cannot allocate TX ring (prio = %d)\n", - wiphy_name(dev->wiphy), prio); + wiphy_err(dev->wiphy, "cannot allocate tx ring (prio = %d)\n", + prio); return -ENOMEM; } @@ -560,8 +568,7 @@ static int rtl8180_start(struct ieee80211_hw *dev) ret = request_irq(priv->pdev->irq, rtl8180_interrupt, IRQF_SHARED, KBUILD_MODNAME, dev); if (ret) { - printk(KERN_ERR "%s: failed to register IRQ handler\n", - wiphy_name(dev->wiphy)); + wiphy_err(dev->wiphy, "failed to register irq handler\n"); goto err_free_rings; } @@ -1098,9 +1105,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, goto err_iounmap; } - printk(KERN_INFO "%s: hwaddr %pM, %s + %s\n", - wiphy_name(dev->wiphy), mac_addr, - chip_name, priv->rf->name); + wiphy_info(dev->wiphy, "hwaddr %pm, %s + %s\n", + mac_addr, chip_name, priv->rf->name); return 0; diff --git a/drivers/net/wireless/rtl818x/rtl8180_grf5101.c b/drivers/net/wireless/rtl818x/rtl8180_grf5101.c index 947ee55f18b..5cab9dfa8c0 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_grf5101.c +++ b/drivers/net/wireless/rtl818x/rtl8180_grf5101.c @@ -69,6 +69,15 @@ static void grf5101_write_phy_antenna(struct ieee80211_hw *dev, short chan) rtl8180_write_phy(dev, 0x10, ant); } +static u8 grf5101_rf_calc_rssi(u8 agc, u8 sq) +{ + if (agc > 60) + return 65; + + /* TODO(?): just return agc (or agc + 5) to avoid mult / div */ + return 65 * agc / 60; +} + static void grf5101_rf_set_channel(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { @@ -176,5 +185,6 @@ const struct rtl818x_rf_ops grf5101_rf_ops = { .name = "GCT", .init = grf5101_rf_init, .stop = grf5101_rf_stop, - .set_chan = grf5101_rf_set_channel + .set_chan = grf5101_rf_set_channel, + .calc_rssi = grf5101_rf_calc_rssi, }; diff --git a/drivers/net/wireless/rtl818x/rtl8180_max2820.c b/drivers/net/wireless/rtl818x/rtl8180_max2820.c index 6c825fd7f3b..16c4655181c 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_max2820.c +++ b/drivers/net/wireless/rtl818x/rtl8180_max2820.c @@ -74,6 +74,22 @@ static void max2820_write_phy_antenna(struct ieee80211_hw *dev, short chan) rtl8180_write_phy(dev, 0x10, ant); } +static u8 max2820_rf_calc_rssi(u8 agc, u8 sq) +{ + bool odd; + + odd = !!(agc & 1); + + agc >>= 1; + if (odd) + agc += 76; + else + agc += 66; + + /* TODO: change addends above to avoid mult / div below */ + return 65 * agc / 100; +} + static void max2820_rf_set_channel(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { @@ -148,5 +164,6 @@ const struct rtl818x_rf_ops max2820_rf_ops = { .name = "Maxim", .init = max2820_rf_init, .stop = max2820_rf_stop, - .set_chan = max2820_rf_set_channel + .set_chan = max2820_rf_set_channel, + .calc_rssi = max2820_rf_calc_rssi, }; diff --git a/drivers/net/wireless/rtl818x/rtl8180_rtl8225.c b/drivers/net/wireless/rtl818x/rtl8180_rtl8225.c index 4d2be0d9672..69e4d4745da 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_rtl8225.c +++ b/drivers/net/wireless/rtl818x/rtl8180_rtl8225.c @@ -50,7 +50,10 @@ static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data) udelay(10); for (i = 15; i >= 0; i--) { - u16 reg = reg80 | !!(bangdata & (1 << i)); + u16 reg = reg80; + + if (bangdata & (1 << i)) + reg |= 1; if (i & 1) rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); diff --git a/drivers/net/wireless/rtl818x/rtl8180_sa2400.c b/drivers/net/wireless/rtl818x/rtl8180_sa2400.c index cea4e0ccb92..d064fcc5ec0 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_sa2400.c +++ b/drivers/net/wireless/rtl818x/rtl8180_sa2400.c @@ -76,6 +76,31 @@ static void sa2400_write_phy_antenna(struct ieee80211_hw *dev, short chan) } +static u8 sa2400_rf_rssi_map[] = { + 0x64, 0x64, 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, + 0x5d, 0x5c, 0x5b, 0x5a, 0x57, 0x54, 0x52, 0x50, + 0x4e, 0x4c, 0x4a, 0x48, 0x46, 0x44, 0x41, 0x3f, + 0x3c, 0x3a, 0x37, 0x36, 0x36, 0x1c, 0x1c, 0x1b, + 0x1b, 0x1a, 0x1a, 0x19, 0x19, 0x18, 0x18, 0x17, + 0x17, 0x16, 0x16, 0x15, 0x15, 0x14, 0x14, 0x13, + 0x13, 0x12, 0x12, 0x11, 0x11, 0x10, 0x10, 0x0f, + 0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b, + 0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07, + 0x07, 0x06, 0x06, 0x05, 0x04, 0x03, 0x02, +}; + +static u8 sa2400_rf_calc_rssi(u8 agc, u8 sq) +{ + if (sq == 0x80) + return 1; + + if (sq > 78) + return 32; + + /* TODO: recalc sa2400_rf_rssi_map to avoid mult / div */ + return 65 * sa2400_rf_rssi_map[sq] / 100; +} + static void sa2400_rf_set_channel(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { @@ -198,5 +223,6 @@ const struct rtl818x_rf_ops sa2400_rf_ops = { .name = "Philips", .init = sa2400_rf_init, .stop = sa2400_rf_stop, - .set_chan = sa2400_rf_set_channel + .set_chan = sa2400_rf_set_channel, + .calc_rssi = sa2400_rf_calc_rssi, }; diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 891b8490e34..5738a55c1b0 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -573,7 +573,7 @@ static int rtl8187_cmd_reset(struct ieee80211_hw *dev) } while (--i); if (!i) { - printk(KERN_ERR "%s: Reset timeout!\n", wiphy_name(dev->wiphy)); + wiphy_err(dev->wiphy, "reset timeout!\n"); return -ETIMEDOUT; } @@ -589,8 +589,7 @@ static int rtl8187_cmd_reset(struct ieee80211_hw *dev) } while (--i); if (!i) { - printk(KERN_ERR "%s: eeprom reset timeout!\n", - wiphy_name(dev->wiphy)); + wiphy_err(dev->wiphy, "eeprom reset timeout!\n"); return -ETIMEDOUT; } @@ -1527,9 +1526,9 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, mutex_init(&priv->conf_mutex); skb_queue_head_init(&priv->b_tx_status.queue); - printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s, rfkill mask %d\n", - wiphy_name(dev->wiphy), mac_addr, - chip_name, priv->asic_rev, priv->rf->name, priv->rfkill_mask); + wiphy_info(dev->wiphy, "hwaddr %pm, %s v%d + %s, rfkill mask %d\n", + mac_addr, chip_name, priv->asic_rev, priv->rf->name, + priv->rfkill_mask); #ifdef CONFIG_RTL8187_LEDS eeprom_93cx6_read(&eeprom, 0x3F, ®); diff --git a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c index a09819386a1..fd96f911232 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c +++ b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c @@ -366,8 +366,8 @@ static void rtl8225_rf_init(struct ieee80211_hw *dev) rtl8225_write(dev, 0x02, 0x044d); msleep(100); if (!(rtl8225_read(dev, 6) & (1 << 7))) - printk(KERN_WARNING "%s: RF Calibration Failed! %x\n", - wiphy_name(dev->wiphy), rtl8225_read(dev, 6)); + wiphy_warn(dev->wiphy, "rf calibration failed! %x\n", + rtl8225_read(dev, 6)); } rtl8225_write(dev, 0x0, 0x127); @@ -735,8 +735,8 @@ static void rtl8225z2_rf_init(struct ieee80211_hw *dev) rtl8225_write(dev, 0x02, 0x044D); msleep(100); if (!(rtl8225_read(dev, 6) & (1 << 7))) - printk(KERN_WARNING "%s: RF Calibration Failed! %x\n", - wiphy_name(dev->wiphy), rtl8225_read(dev, 6)); + wiphy_warn(dev->wiphy, "rf calibration failed! %x\n", + rtl8225_read(dev, 6)); } msleep(200); diff --git a/drivers/net/wireless/rtl818x/rtl818x.h b/drivers/net/wireless/rtl818x/rtl818x.h index 978519d1ff4..1615f63b02f 100644 --- a/drivers/net/wireless/rtl818x/rtl818x.h +++ b/drivers/net/wireless/rtl818x/rtl818x.h @@ -193,6 +193,7 @@ struct rtl818x_rf_ops { void (*stop)(struct ieee80211_hw *); void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *); void (*conf_erp)(struct ieee80211_hw *, struct ieee80211_bss_conf *); + u8 (*calc_rssi)(u8 agc, u8 sq); }; /** diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h index 4f5f02a26e6..6b942a28e6a 100644 --- a/drivers/net/wireless/wl12xx/wl1251.h +++ b/drivers/net/wireless/wl12xx/wl1251.h @@ -381,6 +381,9 @@ struct wl1251 { u32 chip_id; char fw_ver[21]; + + /* Most recently reported noise in dBm */ + s8 noise; }; int wl1251_plt_start(struct wl1251 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c index 2545123931e..65e0416be5b 100644 --- a/drivers/net/wireless/wl12xx/wl1251_boot.c +++ b/drivers/net/wireless/wl12xx/wl1251_boot.c @@ -225,7 +225,7 @@ static void wl1251_boot_set_ecpu_ctrl(struct wl1251 *wl, u32 flag) int wl1251_boot_run_firmware(struct wl1251 *wl) { int loop, ret; - u32 chip_id, interrupt; + u32 chip_id, acx_intr; wl1251_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); @@ -242,15 +242,15 @@ int wl1251_boot_run_firmware(struct wl1251 *wl) loop = 0; while (loop++ < INIT_LOOP) { udelay(INIT_LOOP_DELAY); - interrupt = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); + acx_intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); - if (interrupt == 0xffffffff) { + if (acx_intr == 0xffffffff) { wl1251_error("error reading hardware complete " "init indication"); return -EIO; } /* check that ACX_INTR_INIT_COMPLETE is enabled */ - else if (interrupt & WL1251_ACX_INTR_INIT_COMPLETE) { + else if (acx_intr & WL1251_ACX_INTR_INIT_COMPLETE) { wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK, WL1251_ACX_INTR_INIT_COMPLETE); break; diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.h b/drivers/net/wireless/wl12xx/wl1251_cmd.h index 7e70dd5a21b..a9e4991369b 100644 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1251_cmd.h @@ -175,8 +175,8 @@ struct cmd_read_write_memory { #define WL1251_SCAN_NUM_PROBES 3 struct wl1251_scan_parameters { - u32 rx_config_options; - u32 rx_filter_options; + __le32 rx_config_options; + __le32 rx_filter_options; /* * Scan options: @@ -186,7 +186,7 @@ struct wl1251_scan_parameters { * bit 2: voice mode, 0 for normal scan. * bit 3: scan priority, 1 for high priority. */ - u16 scan_options; + __le16 scan_options; /* Number of channels to scan */ u8 num_channels; @@ -195,7 +195,7 @@ struct wl1251_scan_parameters { u8 num_probe_requests; /* Rate and modulation for probe requests */ - u16 tx_rate; + __le16 tx_rate; u8 tid_trigger; u8 ssid_len; @@ -204,8 +204,8 @@ struct wl1251_scan_parameters { } __packed; struct wl1251_scan_ch_parameters { - u32 min_duration; /* in TU */ - u32 max_duration; /* in TU */ + __le32 min_duration; /* in TU */ + __le32 max_duration; /* in TU */ u32 bssid_lsb; u16 bssid_msb; diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 38f72f41718..861a5f33761 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -411,6 +411,7 @@ static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) static int wl1251_op_start(struct ieee80211_hw *hw) { struct wl1251 *wl = hw->priv; + struct wiphy *wiphy = hw->wiphy; int ret = 0; wl1251_debug(DEBUG_MAC80211, "mac80211 start"); @@ -444,6 +445,10 @@ static int wl1251_op_start(struct ieee80211_hw *hw) wl1251_info("firmware booted (%s)", wl->fw_ver); + /* update hw/fw version info in wiphy struct */ + wiphy->hw_version = wl->chip_id; + strncpy(wiphy->fw_version, wl->fw_ver, sizeof(wiphy->fw_version)); + out: if (ret < 0) wl1251_power_off(wl); @@ -1172,6 +1177,22 @@ out: return ret; } +static int wl1251_op_get_survey(struct ieee80211_hw *hw, int idx, + struct survey_info *survey) +{ + struct wl1251 *wl = hw->priv; + struct ieee80211_conf *conf = &hw->conf; + + if (idx != 0) + return -ENOENT; + + survey->channel = conf->channel; + survey->filled = SURVEY_INFO_NOISE_DBM; + survey->noise = wl->noise; + + return 0; +} + /* can't be const, mac80211 writes to this */ static struct ieee80211_supported_band wl1251_band_2ghz = { .channels = wl1251_channels, @@ -1193,6 +1214,7 @@ static const struct ieee80211_ops wl1251_ops = { .bss_info_changed = wl1251_op_bss_info_changed, .set_rts_threshold = wl1251_op_set_rts_threshold, .conf_tx = wl1251_op_conf_tx, + .get_survey = wl1251_op_get_survey, }; static int wl1251_read_eeprom_byte(struct wl1251 *wl, off_t offset, u8 *data) diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.c b/drivers/net/wireless/wl12xx/wl1251_rx.c index 851515836a7..1b6294b3b99 100644 --- a/drivers/net/wireless/wl12xx/wl1251_rx.c +++ b/drivers/net/wireless/wl12xx/wl1251_rx.c @@ -74,6 +74,12 @@ static void wl1251_rx_status(struct wl1251 *wl, status->signal = desc->rssi; + /* + * FIXME: guessing that snr needs to be divided by two, otherwise + * the values don't make any sense + */ + wl->noise = desc->rssi - desc->snr / 2; + status->freq = ieee80211_channel_to_frequency(desc->channel); status->flag |= RX_FLAG_TSFT; diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl12xx/wl1251_tx.c index c8223185efd..a38ec199187 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.c +++ b/drivers/net/wireless/wl12xx/wl1251_tx.c @@ -117,7 +117,7 @@ static void wl1251_tx_frag_block_num(struct tx_double_buffer_desc *tx_hdr) frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD; tx_hdr->frag_threshold = cpu_to_le16(frag_threshold); - payload_len = tx_hdr->length + MAX_MSDU_SECURITY_LENGTH; + payload_len = le16_to_cpu(tx_hdr->length) + MAX_MSDU_SECURITY_LENGTH; if (payload_len > frag_threshold) { mem_blocks_per_frag = @@ -191,11 +191,13 @@ static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb, if (control->control.hw_key && control->control.hw_key->alg == ALG_TKIP) { int hdrlen; - u16 fc; + __le16 fc; + u16 length; u8 *pos; - fc = *(u16 *)(skb->data + sizeof(*tx_hdr)); - tx_hdr->length += WL1251_TKIP_IV_SPACE; + fc = *(__le16 *)(skb->data + sizeof(*tx_hdr)); + length = le16_to_cpu(tx_hdr->length) + WL1251_TKIP_IV_SPACE; + tx_hdr->length = cpu_to_le16(length); hdrlen = ieee80211_hdrlen(fc); diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.h b/drivers/net/wireless/wl12xx/wl1251_tx.h index 65c4be8c2e8..f40eeb37f5a 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.h +++ b/drivers/net/wireless/wl12xx/wl1251_tx.h @@ -114,7 +114,7 @@ struct tx_control { struct tx_double_buffer_desc { /* Length of payload, including headers. */ - u16 length; + __le16 length; /* * A bit mask that specifies the initial rate to be used @@ -133,10 +133,10 @@ struct tx_double_buffer_desc { * 0x0800 - 48Mbits * 0x1000 - 54Mbits */ - u16 rate; + __le16 rate; /* Time in us that a packet can spend in the target */ - u32 expiry_time; + __le32 expiry_time; /* index of the TX queue used for this packet */ u8 xmit_queue; @@ -150,7 +150,7 @@ struct tx_double_buffer_desc { * The FW should cut the packet into fragments * of this size. */ - u16 frag_threshold; + __le16 frag_threshold; /* Numbers of HW queue blocks to be allocated */ u8 num_mem_blocks; diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 53d47d7a2a1..dd3cee6ea5b 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -475,6 +475,9 @@ struct wl1271 { bool sg_enabled; struct list_head list; + + /* Most recently reported noise in dBm */ + s8 noise; }; int wl1271_plt_start(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index d30de58cef9..9d68f0012f0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -576,7 +576,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) goto out; } - wl->nvs = kzalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL); + wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL); if (!wl->nvs) { wl1271_error("could not allocate memory for the nvs file"); @@ -584,8 +584,6 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) goto out; } - memcpy(wl->nvs, fw->data, fw->size); - out: release_firmware(fw); @@ -841,6 +839,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct wl1271 *wl = hw->priv; + struct wiphy *wiphy = hw->wiphy; int retries = WL1271_BOOT_RETRIES; int ret = 0; @@ -894,6 +893,12 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, wl->state = WL1271_STATE_ON; wl1271_info("firmware booted (%s)", wl->chip.fw_ver); + + /* update hw/fw version info in wiphy struct */ + wiphy->hw_version = wl->chip.id; + strncpy(wiphy->fw_version, wl->chip.fw_ver, + sizeof(wiphy->fw_version)); + goto out; irq_disable: @@ -1929,6 +1934,22 @@ out: return mactime; } +static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx, + struct survey_info *survey) +{ + struct wl1271 *wl = hw->priv; + struct ieee80211_conf *conf = &hw->conf; + + if (idx != 0) + return -ENOENT; + + survey->channel = conf->channel; + survey->filled = SURVEY_INFO_NOISE_DBM; + survey->noise = wl->noise; + + return 0; +} + /* can't be const, mac80211 writes to this */ static struct ieee80211_rate wl1271_rates[] = { { .bitrate = 10, @@ -2158,6 +2179,7 @@ static const struct ieee80211_ops wl1271_ops = { .set_rts_threshold = wl1271_op_set_rts_threshold, .conf_tx = wl1271_op_conf_tx, .get_tsf = wl1271_op_get_tsf, + .get_survey = wl1271_op_get_survey, CFG80211_TESTMODE_CMD(wl1271_tm_cmd) }; @@ -2350,15 +2372,13 @@ struct ieee80211_hw *wl1271_alloc_hw(void) goto err_hw_alloc; } - plat_dev = kmalloc(sizeof(wl1271_device), GFP_KERNEL); + plat_dev = kmemdup(&wl1271_device, sizeof(wl1271_device), GFP_KERNEL); if (!plat_dev) { wl1271_error("could not allocate platform_device"); ret = -ENOMEM; goto err_plat_alloc; } - memcpy(plat_dev, &wl1271_device, sizeof(wl1271_device)); - wl = hw->priv; memset(wl, 0, sizeof(*wl)); diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index e98f22b3c3b..019aa79cd9d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c @@ -55,6 +55,13 @@ static void wl1271_rx_status(struct wl1271 *wl, status->signal = desc->rssi; + /* + * FIXME: In wl1251, the SNR should be divided by two. In wl1271 we + * need to divide by two for now, but TI has been discussing about + * changing it. This needs to be rechecked. + */ + wl->noise = desc->rssi - (desc->snr >> 1); + status->freq = ieee80211_channel_to_frequency(desc->channel); if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index 147bb1a69ab..a75ed3083a6 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -295,7 +295,7 @@ claw_driver_group_store(struct device_driver *ddrv, const char *buf, int err; err = ccwgroup_create_from_string(claw_root_dev, claw_group_driver.driver_id, - &claw_ccw_driver, 3, buf); + &claw_ccw_driver, 2, buf); return err ? err : count; } diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index d79892782a2..d1257768be9 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -188,8 +188,7 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, qeth_is_enabled6(c, f) : qeth_is_enabled(c, f)) #define QETH_IDX_FUNC_LEVEL_OSD 0x0101 -#define QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT 0x4108 -#define QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT 0x5108 +#define QETH_IDX_FUNC_LEVEL_IQD 0x4108 #define QETH_MODELLIST_ARRAY \ {{0x1731, 0x01, 0x1732, QETH_CARD_TYPE_OSD, QETH_MAX_QUEUES, 0}, \ @@ -741,6 +740,7 @@ struct qeth_card { struct qeth_qdio_info qdio; struct qeth_perf_stats perf_stats; int use_hard_stop; + int read_or_write_problem; struct qeth_osn_info osn_info; struct qeth_discipline discipline; atomic_t force_alloc_skb; @@ -748,6 +748,7 @@ struct qeth_card { struct qdio_ssqd_desc ssqd; debug_info_t *debug; struct mutex conf_mutex; + struct mutex discipline_mutex; }; struct qeth_card_list_struct { diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index b7019066c30..3a5a18a0fc2 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -262,6 +262,7 @@ static int qeth_issue_next_read(struct qeth_card *card) QETH_DBF_MESSAGE(2, "%s error in starting next read ccw! " "rc=%i\n", dev_name(&card->gdev->dev), rc); atomic_set(&card->read.irq_pending, 0); + card->read_or_write_problem = 1; qeth_schedule_recovery(card); wake_up(&card->wait_q); } @@ -382,6 +383,7 @@ void qeth_clear_ipacmd_list(struct qeth_card *card) qeth_put_reply(reply); } spin_unlock_irqrestore(&card->lock, flags); + atomic_set(&card->write.irq_pending, 0); } EXPORT_SYMBOL_GPL(qeth_clear_ipacmd_list); @@ -1076,6 +1078,7 @@ static int qeth_setup_card(struct qeth_card *card) card->state = CARD_STATE_DOWN; card->lan_online = 0; card->use_hard_stop = 0; + card->read_or_write_problem = 0; card->dev = NULL; spin_lock_init(&card->vlanlock); spin_lock_init(&card->mclock); @@ -1084,6 +1087,7 @@ static int qeth_setup_card(struct qeth_card *card) spin_lock_init(&card->ip_lock); spin_lock_init(&card->thread_mask_lock); mutex_init(&card->conf_mutex); + mutex_init(&card->discipline_mutex); card->thread_start_mask = 0; card->thread_allowed_mask = 0; card->thread_running_mask = 0; @@ -1383,12 +1387,7 @@ static void qeth_init_func_level(struct qeth_card *card) { switch (card->info.type) { case QETH_CARD_TYPE_IQD: - if (card->ipato.enabled) - card->info.func_level = - QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT; - else - card->info.func_level = - QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT; + card->info.func_level = QETH_IDX_FUNC_LEVEL_IQD; break; case QETH_CARD_TYPE_OSD: case QETH_CARD_TYPE_OSN: @@ -1662,6 +1661,10 @@ int qeth_send_control_data(struct qeth_card *card, int len, QETH_CARD_TEXT(card, 2, "sendctl"); + if (card->read_or_write_problem) { + qeth_release_buffer(iob->channel, iob); + return -EIO; + } reply = qeth_alloc_reply(card); if (!reply) { return -ENOMEM; @@ -1733,6 +1736,9 @@ time_err: spin_unlock_irqrestore(&reply->card->lock, flags); reply->rc = -ETIME; atomic_inc(&reply->received); + atomic_set(&card->write.irq_pending, 0); + qeth_release_buffer(iob->channel, iob); + card->write.buf_no = (card->write.buf_no + 1) % QETH_CMD_BUFFER_NO; wake_up(&reply->wait_q); rc = reply->rc; qeth_put_reply(reply); @@ -1990,7 +1996,7 @@ static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply, QETH_DBF_TEXT(SETUP, 2, "olmlimit"); dev_err(&card->gdev->dev, "A connection could not be " "established because of an OLM limit\n"); - rc = -EMLINK; + iob->rc = -EMLINK; } QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc); return rc; @@ -2489,6 +2495,10 @@ int qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, qeth_prepare_ipa_cmd(card, iob, prot_type); rc = qeth_send_control_data(card, IPA_CMD_LENGTH, iob, reply_cb, reply_param); + if (rc == -ETIME) { + qeth_clear_ipacmd_list(card); + qeth_schedule_recovery(card); + } return rc; } EXPORT_SYMBOL_GPL(qeth_send_ipa_cmd); @@ -3413,7 +3423,6 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card, { struct qeth_ipa_cmd *cmd; struct qeth_set_access_ctrl *access_ctrl_req; - int rc; QETH_CARD_TEXT(card, 4, "setaccb"); @@ -3440,7 +3449,6 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card, card->gdev->dev.kobj.name, access_ctrl_req->subcmd_code, cmd->data.setadapterparms.hdr.return_code); - rc = 0; break; } case SET_ACCESS_CTRL_RC_NOT_SUPPORTED: @@ -3454,7 +3462,6 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card, /* ensure isolation mode is "none" */ card->options.isolation = ISOLATION_MODE_NONE; - rc = -EOPNOTSUPP; break; } case SET_ACCESS_CTRL_RC_NONE_SHARED_ADAPTER: @@ -3469,7 +3476,6 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card, /* ensure isolation mode is "none" */ card->options.isolation = ISOLATION_MODE_NONE; - rc = -EOPNOTSUPP; break; } case SET_ACCESS_CTRL_RC_ACTIVE_CHECKSUM_OFF: @@ -3483,7 +3489,6 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card, /* ensure isolation mode is "none" */ card->options.isolation = ISOLATION_MODE_NONE; - rc = -EPERM; break; } default: @@ -3497,12 +3502,11 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card, /* ensure isolation mode is "none" */ card->options.isolation = ISOLATION_MODE_NONE; - rc = 0; break; } } qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd); - return rc; + return 0; } static int qeth_setadpparms_set_access_ctrl(struct qeth_card *card, @@ -3744,15 +3748,10 @@ int qeth_snmp_command(struct qeth_card *card, char __user *udata) /* skip 4 bytes (data_len struct member) to get req_len */ if (copy_from_user(&req_len, udata + sizeof(int), sizeof(int))) return -EFAULT; - ureq = kmalloc(req_len+sizeof(struct qeth_snmp_ureq_hdr), GFP_KERNEL); - if (!ureq) { + ureq = memdup_user(udata, req_len + sizeof(struct qeth_snmp_ureq_hdr)); + if (IS_ERR(ureq)) { QETH_CARD_TEXT(card, 2, "snmpnome"); - return -ENOMEM; - } - if (copy_from_user(ureq, udata, - req_len + sizeof(struct qeth_snmp_ureq_hdr))) { - kfree(ureq); - return -EFAULT; + return PTR_ERR(ureq); } qinfo.udata_len = ureq->hdr.data_len; qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL); @@ -3971,6 +3970,7 @@ retriable: else goto retry; } + card->read_or_write_problem = 0; rc = qeth_mpc_initialize(card); if (rc) { QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc); @@ -4353,16 +4353,18 @@ static void qeth_core_remove_device(struct ccwgroup_device *gdev) struct qeth_card *card = dev_get_drvdata(&gdev->dev); QETH_DBF_TEXT(SETUP, 2, "removedv"); - if (card->discipline.ccwgdriver) { - card->discipline.ccwgdriver->remove(gdev); - qeth_core_free_discipline(card); - } if (card->info.type == QETH_CARD_TYPE_OSN) { qeth_core_remove_osn_attributes(&gdev->dev); } else { qeth_core_remove_device_attributes(&gdev->dev); } + + if (card->discipline.ccwgdriver) { + card->discipline.ccwgdriver->remove(gdev); + qeth_core_free_discipline(card); + } + debug_unregister(card->debug); write_lock_irqsave(&qeth_core_card_list.rwlock, flags); list_del(&card->list); diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index 2eb022ff261..42fa783a70c 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -411,7 +411,7 @@ static ssize_t qeth_dev_layer2_store(struct device *dev, if (!card) return -EINVAL; - mutex_lock(&card->conf_mutex); + mutex_lock(&card->discipline_mutex); if (card->state != CARD_STATE_DOWN) { rc = -EPERM; goto out; @@ -433,6 +433,7 @@ static ssize_t qeth_dev_layer2_store(struct device *dev, if (card->options.layer2 == newdis) goto out; else { + card->info.mac_bits = 0; if (card->discipline.ccwgdriver) { card->discipline.ccwgdriver->remove(card->gdev); qeth_core_free_discipline(card); @@ -445,7 +446,7 @@ static ssize_t qeth_dev_layer2_store(struct device *dev, rc = card->discipline.ccwgdriver->probe(card->gdev); out: - mutex_unlock(&card->conf_mutex); + mutex_unlock(&card->discipline_mutex); return rc ? rc : count; } diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 32d07c2dcc6..830d63524d6 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -860,8 +860,6 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev) unregister_netdev(card->dev); card->dev = NULL; } - - qeth_l2_del_all_mc(card); return; } @@ -935,6 +933,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) enum qeth_card_states recover_flag; BUG_ON(!card); + mutex_lock(&card->discipline_mutex); mutex_lock(&card->conf_mutex); QETH_DBF_TEXT(SETUP, 2, "setonlin"); QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); @@ -1012,6 +1011,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); out: mutex_unlock(&card->conf_mutex); + mutex_unlock(&card->discipline_mutex); return 0; out_remove: @@ -1025,6 +1025,7 @@ out_remove: else card->state = CARD_STATE_DOWN; mutex_unlock(&card->conf_mutex); + mutex_unlock(&card->discipline_mutex); return rc; } @@ -1040,6 +1041,7 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev, int rc = 0, rc2 = 0, rc3 = 0; enum qeth_card_states recover_flag; + mutex_lock(&card->discipline_mutex); mutex_lock(&card->conf_mutex); QETH_DBF_TEXT(SETUP, 3, "setoffl"); QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *)); @@ -1060,6 +1062,7 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev, /* let user_space know that device is offline */ kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE); mutex_unlock(&card->conf_mutex); + mutex_unlock(&card->discipline_mutex); return 0; } diff --git a/drivers/s390/net/qeth_l3.h b/drivers/s390/net/qeth_l3.h index 8447d233d0b..e705b27ec7d 100644 --- a/drivers/s390/net/qeth_l3.h +++ b/drivers/s390/net/qeth_l3.h @@ -64,5 +64,6 @@ void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions, const u8 *); int qeth_l3_set_large_send(struct qeth_card *, enum qeth_large_send_types); int qeth_l3_set_rx_csum(struct qeth_card *, enum qeth_checksum_types); +int qeth_l3_is_addr_covered_by_ipato(struct qeth_card *, struct qeth_ipaddr *); #endif /* __QETH_L3_H__ */ diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 61d348e5192..e22ae248f61 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -195,7 +195,7 @@ static void qeth_l3_convert_addr_to_bits(u8 *addr, u8 *bits, int len) } } -static int qeth_l3_is_addr_covered_by_ipato(struct qeth_card *card, +int qeth_l3_is_addr_covered_by_ipato(struct qeth_card *card, struct qeth_ipaddr *addr) { struct qeth_ipato_entry *ipatoe; @@ -3354,6 +3354,8 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev) { struct qeth_card *card = dev_get_drvdata(&cgdev->dev); + qeth_l3_remove_device_attributes(&cgdev->dev); + qeth_set_allowed_threads(card, 0, 1); wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); @@ -3367,7 +3369,6 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev) card->dev = NULL; } - qeth_l3_remove_device_attributes(&cgdev->dev); qeth_l3_clear_ip_list(card, 0, 0); qeth_l3_clear_ipato_list(card); return; @@ -3380,6 +3381,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) enum qeth_card_states recover_flag; BUG_ON(!card); + mutex_lock(&card->discipline_mutex); mutex_lock(&card->conf_mutex); QETH_DBF_TEXT(SETUP, 2, "setonlin"); QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); @@ -3461,6 +3463,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); out: mutex_unlock(&card->conf_mutex); + mutex_unlock(&card->discipline_mutex); return 0; out_remove: card->use_hard_stop = 1; @@ -3473,6 +3476,7 @@ out_remove: else card->state = CARD_STATE_DOWN; mutex_unlock(&card->conf_mutex); + mutex_unlock(&card->discipline_mutex); return rc; } @@ -3488,6 +3492,7 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, int rc = 0, rc2 = 0, rc3 = 0; enum qeth_card_states recover_flag; + mutex_lock(&card->discipline_mutex); mutex_lock(&card->conf_mutex); QETH_DBF_TEXT(SETUP, 3, "setoffl"); QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *)); @@ -3508,6 +3513,7 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, /* let user_space know that device is offline */ kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE); mutex_unlock(&card->conf_mutex); + mutex_unlock(&card->discipline_mutex); return 0; } diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c index fb5318b30e9..67cfa68dcf1 100644 --- a/drivers/s390/net/qeth_l3_sys.c +++ b/drivers/s390/net/qeth_l3_sys.c @@ -479,6 +479,7 @@ static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev_get_drvdata(dev); + struct qeth_ipaddr *tmpipa, *t; char *tmp; int rc = 0; @@ -497,8 +498,21 @@ static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev, card->ipato.enabled = (card->ipato.enabled)? 0 : 1; } else if (!strcmp(tmp, "1")) { card->ipato.enabled = 1; + list_for_each_entry_safe(tmpipa, t, card->ip_tbd_list, entry) { + if ((tmpipa->type == QETH_IP_TYPE_NORMAL) && + qeth_l3_is_addr_covered_by_ipato(card, tmpipa)) + tmpipa->set_flags |= + QETH_IPA_SETIP_TAKEOVER_FLAG; + } + } else if (!strcmp(tmp, "0")) { card->ipato.enabled = 0; + list_for_each_entry_safe(tmpipa, t, card->ip_tbd_list, entry) { + if (tmpipa->set_flags & + QETH_IPA_SETIP_TAKEOVER_FLAG) + tmpipa->set_flags &= + ~QETH_IPA_SETIP_TAKEOVER_FLAG; + } } else rc = -EINVAL; out: |